Commit Graph
4557 Commits
Author SHA1 Message Date
Daan De Meyer 933a45835f basic/math-util: drop libm where possible
- test-random-util is reworked to not use sqrt()
- pretty-print.c inlines ceil() so libm doesn't have
  to be linked into libshared
- We add fno-math-errno to allow inlining of more math
  functions by not requiring standard math functions to 
  set errno on invalid input.
2026-05-20 16:32:22 +02:00
Daan De Meyer d52c8f2068 tree-wide: Replace exp10() with our own impl
exp10() has a symbol version > 2.34 on latest glibc. To allow 
dropping our baseline required glibc runtime version to <= 2.34, 
let's add our own version to prevent pulling in the newer symbol 
from glibc.
2026-05-20 11:03:27 +02:00
Yu Watanabe 27e0bba966 core: introduce varlink io.systemd.Job interface (#42104)
Methods:

- `io.systemd.Job.List` — list all queued jobs or look up by `id`/`unit`
name, with streaming support. Uses context/runtime split: `JobContext`
(Unit, JobType) and `JobRuntime` (Id, State, Result,
ActivationDetails). Follows the same SELinux and parameter-conflict
patterns as `io.systemd.Unit.List`.
- `io.systemd.Job.Cancel` — cancel a specific job by ID, with SELinux
and polkit authorization.
- `io.systemd.Job.ClearAll` — cancel all pending jobs, with SELinux and
polkit authorization.
2026-05-20 17:22:18 +09:00
Yu Watanabe ce260a112f sd-bus: add depth limit to message_skip_fields() to prevent stack overflow (#42164)
`message_skip_fields()` recursively processes D-Bus variant types in
message header fields with no depth limit. A crafted message with deeply
nested variants can cause unbounded recursion and overflow the stack.

Add a `depth` parameter checked against `BUS_CONTAINER_DEPTH` (128),
matching the limit already enforced by the public
`sd_bus_message_skip()` API. All recursive call sites pass `depth + 1`,
and the top-level caller in `message_parse_fields()` passes `0`.
2026-05-20 10:22:32 +09:00
TristanInSec ddb221c3b2 test: add test for variant recursion depth limit in message_skip_fields()
Craft a raw D-Bus message with an unknown header field containing
BUS_CONTAINER_DEPTH+1 nested variants and verify that message parsing
rejects it with -EBADMSG rather than recursing until stack overflow.
2026-05-19 17:33:11 -04:00
TristanInSec 9b21738498 sd-bus: add depth limit to message_skip_fields() to prevent stack overflow
message_skip_fields() recurses for each nested variant ('v') type in
D-Bus message header fields. A crafted message with deeply nested
variants (e.g., a variant containing a variant containing a variant...)
causes unbounded stack growth, leading to stack overflow and crash.

Add a depth parameter that increments on each recursive call and
rejects messages exceeding BUS_CONTAINER_DEPTH with -EBADMSG. This
matches the existing depth limits enforced elsewhere in the sd-bus
message processing (e.g., bus_message_enter_container).
2026-05-19 17:33:06 -04:00
Daan De Meyer d158595dc7 tree-wide: move static dl handles into their dlopen_*() functions
Each dlopen_*() wrapper kept its dl handle as a file-scope
'static void *xxx_dl = NULL;' even though only the wrapper itself
ever referenced it. Move each one inside the corresponding function
so its scope matches its actual use, leaving the rest of each
translation unit free of the unused file-scope name.

In pcre2-util.c the assert(pcre2_dl) in pattern_matches_and_log()
becomes assert(sym_pcre2_match), which carries the same invariant
(pattern_compile_and_log() ran dlopen_pcre2()).
2026-05-19 19:22:06 +00:00
Daan De Meyer bdbcff6530 Various dlopen/linking cleanups from #42100 (#42166)
- **bpf-util: rename from bpf-dlopen, unify version-specific symbol
handling**
- **cryptsetup: dlopen libcryptsetup in tokens**
- **tree-wide: dlopen libpam in pam plugins**
- **test-bus-marshal: dlopen() glib and libdbus instead of linking
directly**
- **lock-util: Simplify timeout for lock_generic_with_timeout()**
- **color-util: simplify hsv_to_rgb, fix rgb_to_hsv negative-hue wrap**
- **tree-wide: Use our own macros instead of fabs()/fmax()/fmin()**
- **locale-util: dlopen() libintl instead of linking against it**
- **home: Use log2u64() over log2()**
- **meson: drop libdl, threads, and librt dependencies**
- **libc: Use dlsym() from a constructor instead of weak symbols**
- **libc: Make sure C23 versions of strtol(), sscanf() are not used**
2026-05-19 08:54:27 +02:00
Daan De Meyer a14adac423 meson: drop libdl, threads, and librt dependencies
Our baseline glibc is 2.34, which merged libdl, libpthread (the
dependency('threads') target), and librt into libc. Empty .so/.a stubs
remain for backward compatibility with old binaries, but new builds
resolve dl_*, pthread_*, mq_*, timer_*, etc. directly from libc.
On musl the same libraries are likewise empty stubs.

Drop the libdl, threads, and librt entries from every meson.build, and
remove the now-stale 'Libs.private: -lrt -pthread' from libudev.pc.in
since both flags resolve to empty link-time stubs on glibc 2.34+ and
musl.

Verified with readelf -d that libsystemd.so, libudev.so, and systemd no
longer carry DT_NEEDED entries for libdl/libpthread/librt.
2026-05-18 21:17:38 +00:00
Daan De Meyer b2bfe5b474 tree-wide: Use our own macros instead of fabs()/fmax()/fmin()
To make this work, ABS() is made generic so it also works on
floats and doubles.

While at it, fold the __ABS_INTEGER indirection and the
assert_cc(sizeof(long long) == sizeof(intmax_t)) away. The previous
form switched between __builtin_llabs (clang) and __builtin_imaxabs
(gcc), with the assert keeping the two paths behaviorally identical
on every platform we build for. imaxabs was originally chosen because
intmax_t is conceptually the widest signed integer type the platform
exposes, but the _Generic ABS already casts to (long long) before the
call, so the extra width imaxabs could in theory carry was being
narrowed away immediately anyway. With both paths collapsed to
__builtin_llabs((long long) (a)), the size relationship between
long long and intmax_t is no longer relevant.

Also add explicit unsigned long long / unsigned long / unsigned int
cases that pass the argument through unchanged. The previous default
branch cast unsigned values to (long long); for values above LLONG_MAX
this reinterprets them as negative, and __builtin_llabs(LLONG_MIN) is
UB. Unsigned values are already non-negative, so passing them through
is both correct and avoids the narrowing. Smaller unsigned types
(unsigned char, unsigned short) still go through the default branch
but promote to int first and fit in long long losslessly.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 21:17:38 +00:00
Daan De Meyer 0af0161f55 test-bus-marshal: dlopen() glib and libdbus instead of linking directly
The test only uses 9 symbols (5 from glib, 4 from libdbus) for its
interop checks; dlopen them at runtime so the binary no longer carries a
hard link-time dependency on either library. Headers are still pulled in
through the *_cflags partial dependencies for the type declarations.

While we're at it, drop the compat glue for glib 2.36 which is long obsolete
at this point.
2026-05-18 21:17:38 +00:00
Lennart Poettering 914c41a774 test: add unit test for new sd-json functionality 2026-05-18 10:39:04 +01:00
Ivan Kruglov e4b5bdb9b3 json-util: add JSON_BUILD_PAIR_ENUM_NON_EMPTY macro
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-18 00:33:52 -07:00
Ivan Kruglov 2d4f2441f5 json-util: add json_dispatch_job_id() dispatcher for job IDs
Job IDs are uint32_t values that are always >= 1 (the manager's ID counter starts at 1 and wraps from UINT32_MAX back to 1, never assigning 0). Add a dedicated dispatch function that validates this constraint, rejecting 0 and treating null as "unset" (0).

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-18 00:33:47 -07:00
Lennart Poettering 321df4885c sd-json: add sd_json_parse_fd() helper 2026-05-18 08:51:09 +02:00
Lennart Poettering 584ee9ffe5 sd-json: add SD_JSON_PARSE_SEEK0 flag 2026-05-18 08:51:09 +02:00
Yu Watanabe 247e4caa3c sd-device: also add device_get_sysattr_streq() 2026-05-18 02:55:56 +09:00
Yu Watanabe 1e39d3eb08 sd-device: also add device_get_sysattr_u8() and _u16() 2026-05-18 02:55:56 +09:00
Yu Watanabe 3c230737f5 sd-device: use macro to define device_get_sysattr_int() and friends 2026-05-18 02:55:56 +09:00
Yu Watanabe dbfe8b162b test: add test cases for device_get_sysattr_int() and friends 2026-05-18 02:55:56 +09:00
Yu Watanabe 532276524f sd-device: rename argument names for storing result
When a function takes only one argument for storing result, the argument
is not necessary to be named as ret_xyz, but ret should be enough.
2026-05-18 02:55:56 +09:00
Yu Watanabe 13ce62caba sd-device: use device_get_sysattr_safe_string()
The read value are exposed by sd_device_get_subsystem() and friends.
Hence, it is better to filter invalid characters.
Of course, these should be always safe unless the kernel is buggy.
But, just for safety.

Note, even if uevent file contains invalid characters, then
device_read_uevent_file() should succeed without parsing the contents.
The caller should fail later with a proper error code if a necessary
field is unset. E.g. sd_device_get_ifindex() should still return -ENOENT
even when uevent file contains an invalid characters.
2026-05-18 02:55:56 +09:00
Yu Watanabe 0341058ee6 sd-device: introduce device_get_sysattr_safe_string()
This introduce a helper function that verifies read sysattr value.
Some sysattr value may come from firmware, and kernel may expose unsafe
string. The introduced function should be used when we use the result as
a string.
2026-05-18 02:55:56 +09:00
Yu Watanabe 8e8d3a22b2 sd-device: use string_is_safe() at one more place 2026-05-18 01:57:33 +09:00
Yu Watanabe 42c689f63d sd-device: logs about refused property
Follow-up for a62cd5a153.
2026-05-18 01:55:10 +09:00
Yu Watanabe 5768f1dd6f Final batch of conversions to option and verb macros (#42127) 2026-05-17 03:50:48 +09:00
Zbigniew Jędrzejewski-Szmek cf88903637 tree-wide: get rid of most uses of ALIGN_PTR
This bothered me for a while, but I didn't think too much about it and just
copied the existing usage pattern. But it really doesn't make sense. We expect
the compiler to align the section properly. But if it didn't align it, applying
alignment after the fact would just cause our pointer to point to the middle
of the structure. That'd be even worse than a misaligned pointer.

Similarly, when doing pointer arithmetic, p++ should really result in a value
with the appropriate alignment. This is the basic principle of C pointer
addition. So we really shouldn't try to adjust the pointer ourselves. At most,
we can assert that it is indeed aligned in tests.
2026-05-16 18:32:14 +02:00
Yu Watanabe ace3a7b500 udev,sd-device: drop old database support (#40801)
Closes #40776.
2026-05-16 08:26:16 +09:00
наб 0304ba263a varlink: vl_error_MethodNotFound: an method 2026-05-15 17:55:20 +02:00
наб 6fbb3c55f1 varlink: MethodNotImplemented: drop extraneous dot 2026-05-15 17:54:42 +02:00
Yu Watanabe 1fdcf3ee40 sd-device: drop support of udev database version 0
The udev database versioning has been introduced in v247, which is
released on 2020-11-26.
Let's drop the support of old udev database.
2026-05-15 13:47:45 +02:00
Yu Watanabe c33a9eb858 sd-journal: update comments 2026-05-15 15:04:02 +09:00
我超厉害 a03f3af3e3 sd-device: use ERRNO_IS_NEG_DEVICE_ABSENT() for device-id load failures (#41764)
Device enumeration may encounter transient errors such as ENXIO when devices
appear or disappear concurrently. These conditions represent expected "device absent"
races and should be treated uniformly across the enumeration logic.

This change replaces the ENODEV-specific check with ERRNO_IS_NEG_DEVICE_ABSENT(),
ensuring that all expected disappearance conditions are handled consistently.
Unexpected errors are still propagated, while expected races are ignored without
aborting the enumeration.
2026-05-15 02:51:29 +09:00
Yu Watanabe d6c79c13ff Implement Socket Context/Runtime for io.systemd.Unit.List (#42057)
The PR implements the following objects + tests for
io.systemd.Unit.List:
- SocketContext
- Socket Runtime

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
* https://github.com/systemd/systemd/pull/39391
* https://github.com/systemd/systemd/pull/41980
2026-05-14 23:29:47 +09:00
Daan De Meyer f795d54591 libc,shared: detect newer library symbols at runtime
For libc syscall wrappers (pidfd_open, fsopen, openat2, etc.) we previously
gated the calls behind build-time HAVE_* checks. Replace these with shim
functions in src/libc/ that fall back to the raw syscall at runtime when the
loaded glibc lacks the symbol. The infrastructure lives in src/libc/libc-shim.h:
DEFINE_SYSCALL_SHIM falls back to a direct syscall, DEFINE_LIBC_SHIM returns
ENOSYS (for posix_spawn-family helpers that have no corresponding syscall), and
DEFINE_LIBC_ERRNO_SHIM sets errno=ENOSYS and returns -1 (for read/write-style
helpers). The weak reference to the libc symbol is bound via __asm__(\"name\")
rename so the bare libc identifier never appears as a C token — this avoids
both #undef boilerplate against override-header redirects and the resulting
-Wredundant-decls warning. Drop the corresponding cc.has_function() loop from
meson.build.

For optional libraries (libcryptsetup, libdw, libarchive), drop the per-symbol
HAVE_* checks. Always declare the prototypes, suppressing the redundant-decl
warnings via DISABLE_WARNING_REDUNDANT_DECLS and NOLINT, and resolve the symbols
after the main dlopen via a new DLSYM_OPTIONAL() helper that only assigns on
success. libcryptsetup's crypt_set_keyring_to_link / crypt_token_set_external_path
and libarchive's *_is_set wrappers use fallback functions as their pointer
initializers (returning -ENOSYS and 0 respectively), so call sites can invoke
the symbol unconditionally and just check for -ENOSYS where the \"not supported\"
distinction matters.

The same shim treatment applies to pidfd_spawn / posix_spawnattr_setcgroup_np
(src/libc/spawn.c) and epoll_pwait2 (src/libc/epoll.c), with corresponding
override headers in src/include/override/spawn.h and
src/include/override/sys/epoll.h. posix_spawn_wrapper() in process-util.c and
epoll_wait_usec() in sd-event.c now detect ENOSYS in the return value instead
of checking the function pointer, falling back to plain posix_spawn() and
epoll_wait() respectively. coredump-config and coredump-submit get a
dlopen_dw_has_dwfl_set_sysroot() helper. The kexec arch gate now uses
defined(__NR_kexec_file_load) directly; pidfd.h uses __has_include_next() to
decide whether to pull in glibc's header.

This lets binaries built against newer glibc / libcryptsetup / libdw /
libarchive headers still load and run on older targets where these symbols are
absent.
2026-05-13 10:29:50 +02:00
Frantisek Sumsal 7cecff8c99 sd-bus: handle non-string keys in dictionaries in JSON dump
JSON only supports string keys in objects, but D-Bus specification is a
bit more lenient and allows dict entries to have any basic type as key.
Let's stringify allowed non-string keys so that we can represent them as
JSON objects.

Relevant snippet from the D-Bus specification:

  A DICT_ENTRY works exactly like a struct, but rather than parentheses
  it uses curly braces, and it has more restrictions. The restrictions
  are: it occurs only as an array element type; it has exactly two
  single complete types inside the curly braces; the first single
  complete type (the "key") must be a basic type rather than a container
  type. Implementations must not accept dict entries outside of arrays,
  must not accept dict entries with zero, one, or more than two fields,
  and must not accept dict entries with non-basic-typed keys. A dict
  entry is always a key-value pair.

Resolves: #32904
2026-05-13 07:50:32 +09:00
Daan De Meyer d0234450b6 json-stream: tolerate truncated SCM_RIGHTS on inbound messages
When an LSM (e.g. SELinux) denies an fd transfer or the receiver hits
RLIMIT_NOFILE, the kernel drops the fd(s) from the SCM_RIGHTS cmsg and
sets MSG_CTRUNC on the recvmsg(). recvmsg_safe() turns that into
-ECHRNG, which causes json_stream_read() to discard the data bytes
that were nevertheless received and the varlink server to silently
tear down the connection — leaving the caller waiting for a reply
that never comes.

Inline the recvmsg() call instead and, on MSG_CTRUNC, drop the partial
fds but keep the message data. The method handler will surface a clean
-ENXIO when it tries to peek the missing fd, which sd-varlink wraps as
io.systemd.System for the peer, instead of a hang. This matches the
recent sd-bus fix in 6c8de404c9 ('sd-bus: allow receiving messages with
MSG_CTRUNC set').
2026-05-12 18:54:28 +02:00
Ivan Kruglov 5f1c10e7bc json: add JSON_BUILD_PAIR_FINITE_USEC_NON_ZERO()
Like JSON_BUILD_PAIR_FINITE_USEC() but also suppresses zero values. Useful for usec_t fields where zero means "disabled" or "not configured" (e.g. KeepAliveTimeUSec, DeferAcceptUSec, RandomizedDelayUSec) as opposed to timeout fields where zero would be unusual and worth showing.
2026-05-12 08:51:26 -07:00
Zbigniew Jędrzejewski-Szmek 88d7e44392 Add json_variant_unref_and_replace and use it where appropriate
JSON_VARIANT_REPLACE is similar, but doesn't try to nullify the second
arg, so it can be used with an inline expression.
2026-05-08 11:36:43 +02:00
Zbigniew Jędrzejewski-Szmek 62a489fbf9 tree-wide: rename unref_and_replace_full to unref_and_replace_new_ref
We have a number of *_unref_and_replace macros. One could think that
they are like the various free_and_replace variants, but they actually
create a new ref to the passed object. The free_and_replace variants
take ownership of the argument. This inconsistency is surprising. Rename
all those functions to have "_new_ref" at the end to make the difference
clear.
2026-05-08 11:14:13 +02:00
Christian Brauner fad897b8bf shared: add storage_acquire_volume() helper
storagectl's mount.storage helper bundles "open StorageProvider socket
+ Acquire() + dispatch reply + take fd" inline. Future consumers
(systemd-vmspawn boot-time --bind-volume, machinectl bind-volume) need
the same dance.

Factor it into a single libshared helper that takes the Acquire()
parameters by value and returns the fd plus the actual type/read-only
flags. Library code, so no logging — varlink errors are surfaced via
sd_varlink_error_to_errno() and the StorageProvider error_id is
returned to the caller via reterr_error_id (caller decides how to
format messages).

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-05-06 10:30:16 +02:00
Diego Viola 5d17215c7e treewide: fix typos in the entire codebase
Signed-off-by: Diego Viola <diego.viola@gmail.com>
2026-05-05 17:22:26 +02:00
Lennart Poettering 78c66e8624 dbus-manager: limit the number of states/patterns per query (#41891)
Let's cap the number of states/patterns per query to something
reasonable, i.e. max 256 states and 4K patterns per query.

---

Also, use the env assignments limit in a couple more places.
2026-05-04 10:07:04 +02:00
Frantisek Sumsal 49c1e1bcf2 dbus: limit the number of env variables to something reasonable, vol. 2
Turns out we can utilize this limit at a couple more places, so let's
move the previously defined limit constant to env-util.h and use it to
guard a couple more D-Bus methods. Also, bump it a bit, given it's meant
to be a safety cap that can't be hit in valid scenarios.

Follow-up for 7671b43cb8.
2026-05-01 20:11:53 +02:00
Lennart Poettering 99ce7a0770 options: get rid of "on_error" parameter to FOREACH_OPTION
I am really not a fan of full code lines passed to macros as parameters.
Let's get rid of the 3rd parameter of FOREACH_OPTION() hence:

1. Let's return errors just as a regular value (though a negative one),
   that can be handled via a OPTION_ERROR case statement for the switch.
   This normalizes handling of the error, just like any other event
   returned by the option parser.

2. In order to avoid exploding the amount of boilerplate in each use
   (that just propagates the error on OPTION_ERROR), let's then
   introduce an explicit FOREACH_OPTION_OR_RETURN(), that returns from
   the calling function on its own (and makes that clear in the name).

Together this cleans up, normalizes the logic and shortens the code.
2026-04-30 11:12:33 +01:00
Frantisek Sumsal 7671b43cb8 sd-json: limit the number of env variables to something reasonable
Let's start with 1024, as that should be plenty for all sane use cases.
2026-04-30 09:46:46 +02:00
Daan De Meyer 9d2f5b4611 fundamental/cleanup: add CLEANUP_ELEMENTS() and DEFINE_POINTER_ARRAY_CLEAR_FUNC()
DEFINE_POINTER_ARRAY_CLEAR_FUNC() generates a helper of the form
helper_array_clear(T *array, size_t n) that drops each element but does
not free the array itself, parallel to DEFINE_POINTER_ARRAY_FREE_FUNC()
for cases where the array has automatic storage duration.

CLEANUP_ELEMENTS() pairs with these helpers to provide a _cleanup_-like
attribute for fixed-size arrays: the bound is taken from ELEMENTSOF(),
and the helper is invoked across the elements at scope exit. Compared to
CLEANUP_ARRAY(), the storage is neither freed nor zeroed.

Migrate various logic across the tree over to the new macros.

sd-device: use DEFINE_POINTER_ARRAY_CLEAR_FUNC() for sd_device_unref_array_clear()

Replace the local device_unref_many() helper with the macro-generated
equivalent.

format-table: switch help-table arrays to CLEANUP_ELEMENTS()

Generate table_unref_array_clear() via DEFINE_POINTER_ARRAY_CLEAR_FUNC()
and convert the help-table arrays in bootctl, cryptenroll, nspawn,
repart and vmspawn to CLEANUP_ELEMENTS(). The arrays no longer need a
trailing NULL slot, so the size matches ELEMENTSOF() of the groups
array.

firewall-util: switch netlink message arrays to CLEANUP_ELEMENTS()

Generate sd_netlink_message_unref_array_clear() via
DEFINE_POINTER_ARRAY_CLEAR_FUNC() in place of the NULL-terminated
sd_netlink_message_unref_many(), and convert the two stack arrays of
sd_netlink_message pointers to CLEANUP_ELEMENTS().
2026-04-30 09:15:34 +02:00
Frantisek Sumsal 82614a4c6f sd-json,user-record: store the strv size when extending it
So strv_push_with_size() doesn't have to recalculate the size every
time.
2026-04-29 16:33:46 +02:00
Lennart Poettering e4e3ec811a volume: add an "io.systemd.StorageProvider" IPC API that is supposed to be used by vmspawn/nspawn/pid1 to provide storage volumes in a generic fashion (#41776)
BindPath= in unit files, and --bind= in nspawn/vmspawn doesn't really
cut it to connect arbitrary storage infra to it. Let's do something
about it, and implement a simple, light-weight API for acquiring an fd
to a storage volume. Benefits:

1. the interface can be implemented by anyone, connecting anything to
vmspawn/nspawn/service management
2. very lose coupling: just bind a socket into a well-known dir, done
3. mounting can happen on-demand
2026-04-29 15:51:52 +02:00
Zbigniew Jędrzejewski-Szmek a79c4fdf93 Small cleanups in sd-varlink and sd-json (#41861) 2026-04-29 15:03:00 +02:00