Commit Graph
7673 Commits
Author SHA1 Message Date
Lennart Poettering d7b6d89d90 string-util: add minor optimization to strrstr() 2026-04-17 18:32:21 +02:00
Lennart Poettering 2561159d39 string-util: add new strrstr_no_case() call 2026-04-17 18:32:20 +02:00
Lennart Poettering 023f88a6ab parse-util: add safe_atou64_full() 2026-04-17 18:32:20 +02:00
Zbigniew Jędrzejewski-Szmek 45c20448d5 basic/iovec-wrapper: use iovw_append in one more place 2026-04-17 12:25:58 +02:00
Zbigniew Jędrzejewski-Szmek 13b6ba9775 basic/iovec-wrapper: fix potential memleak on error
Also reorder the functions in the call stack order.
2026-04-17 12:19:40 +02:00
Zbigniew Jędrzejewski-Szmek 5fdc15f408 string-util: check for overflow in strrep() (#41661)
This simply mirrors the same overflow check we already have in
strrepa(), in case someone passed us a sufficiently long string.

strrep() is currently used only in tests, so this is just hardening.
2026-04-16 22:36:22 +02:00
Zbigniew Jędrzejewski-Szmek f32af5c69a basic/iovec-wrapper: add iovw_append and iovw_to_cstring
Existing iovw_append is renamed to iovw_append_iovw.
iovw_consume is made noninline.
2026-04-16 20:37:18 +02:00
Frantisek Sumsal b22daa97e1 string-util: check for overflow in strrep()
This simply mirrors the same overflow check we already have in
strrepa(), in case someone passed us a sufficiently long string.

strrep() is currently used only in tests, so this is just hardening.
2026-04-16 17:46:31 +02:00
Zbigniew Jędrzejewski-Szmek 267b16f33c basic/iovec-wrapper: drop unused code
All non-test users iovec_wrapper define the struct as a field in a
bigger structure, so we never free it individually. Let's simplify the
code and assume it is never null.
2026-04-16 17:21:56 +02:00
Ivan Kruglov 01f6d9e39f basic: resurrect unit_type_to_capitalized_string() 2026-04-14 05:37:49 -07:00
Zbigniew Jędrzejewski-Szmek 1726224b07 many: final final set of coccinelle check-pointer-deref tweaks (#41595)
I promised in https://github.com/systemd/systemd/pull/41426 that its the
final update for coccinelle pointer deref checks. However it turned out
there is this coccinelle/parsing_hacks.h that I wasn't aware of. The
file missed some important things like _cleanup_(x) that prevented
coccinelle to check a bunch of functions.

This PR adds some missing defines to the parsing_hacks.h and fixes the
missing asserts(). I apologize that its a bit long (and frankly boring)
and that I missed this earlier.

The last commit contains one small behavior change (ret in
sd_varlink_idl_parse() is now really optional) but the big one is very
mechanical.
2026-04-13 13:59:24 +02:00
Lennart Poettering 7977c14273 stat-util: always check S_ISDIR() before S_ISLNK()
Check S_ISDIR() before S_ISLINK() for all stat_verify_xyz() helpers
first, where we check them. Just to ensure we systematically return the
same errors.
2026-04-13 13:20:43 +02:00
Lennart Poettering aa0da09127 stat-util: also add stat_verify_char() and use it everywhere 2026-04-13 13:20:43 +02:00
Lennart Poettering 8e0756c0b5 tree-wide: use stat_verify_regular() more 2026-04-13 13:20:43 +02:00
Lennart Poettering bda7e91337 stat-util: also introduce stat_verify_block() and use it everywhere 2026-04-13 13:20:43 +02:00
Lennart Poettering 7f2410deb1 stat-util: add shortcut for fd_verify_symlink()
We have a similar shortcut in the other fd_verify_xyz() calls, let's add
it here too, just for completion's sake.
2026-04-13 13:20:43 +02:00
Lennart Poettering 596c0a259d tree-wide: make more use of stat_verify_device_node() 2026-04-13 13:20:43 +02:00
Lennart Poettering 6b0a3ef8c7 stat-util: introduce a common (stat|fd)_verify_regular_or_block() helper
We already had one in repart.c, let's generalize it, and use it
everywhere.
2026-04-13 13:20:42 +02:00
Zbigniew Jędrzejewski-Szmek d091b0dd6a journal: limit decompress_blob() output to DATA_SIZE_MAX (#41604)
We already have checks in place during compression that limit the data
we compress, so they shouldn't decompress to anything larger than
DATA_SIZE_MAX unless they've been tampered with. Let's make this
explicit and limit all our decompress_blob() calls in journal-handling
code to that limit.

One possible scenario this should prevent is when one tries to open and
verify a journal file that contains a compression bomb in its payload:

```
$ ls -lh test.journal
-rw-rw-r--+ 1 fsumsal fsumsal 1.2M Apr 12 15:07 test.journal

$ systemd-run --user --wait --pipe -- build-local/journalctl --verify --file=$PWD/test.journal
Running as unit: run-p682422-i4875779.service
000110: Invalid hash (00000000 vs. 11e4948d73bdafdd)
000110: Invalid object contents: Bad message
File corruption detected at /home/fsumsal/repos/@systemd/systemd/test.journal:272 (of 1249896 bytes, 0%).
FAIL: /home/fsumsal/repos/@systemd/systemd/test.journal (Bad message)
          Finished with result: exit-code
Main processes terminated with: code=exited, status=1/FAILURE
               Service runtime: 48.051s
             CPU time consumed: 47.941s
                   Memory peak: 8G (swap: 0B)
```
Same could be, in theory, possible with just `journalctl --file=`, but
the reproducer would be a bit more complicated (haven't tried it, yet).

Lastly, the change in journal-remote is mostly hardening, as the maximum
input size to decompress_blob() there is mandated by MHD's connection
memory limit (set to JOURNAL_SERVER_MEMORY_MAX which is 128 KiB at the
time of writing), so the possible output size there is already quite
limited (e.g. ~800 - 900 MiB for xz-compressed data).
2026-04-13 12:02:11 +02:00
Daan De Meyer 0a8578a6ee compress: rework decompressor_detect() on top of compression_detect_from_magic()
Replace the duplicated magic byte signatures in decompressor_detect()
with a call to the new compression_detect_from_magic() helper and use a
switch statement to initialize the appropriate decompression context.
2026-04-13 11:13:04 +02:00
Lennart Poettering e700d5134d time-util: encode our assumption that clock_gettime() never can return 0 or USEC_INFINITY
We generally assume that valid times returned by clock_gettime() are > 0
and < USEC_INFINITY. If this wouldn't hold all kinds of things would
break, because we couldn't distuingish our niche values from regular
values anymore.

Let's hence encode our assumptions in C, already to help static
analyzers and LLMs.

Inspired by: https://github.com/systemd/systemd/pull/41601#pullrequestreview-4094645891
2026-04-13 08:52:43 +02:00
Frantisek Sumsal 2cda5f6169 compress: limit the output to dst_max bytes with LZ4 if set
We already do that with other algorithms, so let's make
decompress_blob_lz4() consistent with the rest.
2026-04-12 16:28:15 +02:00
Michael Vogt bd141bd818 many: fix remaining check-pointer-deref issues
The updated parsing_hacks.h file uncovered a bunch of extra
things that the check-pointer-deref coccinelle script flags.

This commit fixes them to make the tree check-pointer-deref clean.
2026-04-12 15:27:15 +02:00
Luca Boccassi ff102359b7 uid-range: add assert to prevent underflow in coalesce loop
Coverity flags range->n_entries - j as a potential underflow
in the memmove size calculation. Add assert(range->n_entries > 0)
before decrementing n_entries, which holds since the loop condition
guarantees j < n_entries.

CID#1548015

Follow-up for 8dcc66cefc
2026-04-12 13:24:50 +01:00
Zbigniew Jędrzejewski-Szmek 5cd61c1330 Define array cleanup funcs through macros (#41559) 2026-04-10 21:45:14 +02:00
Zbigniew Jędrzejewski-Szmek bbc6af9ce3 Add DEFINE_POINTER_ARRAY_FREE_FUNC and conf_file_free_array
As mentioned in the grandfather commit, I want to use the _many
suffix for freeing of the contents of an array, so the functions
to free the array to get the suffix _array.
2026-04-10 15:08:02 +02:00
Lennart Poettering 554ba32d30 report: add cgroup metrics in a separate varlink service (#41489)
Add CpuUsage, MemoryUsage, IOReadBytes, IOReadOperations, and
TasksCurrent in a standalone socket-activated varlink service. These
metrics are gathered from the kernel via cgroup files and PID1's only
role is mapping unit names to cgroup paths — a separate process can
query PID1 once for that mapping and then read the cgroup files
directly, minimizing PID1 involvement.

The new systemd-report-cgroup-metrics service listens at
/run/systemd/report/io.systemd.CGroup and exposes:
  - io.systemd.CGroup.CpuUsage
  - io.systemd.CGroup.IOReadBytes
  - io.systemd.CGroup.IOReadOperations
  - io.systemd.CGroup.MemoryUsage (with type=current/available/peak)
  - io.systemd.CGroup.TasksCurrent

This is spun out of #41078 and based on top of it. Will rebase once
that's merged.
2026-04-10 12:10:06 +02:00
Yaping Li 6fe4a16f36 cgroup-util: add cg_get_keyed_attribute_uint64() helper
Multiple callers of cg_get_keyed_attribute() follow the same pattern of
reading a single keyed attribute and then parsing it as uint64_t with
safe_atou64(). Add a helper that combines both steps.

Convert all existing single-key + uint64 call sites in cgtop, cgroup.c,
and oomd-util.c to use the new helper.
2026-04-09 14:45:05 -07:00
Daan De Meyer 594659da06 core: Add I/O pressure support 2026-04-09 22:47:10 +02:00
Daan De Meyer 316d17fcbd core: Add support for CPU pressure notifications
Works the same way as memory pressure notifications. Code is refactored
to work on enum arrays to reduce duplication.
2026-04-09 22:47:10 +02:00
Daan De Meyer b3bb4fefde test-mempress: Support unprivileged operation 2026-04-09 22:47:10 +02:00
Daan De Meyer f08796065d compress: consolidate all compression into compress.c with dlopen
Move the push-based streaming compression API from import-compress.c
into compress.c and delete import-compress.c/h. This consolidates all
compression code in one place and makes all compression libraries
(liblzma, liblz4, libzstd, libz, libbz2) runtime-loaded via dlopen
instead of directly linked.

Introduce opaque Compressor/Decompressor types backed by a heap-
allocated struct defined only in compress.c, keeping all third-party
library headers out of compress.h.

Rewrite the per-codec fd-to-fd stream functions as thin wrappers around
the push API via generic compress_stream()/decompress_stream() taking a
Compression type parameter. Integrate LZ4 into this framework using the
LZ4 Frame API, eliminating all LZ4 special-casing.

Extend the Compression enum with COMPRESSION_GZIP and COMPRESSION_BZIP2
and add the corresponding blob, startswith, and stream functions for
both.

Rename the ImportCompress types and functions: ImportCompressType becomes
the existing Compression enum, ImportCompress becomes Compressor (with
Decompressor typedef), and all import_compress_*/import_uncompress_*
become compressor_*/decompressor_*. Rename dlopen_lzma() to dlopen_xz()
for consistency. Make compression_to_string() return lowercase by
default.

Add INT_MAX/UINT_MAX overflow checks for LZ4, zlib, and bzip2 blob
functions where the codec API uses narrower integer types than our
uint64_t parameters.

Migrate test-compress.c and test-compress-benchmark.c to the TEST()
macro framework, new assertion macros, and codec-generic loops instead
of per-codec duplication.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 22:39:11 +02:00
noxiouz 9bd72b612b compress: write sparse files when decompressing to regular files
Core dumps are often very sparse, containing large zero-filled regions
whose actual disk usage can be significantly reduced by preserving
holes. Previously, decompress_stream() always wrote dense output,
expanding all zero regions into allocated disk blocks.

Each decompression backend (xz, lz4, zstd) now auto-detects whether the
output fd is suitable for sparse writes via a shared should_sparse()
helper. The check requires both S_ISREG (regular file) and !O_APPEND,
since O_APPEND causes write() to ignore the file position set by
lseek(), which would collapse the holes and corrupt the output. For
pipes, sockets, and append-mode files, dense writes are preserved via
loop_write_full() with USEC_INFINITY timeout, matching the original
behavior. After sparse decompression, finalize_sparse() sets the final
file size to account for any trailing holes.

This is transparent to callers — all public signatures are unchanged.
coredumpctl benefits automatically:
- coredumpctl debug: temp file in /var/tmp is now sparse
- coredumpctl dump -o file: output file is now sparse
- coredumpctl dump > file: redirected stdout is now sparse
- coredumpctl dump | ...: pipe output unchanged (dense)
- coredumpctl dump >> file: append mode, falls back to dense

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-developed-by: Codex (GPT-5) <noreply@openai.com>
2026-04-08 23:44:23 +01:00
Nandakumar Raghavan 8a8f22f1d8 tmpfiles: skip redundant label writes to avoid unnecessary timestamp changes
When systemd-tmpfiles processes a 'z' (relabel) entry, fd_set_perms()
unconditionally calls label_fix_full() even when mode, owner, and group
already match. This causes setfilecon_raw() (SELinux) or xsetxattr() (SMACK)
to write the security label even if it is already correct, which on some
kernels updates the file's timestamps unnecessarily.

Fix this by comparing the current label with the desired label before
writing, and skipping the write when they already match. This is consistent
with how fd_set_perms() already skips chmod/chown when the values are
unchanged.
2026-04-08 14:48:10 +01:00
Zbigniew Jędrzejewski-Szmek df45055942 tmpfiles: do not require STATX_ATIME (#41232)
Timestamps are not guaranteed to be set by `statx()`, and their presence
should not be asserted as a proxy to judge the kernel version. In
particular, `STATX_ATIME` is omitted from the return when querying a
file on a `noatime` superblock, causing spurious errors from tmpfiles:

```console
# SYSTEMD_LOG_LEVEL=debug systemd-tmpfiles --clean
<...>
Running clean action for entry X /var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-*/tmp
statx() does not support 'STATX_ATIME' mask (running on an old kernel?)
statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-prometheus-smartctl-exporter.service-GKguQK/tmp) failed: Protocol driver not attached
statx() does not support 'STATX_ATIME' mask (running on an old kernel?)
statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-systemd-logind.service-k8j52T/tmp) failed: Protocol driver not attached
statx() does not support 'STATX_ATIME' mask (running on an old kernel?)
statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-irqbalance.service-7RJkev/tmp) failed: Protocol driver not attached
statx() does not support 'STATX_ATIME' mask (running on an old kernel?)
statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-chronyd.service-8hkO5G/tmp) failed: Protocol driver not attached
statx() does not support 'STATX_ATIME' mask (running on an old kernel?)
statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-dbus-broker.service-6P6LVl/tmp) failed: Protocol driver not attached
statx() does not support 'STATX_ATIME' mask (running on an old kernel?)
statx(/var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-nginx.service-B5HX8B/tmp) failed: Protocol driver not attached
Running clean action for entry x /var/tmp/systemd-private-94cc8a77688e497f96d5b9019e66ed6f-*
Running clean action for entry q /var/tmp
statx() does not support 'STATX_ATIME' mask (running on an old kernel?)
statx(/var/tmp) failed: Protocol driver not attached
<...>
```

Additionally, refactor `dir_cleanup()` slightly for self-consistency to
make
it evident that the `NSEC_INFINITY` transformation is correct.

Fixes #41227.
2026-04-08 13:56:13 +02:00
Luca Boccassi 40eef914f3 limits-util: use MUL_SAFE for physical memory calculation
Coverity flags (uint64_t)sc * (uint64_t)ps as a potential overflow.
Use MUL_SAFE which Coverity understands via __builtin_mul_overflow.
Physical page count times page size cannot realistically overflow
uint64_t, but this makes it provable to static analyzers.

CID#1548042

Follow-up for 09bb6448ae
2026-04-08 01:28:51 +01:00
Luca Boccassi 8fa088b886 recurse-dir: add assert for MALLOC_SIZEOF_SAFE lower bound
Coverity flags MALLOC_SIZEOF_SAFE(de) - offsetof(DirectoryEntries,
buffer) as a potential underflow when MALLOC_SIZEOF_SAFE returns 0.
After a successful malloc the return value is at least as large as
the requested size, but Coverity cannot trace this. Add an assert
to establish the lower bound.

CID#1548020

Follow-up for 6393b847f4
2026-04-07 23:59:16 +01:00
Luca Boccassi 1934c65108 uid-range: add assert to silence coverity
Coverity flags range->n_entries - j - 1 and j-- as potential
underflows. Add an assert that j > 0 before decrementing, since
j starts at i + 1 >= 1 and is never decremented below its
initial value.

CID#1548015

Follow-up for 8dcc66cefc
2026-04-07 23:45:39 +01:00
Ivan Shapovalov 9c735dec67 time-util: add TIMESPEC_STORE_NSEC() 2026-04-06 22:53:00 +02:00
Daan De Meyer 3c96d1429f namespace-util: Add logging to process_is_owned_by_uid() 2026-04-06 17:13:40 +02:00
Daan De Meyer 1cc7353dcf fd-util: Add missing assert() 2026-04-03 23:22:14 +02:00
Zbigniew Jędrzejewski-Szmek 926167301c many: final set of coccinelle check-pointer-deref tweaks (#41426)
This is a followup to https://github.com/systemd/systemd/pull/41400 with
the final set of tweaks so that the new coccinelle `check-pinters-deref`
checker runs without failures.

It also includes a commit with some fixes for redundant asserts and the
final commit to make the assert() in the inner loop of qsort
POINTER_MAY_BE_NULL which will become a no-op - that is probably the
most controversial one, I hope the commit message explains the
trade-offs, I'm happy to drop it, I have no strong opinion either way.

Please see the individual commits/commit messages for more details, most
is (hopefully) relatively boring/mechanical.
2026-04-03 19:27:09 +02:00
Daan De Meyer dcce04e649 vmspawn: propagate $TERM from host into VM via kernel command line
When running in a console mode (interactive, native, or read-only),
propagate the host's $TERM into the VM by adding TERM= and
systemd.tty.term.hvc0= to the kernel command line.

TERM= is picked up by PID 1 and inherited by services on /dev/console
(such as emergency.service). systemd.tty.term.hvc0= is used by services
directly attached to /dev/hvc0 (such as serial-getty@hvc0.service) which
look up $TERM via the systemd.tty.term.<tty> kernel command line
parameter.

While systemd can auto-detect the terminal type via DCS XTGETTCAP, not
all terminal emulators implement this, so explicitly propagating $TERM
provides a more reliable experience. We skip propagation when $TERM is
unset or set to "unknown" (as is the case in GitHub Actions and some
other CI environments).

Previously this was handled by mkosi synthesizing the corresponding
kernel command line parameters externally.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 18:06:10 +02:00
Lennart Poettering 5f598576b8 network-generator: support BOOTIF= and rd.bootif=0 options (#41028)
The network generator currently supports many of the options described
by dracut.cmdline(7), but not everything.

This commit adds support for the BOOTIF= option (and the related
rd.bootif= option) used in PXE setups.

This is implemented by treating BOOTIF as a special name/placeholder
when used as an interface name, and expecting a MAC address to be set in
the BOOTIF= parameter. The resulting .network file then uses MACAddress=
in the [Match] section, instead of Name=.
2026-04-02 16:17:11 +02:00
Daan De Meyer bfdc389ea7 terminal-util: Protect errno in termios_reset() 2026-04-02 16:08:56 +02:00
Daan De Meyer 7d11e8bed7 basic/terminal-util: use getenv_terminal_is_dumb()
terminal_prepare_query() is called from terminal_get_size() which
operates on an explicitly passed fd — typically /dev/console opened
directly by PID 1 via reset_dev_console_fd(), or a service's TTY via
exec_context_apply_tty_size(). Using terminal_is_dumb() here is wrong
because it additionally checks on_tty(), which tests whether stderr is
a tty. PID 1's stderr may not be a tty (e.g. connected to kmsg or the
journal), causing terminal_is_dumb() to return true and skip the ANSI
query even though the fd we're operating on is a perfectly functional
terminal.

Use getenv_terminal_is_dumb() instead, which only checks $TERM, matching
what terminal_reset_ansi_seq() already does.

Also use it in terminal_get_cursor_position(), which also receives fds
to operate on.
2026-04-02 16:08:56 +02:00
Daan De Meyer ba10d789a8 basic/terminal-util: use non-blocking writes when sending ANSI sequences in terminal_get_size()
terminal_get_size() writes ANSI escape sequences (CSI 18 and DSR
queries) to the output fd to determine terminal dimensions. This is
called during early boot via reset_dev_console_fd() and from service
execution contexts via exec_context_apply_tty_size().

Previously, these writes used loop_write() on a blocking fd, which
could block indefinitely if the terminal is not consuming data — for
example on a serial console with flow control asserted, or a
disconnected terminal. This is the same problem that was solved for
terminal_reset_ansi_seq() in systemd/systemd#32369 by temporarily
setting the fd to non-blocking mode with a write timeout.

Apply the same pattern here: set the output fd to non-blocking in
terminal_get_size() before issuing the queries, and restore blocking
mode afterward. Change the loop_write() calls in
terminal_query_size_by_dsr() and terminal_query_size_by_csi18() to
loop_write_full() with a 100ms timeout so writes fail gracefully
instead of hanging.

Also introduce the CONSOLE_ANSI_SEQUENCE_TIMEOUT_USEC constant for all
timeouts used across all ANSI sequence writes and reads (vt_disallocate(),
terminal_reset_ansi_seq(), and the two size query functions). 333ms
is now used for all timeouts in terminal-util.c.

Also introduce a cleanup function for resetting a fd back to blocking
mode after it was made non-blocking.
2026-04-02 16:08:56 +02:00
Daan De Meyer e98a26ddc0 vmspawn: use fstab.extra credential for runtime mounts instead of kernel cmdline
Switch runtime virtiofs mount configuration from systemd.mount-extra=
kernel command line parameters to the fstab.extra credential. This
avoids consuming kernel command line space (which is limited) and
matches the approach used by mkosi.

Each mount is added as an fstab entry in the format:
  {tag} {destination} virtiofs {ro|rw},x-initrd.mount

If the user already specified a fstab.extra credential via
--set-credential= or --load-credential=, the virtiofs mount entries
are appended to it rather than conflicting.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:03:29 +02:00
Zbigniew Jędrzejewski-Szmek d0f482d342 basic/terminal-util: flush stray input when terminal query fails
Follow-up for da69848791.
2026-04-01 16:01:58 +02:00
Michal Rybecky b675582861 hmac: add comments explaining why each buffer needs erasing
As requested in review: clarify that the padding arrays carry
key material (key XOR fixed constant, trivially reversible),
not just padding bytes.
2026-04-01 15:12:46 +02:00