Commit Graph
7640 Commits
Author SHA1 Message Date
Lennart Poettering cbbaa1a335 core: implement Kill/Automount/Mount Context/Runtime for io.systemd.Unit.List (#39391)
The PR implements the following objects + tests for
`io.systemd.Unit.List`:
- `KillContext`
- `AutomountContext`
- `AutomountRuntime`
- `MountContext`
- `MountRuntime`

It's a continuation of the following PRs:
* https://github.com/systemd/systemd/pull/37432
* https://github.com/systemd/systemd/pull/37646
* https://github.com/systemd/systemd/pull/38032
* https://github.com/systemd/systemd/pull/38212
2026-04-20 22:57:21 +02:00
Lennart Poettering 4712d70669 chase: tighten flags checks in chase_and_unlinkat()
Some flags don't reasonably apply to chase_and_unlinkat() (because we
open the parent inode of an inode to delete, which is always a dir),
hence let's catch these flags when misused.

(I ran into this, and it was very confusing to debug, hence let's make
it easier)
2026-04-20 17:19:27 +02:00
Lennart Poettering ad18f634b6 parse-util: rework safe_atou64() as wrapper around safe_atou64_full()
Follow-up for: 023f88a6ab

Claude complained...
2026-04-20 12:02:54 +02:00
Frantisek Sumsal 3297add538 compress: simplify the condition a bit
Simply mirror the format we've already established in
decompress_blob_zstd().
2026-04-20 09:37:13 +02:00
Frantisek Sumsal 35eb598af2 compress: gracefully handle a truncated ZSTD frame
If a journal file contains a truncated ZSTD frame (i.e. a frame with
Frame_Content_Size > 0, but with not enough data in Data_Block),
ZSTD_decompressStream() would return a non-zero, non-error value. This
would then skip the error path in the ZSTD_isError() branch and we'd hit
the following assert:

$ build-local/journalctl -o cat --file zstd-truncated.journal
Assertion 'output.pos >= prefix_len + 1' failed at src/basic/compress.c:1236, function decompress_startswith_zstd(). Aborting.
Aborted                    (core dumped) build-local/journalctl -o cat --file zstd-truncated.journal

Let's handle this situation gracefully and return EBADMSG instead.

Also, add another journalctl invocation to the corrupted-journals test
that goes through the sd_journal_get_data() -> decompress_startswith_zstd()
code path which, among other things, covers the issue when run on the
provided journal file.
2026-04-20 09:37:13 +02:00
Christian Brauner 6548da06fc nspawn: avoid passing NULL to log_syntax() (#41712)
And a couple of other cosmetic tweaks.
2026-04-20 08:48:17 +02:00
Frantisek Sumsal 774a9f440b strxcpyx: add a paranoia check for vsnprintf()'s return value
vsnprintf() can, under some circumstances, return negative value, namely
during encoding errors when converting wchars to multi-byte characters.
This would then wreak havoc in the arithmetics we do following the
vsnprintf() call. However, since we never do any wchar shenanigans in
our code it should never happen.

Let's encode this assumption into the code as an assert(), similarly how
we already do this in other places (like strextendf_with_separator()).
2026-04-19 14:06:15 +02:00
Yu Watanabe f71dcac4dc iovec-wrapper: introduce several more helper functions 2026-04-19 06:15:54 +09:00
Yu Watanabe 6d14614f4d iovec-wrapper: rename iovw_append() to iovw_extend()
The naming is consistent with strv_extend().

This also
- introduces tiny iovw_extend_iov() wrapper,
- refuse when the source and target points to the same object,
- check the final count before extending in iovw_extend_iovw().
2026-04-19 06:02:48 +09:00
Yu Watanabe d49c509d9b iovec-wrapper: introduce iovw_concat()
This is similar to iovw_to_cstring(), but allows embedded NUL, as this
just concat multiple iovec, the result may not be a string.

Now, iovw_to_cstring() internally uses iovw_concat().
2026-04-19 05:51:05 +09:00
Yu Watanabe a4e0f04157 iovec-wrapper: introduce iovw_compare() and iovw_equal() 2026-04-19 05:51:01 +09:00
Yu Watanabe ce81c7dd74 iovec-wrapper: fix memleak in iovw_consume() when len == 0
This makes even when len == 0, the input buffer is freed.
The behavior is consistent with strv_consume() and friends.
2026-04-19 03:45:08 +09:00
Yu Watanabe b51c133a4e random-util: introduce random_bytes_allocate_iovec() helper function
It is similar to crypto_random_bytes_allocate_iovec(), but possibly
insecure.
2026-04-18 09:56:38 +02:00
Lennart Poettering 4368cc8164 Various useful helpers (#41684)
Split out of #41543.

These don't make too much sense on their own, but they also don't really
hurt. They are preparation for #41543, but in order to make things
either to review I split these four commits out, since they are not
directly part of what the PR shall achieve
2026-04-18 09:50:19 +02:00
Yu Watanabe 8bb669712e string-util: make make_cstring() take void* rather than char*
It is typically used for making C string embedded in a binary data.
Hence, the input pointer may not be char*.
2026-04-17 19:24:53 +02:00
Yu Watanabe f46ad8b4ba mountpoint-util: initialize mnt_id for name_to_handle_at(AT_HANDLE_MNT_ID_UNIQUE)
Suppress the following message:
```
$ sudo valgrind --leak-check=full build/networkctl dhcp-lease wlp59s0
==175708== Memcheck, a memory error detector
==175708== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==175708== Using Valgrind-3.26.0 and LibVEX; rerun with -h for copyright info
==175708== Command: build/networkctl status wlp59s0
==175708==
==175708== Conditional jump or move depends on uninitialised value(s)
==175708==    at 0x4BC33D1: inode_same_at (stat-util.c:610)
==175708==    by 0x4BF1972: inode_same (stat-util.h:86)
==175708==    by 0x4BF48FE: running_in_chroot (virt.c:817)
==175708==    by 0x4B16643: running_in_chroot_or_offline (verbs.c:37)
==175708==    by 0x4B175CE: _dispatch_verb_with_args (verbs.c:136)
==175708==    by 0x4B17868: dispatch_verb (verbs.c:160)
==175708==    by 0x407CBB: networkctl_main (networkctl.c:249)
==175708==    by 0x407D06: run (networkctl.c:263)
==175708==    by 0x407D39: main (networkctl.c:266)
==175708==
```
Not sure if it is an issue in valgrind or glibc, but at least there is
nothing we can do except for working around it.
2026-04-17 19:05:41 +02:00
Lennart Poettering 7e8882a96f stat-util: add vfs_free_bytes()
The casts and the right fields to multiply aren't entirely trivial,
let's add a helper for it.
2026-04-17 18:32:21 +02:00
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