Commit Graph
9757 Commits
Author SHA1 Message Date
Lennart Poettering ce72c94acc bpf-restrict-fsaccess: move STAT_DEV_TO_KERNEL into generic code
We want to reuse it when processing sock-diag messages, hence let's
generalize this.
2026-06-23 22:55:23 +02:00
Lennart Poettering cc174775f5 core: add socket xattr settings for socket unit 2026-06-23 22:55:23 +02:00
Luca Boccassi 7a713418be core: fix assertion when inactive unit pulled in by try-restart and start at the same time
With EnqueueUnitJobMany(), one anchor can collapse to NOP (inactive
unit + try-restart) while another anchor pulls that same unit in as a
regular start/restart job, leaving a NOP and a regular job in one
unit's transaction list, hitting an assert:

 #11 0x00007f3fd2a446dc in __assert_fail (assertion=<optimized out>, file=<optimized out>, line=<optimized out>,
     function=<optimized out>) at ./assert/assert.c:127
 #12 0x00007f3fd326e872 in job_type_lookup_merge (a=<optimized out>, b=<optimized out>) at ../src/core/job.c:428
 #13 0x00007f3fd32e5641 in job_type_merge_and_collapse (a=0x7ffc7dda2430, b=<optimized out>, u=0x557bb11434c0)
     at ../src/core/job.c:523
 #14 0x00007f3fd335e4b3 in transaction_ensure_mergeable (tr=tr@entry=0x557bb0f6d150,
     matters_to_anchor=matters_to_anchor@entry=true, e=e@entry=0x7ffc7dda33e0) at ../src/core/transaction.c:241
 #15 0x00007f3fd3360242 in transaction_merge_jobs (tr=0x557bb0f6d150, e=0x7ffc7dda33e0)
     at ../src/core/transaction.c:273
 #16 transaction_activate (tr=0x557bb0f6d150, m=0x557bb0dd9c10, mode=JOB_REPLACE, affected_jobs=0x0, e=0x7ffc7dda33e0)
     at ../src/core/transaction.c:797
 #17 0x00007f3fd33091ed in manager_add_jobs (m=<optimized out>, type=<optimized out>, names=<optimized out>,
     reload_if_possible=false, mode=JOB_REPLACE, extra_flags=0, affected_jobs=0x0, reterr_error=0x7ffc7dda33e0,
     ret_jobs=0x557bb0fe8790) at ../src/core/manager.c:2386

Follow-up for 7d3b32daef
2026-06-23 17:36:03 +01:00
Luca Boccassi 32a162dbb9 core: add method to enqueue multiple jobs in a single call (#42182)
Currently only a single job for a single unit can be enqueued
atomically,
so there is no guarantee that, e.g., starting a unit and its socket
at the same time will happen in the same transaction. That forces
callers to 'know' the right order in which to start new units being
installed, or failures will occur. It also means some ordering
constraints are ignored, in case the separate calls are done
in the wrong manual order.

Add a new EnqueueUnitJobMany() D-Bus method that takes a list of units
to start.
2026-06-22 21:35:17 +01:00
Zbigniew Jędrzejewski-Szmek 0c6186695a manager: make systemd+executor a multicall binary
Allow systemd-executor to be compiled into a single binary.
The existing -Dlink-executor-shared=true|false is extended to also
allow -Dlink-executor-shared=single (*). The new mode is opt-in,
to allow experimentation and introduce this smoothly.

This saves a little space, but not as much as I expected:
$ ls -l build/{systemd,systemd-executor} build-new/systemd
-rwxr-xr-x 1 zbyszek zbyszek  631520 May 25 22:44 build/systemd
-rwxr-xr-x 1 zbyszek zbyszek  670464 May 25 22:44 build/systemd-executor
-rwxr-xr-x 1 zbyszek zbyszek 1214488 May 25 22:45 build-new/systemd
(This is with -Dbuildtype=debugoptimized -Db_lto=true).
The combined binary is slightly smaller than the sum of the separate
ones, but not much. In both cases, the binaries are linked to
libsystemd-core which is 10MB, so the size of the binaries themselves
doesn't make much of a difference. The executor needs exec-invoke.c
which is huge and not shared with anything else.

Longer term, I want to allow systemd to be linked statically. In
that case, having systemd-executor separate would be very painful.
So the option to use a multicall binary will be necessary.

Previously, we stored the resolved path to systemd-executor and
used it argv[0]. I don't think this was useful. After all, normally
we would use the non-resolved original path as argv[0]. So that
part is dropped, and the resolved path is only logged, but
"systemd-executor" is always used as argv[0]. This makes the
multicall binary work reliably, no matter what the actual file
name is.

(*) This means that compat as the commandline level is maintained:
'meson setup build -Dlink-executor-shared=true …' works as before.
Unfortunately, when using an existing build directory, meson chokes
on the type change and refuses to reconfigure the directory or change
the option or do anything useful. I think meson is DTWT here, but
this is hard to fix. So the build directory probably needs to be
recreated.
2026-06-22 17:19:54 +02:00
Luca BoccassiandMichal Koutný 7d3b32daef core: add method to enqueue multiple jobs in a single call
Currently only a single job for a single unit can be enqueued atomically,
so there is no guarantee that, e.g., starting a unit and its socket
at the same time will happen in the same transaction. That forces
callers to 'know' the right order in which to start new units being
installed, or failures will occur. It also means some ordering
constraints are ignored, in case the separate calls are done
in the wrong manual order.

Add a new EnqueueUnitJobMany() D-Bus method that takes a list of units
to start.

Fixes https://github.com/systemd/systemd/issues/8102

Co-authored-by: Michal Koutný <mkoutny@suse.com>
2026-06-22 13:01:17 +01:00
Luca Boccassi 454591065c report-basic, networkd: add Version, KernelTimestamp, Address metrics (#42315)
This PR adds some more useful metrics:
- io.systemd.Network.Address
- io.systemd.Basic.KernelTimestamp.{Realtime,Monotonic}
- io.systemd.Basic.Version
2026-06-22 11:54:38 +01:00
Michael Vogt 54fd64db20 core: add _parameters_init for the Unit.StartTransient dispatch
This commit extracts the initialization of the transient parameters
for io.systemd.Unit.StartTransient into a set of helpers that follow
the _parameters_init() pattern. This way the code is more uniform
and easier to extend and less fragile. It also means there is a
single (logical) place to init the fields.
2026-06-21 20:47:17 +02:00
Michael Vogt cc348856de core: add more settable properties to varlink Unit.StartTransient()
This commit uses the abstractions added in the previous commit to
add a bunch more properties to the io.systemd.StartTransient()
to showcase how straightforward this is now.

New helpers for tristate bools and an init helper are added. A
dedicated dispatcher for LogLevelMax parses the string-form name
("info", "debug" etc.) declared in the varlink IDL.

The new properties are: DynamicUser, IgnoreSIGPIPE, LockPersonality,
MemoryDenyWriteExecute, NoNewPrivileges, OOMScoreAdjust, RemoveIPC,
RestrictRealtime, RestrictSUIDSGID, RootEphemeral, UMask.

The remaining ProtectKernel*, Private*, ProtectClock properties are
declared as STRING in the varlink IDL (matching the modern *Ex/enum
form) so a bool dispatcher does not pass schema validation. Those
need a string-parsing dispatcher and will be added in a follow-up.

This brings us closer to parity with the D-Bus code (still a long
way to go though).
2026-06-21 20:47:17 +02:00
Michael Vogt 4f0b27922f core: create abstraction for the "Exec" part of Unit.StartTransient
The handling of the `Exec` parameters for the varlink
`io.systemd.Unit.StartTransient()` became a bit unwieldy. So
this commit creates another abstraction to handle the various
fields in the `Exec` part of the StartTransient code.

Each Exec property is now described by a single TransientExecProperty
entry and adding a new property is just a single entry there plus
an apply function.

Thanks to Ivan Kruglov for many useful suggestions.
2026-06-21 20:17:51 +02:00
Luca Boccassi 45920af4a4 executor: also preload libcrypto
It's needed for the userspace fallback verity verification, so
it needs to be pre-loaded to avoid getting blocked by RTLD_NOLOAD:

 [   57.163995] (cat)[1560]: minimal-app0-foo.service: Validation of dm-verity signature failed via the kernel, trying userspace validation instead: Required key not available
 [   57.194696] (cat)[1560]: minimal-app0-foo.service: Refusing loading of 'libcrypto.so.3', as loading further dlopen() modules has been blocked.
 [   57.197940] (cat)[1560]: minimal-app0-foo.service: Shared library 'libcrypto.so.3' is not available: Operation not permitted
 [   57.204283] (cat)[1560]: minimal-app0-foo.service: Failed to activate verity device /dev/mapper/2b2fd83f324c3aa2ea1a979899f9c630761f1de3c5e00ce8c6bb36f4d137f450-verity: Operation not supported
 [   57.272782] (cat)[1560]: minimal-app0-foo.service: Failed to set up mount namespacing: Operation not supported
 [   57.274250] (cat)[1560]: minimal-app0-foo.service: Failed at step NAMESPACE spawning cat: Operation not supported

Follow-up for efaf5a763d
2026-06-20 23:51:24 +02:00
Michael Vogt 046de3caea core: add RestartRandomizedDelaySec= service option
We already support exponential backoff for automatic restarts via
RestartSec=/RestartSteps=/RestartMaxDelaySec=, but there is no way to
randomize the restart delay. When many instances of a service fail at
the same time (e.g. because a shared resource briefly went away) they
are all restarted in lockstep, creating a thundering herd problem.

So this commit adds a simple `RestartRandomizedDelaySec=` service
option which is similar to the timer `RandomizedDelaySec=` and
adds a randomized restart delay.
2026-06-20 12:31:28 +02:00
Luca Boccassi 23b0bd230b core: set pids.max=0 before sending SIGKILL to cgroup
When doing the final SIGKILL when stopping units ensure no more
processes can be created by setting pids.max=0 in the cgroup.
2026-06-20 10:53:04 +01:00
Michael Vogt 0b0db27050 core: add kernel/userspace/finish boot timestamps to io.systemd.Manager metrics
This commit adds the boot timeline (MANAGER_TIMESTAMP_KERNEL/USERSPACE/FINISH) as
metrics. The kernel CLOCK_MONOTONIC value is 0 by definition, so only its
.Realtime is reported. For userspace and finish report both .Realtime and
.Monotonic. The naming follows D-Bus.
2026-06-20 10:37:47 +02:00
Michael Vogt 3eb9864e23 core: add io.systemd.Manager.Version to metrics
This commit adds the systemd version to the metrics that
`io.systemd.Manager` generates.
2026-06-20 10:37:47 +02:00
Luca Boccassi f9e6419f34 core: add KExecsCount property
Use LUO to count kexec reboots, and expose through a new property

Fixes https://github.com/systemd/systemd/issues/42581
2026-06-19 19:36:01 +01:00
Luca Boccassi 82b8615463 core: add LUOSession= unit setting
Acquiring a LUO session from /dev/liveupdate requires privileges,
and also the device is a single-owner driver so only a single
process can open it at any given time.

Add a LUOSession= service settings that allows units running
without privileges to get a session assigned to them.

The kernel imposes a 64 chars limit on session names, which is
too short to avoid clashes, so derive a hash from joining the
unit name with the parameter name, that way two units using
the same setting don't clash.
2026-06-17 13:11:15 +01:00
Luca Boccassi e0edfca4cb LUO: only deserialize on boot, add version and structure to JSON payload (#42607) 2026-06-16 17:55:56 +01:00
dongshengyuan 98cae7a125 core: fix unit_merge() load state check evaluating after state overwrite
The condition on line 1206 checks other->load_state != UNIT_STUB to
decide whether to call the vtable done() callback, but the state was
already overwritten to UNIT_MERGED on line 1198, making the condition
always true.

Save the original load_state before overwriting it, so that units in
UNIT_STUB state (which never went through a load attempt) correctly
skip the done() call.

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
Co-developed-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 15:43:37 +01:00
Luca Boccassi ced0bf2f70 core: add version and structure to LUO json payload
We might want to add more state to the LUO session json payload,
so add a version (to allow clean compat breaks if needed) and nest
the current fdstore contents under a 'units' object, so that more
top-level data can be added in the future without breaking
backward compatibility.

Follow-up for 257c35c1a3
2026-06-16 13:51:59 +01:00
Luca Boccassi 229abeaf8d core: only attempt to deserialize state from LUO on boot
Avoid trying to query for our LUO session on reexec/softreboot/reload/etc.
Currently /dev/liveupdate is only accessible to root so it's not a big
issue, but this might change in the future, so make sure nobody can
play games with us.

Follow-up for 257c35c1a3
2026-06-16 11:35:11 +01:00
dongshengyuan cfed283b9c mount: log control command before clearing it in mount_sigchld_event()
control_command and control_command_id were cleared before being passed
to unit_log_process_exit(), so the log always showed an invalid/unknown
command name.

Move both clears after the log call, matching the ordering in
socket_sigchld_event() and service_sigchld_event().

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
Co-developed-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 10:14:02 +02:00
Luca Boccassi 2629c9c179 Assorted fixes (#40987) 2026-06-13 18:24:54 +01:00
Mike Yuan cd13dc16c3 core/execute-serialize: fix error handling 2026-06-13 17:11:11 +02:00
Mike Yuan 6f0731cf34 core/unit: refuse PrivatePIDs= + PAMName=
Fixes #40928
2026-06-13 17:11:11 +02:00
Mike Yuan 9be5a6f665 core/manager: add missing assertion on stop_notify_queue being empty
Follow-up for 1b4ab5a209
2026-06-13 17:11:10 +02:00
Luca Boccassi 73e9bf735c core: clear pending_reload_message_vl on manager varlink teardown
manager_varlink_done() tore down the varlink server without dropping the
queued reload reply, unlike bus_done_api() which unrefs
pending_reload_message_dbus. Unref it here too, so the slot consistently
mirrors the D-Bus side at teardown.

Follow-up for 55a1b36e91

Assisted-by: kres (claude-opus-4-7)
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 17:06:41 +02:00
Christian Brauner efd0173f37 oom: use cgroup.kill if available (#42373)
The log message is informational only, same as the count of killed
processes, so we can safely use cgroup.kill when available instead
of manually recursing through the cgroup tree.
2026-06-10 21:56:01 +02:00
Chris Down fb1e76c674 core: Update stale UserNamespacePath= failure message
The message is stale (this is about UserNamespacePath=, not PrivateUsers=) and
this should be an error, not notice given we are going to fail.
2026-06-08 16:34:28 +09:00
Chris Down bfaecf37cc core: Don't silently succeed on UserNamespacePath= join failures
These also need to set exit_status so that sd-executor returns the right
thing to pid1.
2026-06-08 16:12:52 +09:00
Lennart Poettering 2740d6aaa1 core: fix accidental change in 3d0309ac0f
Sorry!
2026-06-05 18:37:57 +02:00
Lennart Poettering 3d0309ac0f update TODO 2026-06-05 17:51:28 +02:00
Zbigniew Jędrzejewski-Szmek 112b565756 Add DLOPEN macros that stamp the caller's ELF and use it to ensure executables list their dlopen dependencies (#42398)
Currently almost all the dlopens happen in libbasic or libshared code,
so the ELF dlopen notes all end up in libsystemd-shared. Many
distributions split this library and various binaries in separate
packages, and the library ends up with soft-dependencies, even though
many binaries are either completely useless or do not work at all with
the dlopen dependency. This also makes it impossible to know which
executable uses which dlopen dependency without inspecting the source
code.

If someone only wants to add the soft dependencies from libshared they
can just avoid parsing the executable binaries. By design the code in
libbasic/libshared still does the stamping too, at lower priorities, so
that libsystemd-shared will always list all the optional dependencies,
and if one wants to build a minimal system by default, they can just
parse libsystemd-shared dlopen notes, and ignore the individual
executables. But for many distribution the current setup is insufficient
and requires adding a ton of manual library dependencies, as many
executables become effectively broken or useless without the dlopen
dependencies installed (eg: resolved fails to start without libssl,
repart can do basically nothing without blkid, etc).

Add a new set of DLOPEN_<LIB> macros that wrap the dlopen_lib and also
pull in the ELF note voodoo, so that the callers get their ELF binaries
stamped too. Convert a bunch of callers to use the macro, and use
`required` dependencies for the callers that do not work without the
dlopen library being available.

The one caveat is that, in order to avoid duplicating the exact same
note in a binary due to multiple call sites, some `asm` voodoo is done
instead of the previous bare-C section-creating macro. The drawback of
this approach is that if `--gc-sections` is used to link the binary (as
we do), then binutils >= 2.36 is required for the `SHF_GNU_RETAIN` flag.
This effectively cuts off CentOS 9, so what I did here is adding an
override in meson to detect missing support, and drop `SHF_GNU_RETAIN`.
The build works, but on CentOS 9 there's no dlopen ELF notes anymore.
Given it's just that version, and it goes EOL next year, that seems ok
to me. The alternative is to drop the usage of `--gc-sections` on CentOS
9, or to accept duplicated notes everywhere, and both seem worse.

End result:

```
$ readelf --notes build/systemd-executor

Displaying notes found in: .note.gnu.property
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_PROPERTY_TYPE_0
      Properties: x86 ISA needed: x86-64-baseline

Displaying notes found in: .note.gnu.build-id
  Owner                Data size 	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 8a0c3db54adb79ae54e1432255011aa4ab583742

Displaying notes found in: .note.ABI-tag
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 3.2.0

Displaying notes found in: .note.dlopen
  Owner                Data size 	Description
  FDO                  0x0000006b	FDO_DLOPEN_METADATA
    Dlopen Metadata: [{"feature":"pam","description":"Support for LinuxPAM","priority":"recommended","soname":["libpam.so.0"]}]
  FDO                  0x0000007c	FDO_DLOPEN_METADATA
    Dlopen Metadata: [{"feature":"seccomp","description":"Support for Seccomp Sandboxes","priority":"recommended","soname":["libseccomp.so.2"]}]
  FDO                  0x00000090	FDO_DLOPEN_METADATA
    Dlopen Metadata: [{"feature":"bpf","description":"Support firewalling and sandboxing with BPF","priority":"recommended","soname":["libbpf.so.1","libbpf.so.0"]}]
  FDO                  0x000000a0	FDO_DLOPEN_METADATA
    Dlopen Metadata: [{"feature":"cryptsetup","description":"Support for disk encryption, integrity, and authentication","priority":"recommended","soname":["libcryptsetup.so.12"]}]
  FDO                  0x00000078	FDO_DLOPEN_METADATA
    Dlopen Metadata: [{"feature":"mount","description":"Support for mount enumeration","priority":"recommended","soname":["libmount.so.1"]}]

$ readelf --notes build/systemd

Displaying notes found in: .note.gnu.property
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_PROPERTY_TYPE_0
      Properties: x86 ISA needed: x86-64-baseline

Displaying notes found in: .note.gnu.build-id
  Owner                Data size 	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: dcd4568842e32da3e71be27db3def51c6b459994

Displaying notes found in: .note.ABI-tag
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 3.2.0

Displaying notes found in: .note.dlopen
  Owner                Data size 	Description
  FDO                  0x00000075	FDO_DLOPEN_METADATA
    Dlopen Metadata: [{"feature":"mount","description":"Support for mount enumeration","priority":"required","soname":["libmount.so.1"]}]
  FDO                  0x00000072	FDO_DLOPEN_METADATA
    Dlopen Metadata: [{"feature":"selinux","description":"Support for SELinux","priority":"recommended","soname":["libselinux.so.1"]}]
```
2026-06-02 18:05:34 +02:00
Luca Boccassi a46ec24ddb core: avoid false maybe-uninitialized warning
2026-05-29T18:00:43.7496388Z ../src/core/dynamic-user.c: In function ‘dynamic_user_realize’:
2026-05-29T18:00:43.7497098Z ../src/core/dynamic-user.c:436:29: error: ‘new_uid’ may be used uninitialized [-Werror=maybe-uninitialized]
2026-05-29T18:00:43.7497758Z   436 |                         num = new_uid;
2026-05-29T18:00:43.7498026Z       |                         ~~~~^~~~~~~~~
2026-05-29T18:00:43.7498465Z ../src/core/dynamic-user.c:361:23: note: ‘new_uid’ was declared here
2026-05-29T18:00:43.7498802Z   361 |                 uid_t new_uid;
2026-05-29T18:00:43.7499039Z       |                       ^~~~~~~
2026-05-29T18:00:43.7499315Z In file included from ../src/core/dynamic-user.c:23:
2026-05-29T18:00:43.7499651Z In function ‘dynamic_user_push’,
2026-05-29T18:00:43.7500063Z     inlined from ‘dynamic_user_realize’ at ../src/core/dynamic-user.c:453:13:
2026-05-29T18:00:43.7501021Z ../src/basic/socket-util.h:131:63: error: ‘new_uid_lock_fd’ may be used uninitialized [-Werror=maybe-uninitialized]
2026-05-29T18:00:43.7501897Z   131 | #define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags)
2026-05-29T18:00:43.7502530Z       |                                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2026-05-29T18:00:43.7503145Z ../src/core/dynamic-user.c:320:16: note: in expansion of macro ‘send_one_fd_iov’
2026-05-29T18:00:43.7503647Z   320 |         return send_one_fd_iov(d->storage_socket[1], lock_fd, &iov, 1, MSG_DONTWAIT);
2026-05-29T18:00:43.7504027Z       |                ^~~~~~~~~~~~~~~
2026-05-29T18:00:43.7504397Z ../src/core/dynamic-user.c: In function ‘dynamic_user_realize’:
2026-05-29T18:00:43.7504888Z ../src/core/dynamic-user.c:360:21: note: ‘new_uid_lock_fd’ was declared here
2026-05-29T18:00:43.7505256Z   360 |                 int new_uid_lock_fd;
2026-05-29T18:00:43.7505511Z       |                     ^~~~~~~~~~~~~~~
2026-05-29T18:00:43.7505882Z ../src/core/dynamic-user.c: In function ‘dynamic_user_current’:
2026-05-29T18:00:43.7506461Z ../src/core/dynamic-user.c:468:15: error: ‘uid’ may be used uninitialized [-Werror=maybe-uninitialized]
2026-05-29T18:00:43.7506895Z   468 |         uid_t uid;
2026-05-29T18:00:43.7507096Z       |               ^~~

2026-05-29T18:26:14.2420944Z In function ‘dynamic_user_push’,
2026-05-29T18:26:14.2421730Z     inlined from ‘dynamic_user_realize’ at ../src/core/dynamic-user.c:453:13:
2026-05-29T18:26:14.2435240Z ../src/basic/socket-util.h:131:63: error: ‘new_uid_lock_fd’ may be used uninitialized [-Werror=maybe-uninitialized]
2026-05-29T18:26:14.2440497Z   131 | #define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags)
2026-05-29T18:26:14.2442511Z       |                                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2026-05-29T18:26:14.2445002Z ../src/core/dynamic-user.c:320:16: note: in expansion of macro ‘send_one_fd_iov’
2026-05-29T18:26:14.2445727Z   320 |         return send_one_fd_iov(d->storage_socket[1], lock_fd, &iov, 1, MSG_DONTWAIT);
2026-05-29T18:26:14.2448345Z       |                ^~~~~~~~~~~~~~~
2026-05-29T18:26:14.2448952Z ../src/core/dynamic-user.c: In function ‘dynamic_user_realize’:
2026-05-29T18:26:14.2451781Z ../src/core/dynamic-user.c:360:21: note: ‘new_uid_lock_fd’ was declared here
2026-05-29T18:26:14.2452287Z   360 |                 int new_uid_lock_fd;
2026-05-29T18:26:14.2454430Z       |                     ^~~~~~~~~~~~~~~
2026-05-29T18:26:14.2454960Z ../src/core/dynamic-user.c: In function ‘dynamic_user_current’:
2026-05-29T18:26:14.2457632Z ../src/core/dynamic-user.c:468:15: error: ‘uid’ may be used uninitialized [-Werror=maybe-uninitialized]
2026-05-29T18:26:14.2458207Z   468 |         uid_t uid;
2026-05-29T18:26:14.2460327Z       |               ^~~
2026-06-02 13:20:29 +01:00
Luca Boccassi b240ce9642 ci: add build/unit-test coverage for armv7 (#42386)
arm64 hosts support running armv7 (armhf) binaries, so we can
cross compile and run the unit tests without performance issues.

armv7 (armhf) is a primary architecture on Ubuntu, so build
regressions block new version updates, and adding coverage
helps to avoid introducing regressions.
2026-06-02 13:15:50 +01:00
Luca Boccassi b0ede9f9ee tree-wide: convert dlopen_*() callers to DLOPEN_* wrapper macros
Switch the executable-owned call sites from the plain dlopen_<lib>()
helpers to the new DLOPEN_<LIB>() macros, so that each binary that loads
an optional library at runtime now carries its own .note.dlopen note
instead of relying solely on libsystemd-shared. Each call site passes a
priority reflecting whether it hard-depends on the library (required) or
degrades gracefully without it (recommended).

Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 18:46:24 +01:00
Zbigniew Jędrzejewski-Szmek b1410258f8 manager: if called with compat telinit interface, tell users to update
In https://bugzilla.redhat.com/show_bug.cgi?id=2479961 a user
reported that they are confused that 'init 6' and such commands
do not work anymore. We removed support for the whole interface,
but it's likely that such commands persist in various scripts
and finger memories. Let's give a helpful hint that this inteface
is gone and what to use instead.
2026-06-01 12:19:03 +02:00
Luca Boccassi b3f50b9515 core: fix maybe-uninitialized warning
2026-05-29T13:14:20.8990848Z arm-linux-gnueabihf-gcc -Isrc/core/libsystemd-core-261.a.p -Isrc/core -I../src/core -Isrc/shared -I../src/shared -Isrc/bpf -I../src/bpf -I../src/libsystemd/sd-bus -I../src/libsystemd/sd-common -I../src/libsystemd/sd-device -I../src/libsystemd/sd-event -I../src/libsystemd/sd-future -I../src/libsystemd/sd-hwdb -I../src/libsystemd/sd-id128 -Isrc/libsystemd/sd-journal -I../src/libsystemd/sd-journal -I../src/libsystemd/sd-json -I../src/libsystemd/sd-netlink -I../src/libsystemd/sd-network -I../src/libsystemd/sd-path -I../src/libsystemd/sd-resolve -I../src/libsystemd/sd-varlink -Isrc/basic -I../src/basic -Isrc/fundamental -I../src/fundamental -Isrc/systemd -I../src/systemd -Isrc/version -I../src/version -I/usr/include/uuid -I/usr/include/json-c -I/usr/include/blkid -I/usr/include/libmount -fdiagnostics-color=always -DNDEBUG -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=gnu17 -O0 -Wno-missing-field-initializers -Wno-unused-parameter -Wno-nonnull-compare -Warray-bounds -Warray-bounds=2 -Wdate-time -Wendif-labels -Werror=bool-compare -Werror=discarded-qualifiers -Werror=format=2 -Werror=format-signedness -Werror=implicit-function-declaration -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Werror=missing-declarations -Werror=missing-prototypes -Werror=overflow -Werror=override-init -Werror=pointer-sign -Werror=return-type -Werror=sequence-point -Werror=shift-count-overflow -Werror=shift-overflow=2 -Werror=strict-flex-arrays -Werror=undef -Wfloat-equal -Wimplicit-fallthrough=5 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wmissing-noreturn -Wnested-externs -Wold-style-definition -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-aliasing=2 -Wstrict-prototypes -Wsuggest-attribute=noreturn -Wunused-function -Wwrite-strings -Wzero-length-bounds -fdiagnostics-show-option -fexcess-precision=standard -fno-common -fstack-protector -fstack-protector-strong -fstrict-flex-arrays=3 -fno-math-errno --param=ssp-buffer-size=4 -Wno-unused-result -Werror=shadow -O2 -pipe -g -feliminate-unused-debug-types -fPIC -fno-strict-aliasing -fstrict-flex-arrays=1 -fvisibility=hidden -fno-omit-frame-pointer -include config.h -isystem../src/include/glibc -isystem../src/include/override -isystemsrc/include/override -isystem../src/include/uapi -fvisibility=default -MD -MQ src/core/libsystemd-core-261.a.p/unit.c.o -MF src/core/libsystemd-core-261.a.p/unit.c.o.d -o src/core/libsystemd-core-261.a.p/unit.c.o -c ../src/core/unit.c
2026-05-29T13:14:20.9001764Z ../src/core/unit.c: In function ‘unit_start_on_termination_deps’:
2026-05-29T13:14:20.9002500Z ../src/core/unit.c:2367:21: error: ‘job_mode’ may be used uninitialized [-Werror=maybe-uninitialized]
2026-05-29T13:14:20.9004088Z  2367 |                 r = manager_add_job(u->manager, JOB_START, other, job_mode, &error, /* ret= */ NULL);
2026-05-29T13:14:20.9004619Z       |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2026-05-29T13:14:20.9005147Z ../src/core/unit.c:2341:17: note: ‘job_mode’ was declared here
2026-05-29T13:14:20.9005458Z  2341 |         JobMode job_mode;
2026-05-29T13:14:20.9005673Z       |                 ^~~~~~~~
2026-05-29T13:14:20.9005898Z cc1: all warnings being treated as errors

Follow-up for 9faeb2d024
2026-05-29 17:48:37 +01:00
Luca Boccassi 92a5bf2c02 cgroup: optionally check number of tasks before cgroup.kill
This of course cannot be atomic, but for informational purposes it
should be good enough
2026-05-28 20:55:01 +01:00
Chris Mason 99aff23783 core/exec-invoke: log write() allow-list widening
apply_syscall_filter() unconditionally inserts the write() syscall
into c->syscall_filter when exec_fd or handoff_timestamp_fd is in
use, so the parent can receive the exec status / handoff timestamp
from the child. When the unit configured a positive
SystemCallFilter= allow-list that deliberately omits write(), the
resulting widening of the operator's policy happens silently with
no trace in the journal.

Emit a log_debug() before the seccomp_filter_set_add_by_name() call
when syscall_allow_list is true, so the widening is at least
observable to operators inspecting the unit's debug log.

While here, document that mutating c->syscall_filter through a
'const ExecContext *c' is intentional: apply_syscall_filter() runs
only in the post-fork child, which owns a private copy of the
address space, so the hashmap change is never observed by the
manager.

No functional change for the allow-list itself; write() is still
added exactly as before.

Fixes: 84b79215cc ("core: do not filter out write() if required in the very late stage")
Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
2026-05-22 22:19:35 +02:00
Chris Mason 4e02162a6e core/exec-invoke: chdir("/") after chroot in apply_root_directory
apply_root_directory() calls chroot() but never pairs it with a
chdir("/"). Moving cwd into the new root is left to the subsequent
apply_working_directory() call. That delegation breaks when the unit
sets WorkingDirectory=-/path (working_directory_missing_ok):

    apply_root_directory()              apply_working_directory()
      chroot(new_root)        -->         chdir(wd) fails (ENOENT)
      return 0                            return 0  /* missing_ok */

chroot(2) changes only the process root, not cwd. With cwd still
resolving to the pre-chroot host dentry, the process runs with the
kernel root pointing at the new root while relative-path accesses
and /proc/self/cwd reach paths outside RootDirectory=.

Only the chroot-only branch (exec_needs_mount_namespace() == false)
is affected. The mount-namespace branch uses pivot_root(), which
restructures the mount tree and makes the pre-chroot dentry
unreachable.

Fix by issuing chdir("/") immediately after the successful chroot()
in apply_root_directory() and propagating any failure with
EXIT_CHROOT, matching the standard chroot+chdir idiom and making
the chroot self-contained regardless of how
apply_working_directory() later handles a missing directory.

Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
2026-05-22 22:18:29 +02:00
Yu Watanabe 580bd17d90 Use malloc'ed strings instead of static libc buffers for user and group lookup (#42184)
Preparation for other work.
2026-05-22 05:09:56 +09:00
Lennart Poettering 461ec6facc condition: add a condition that matches against the machine tags 2026-05-21 18:30:16 +02:00
Lennart Poettering 740a5ce947 core: introduce ConditionFraction= that is true on a certain percantage of the fleet 2026-05-21 18:19:07 +02:00
Zbigniew Jędrzejewski-Szmek c83ff0e58d user-util: return malloc'ed strings in get_user_creds
get_user_creds would use getpwnam() and then returns strings pointing
into the static buffer. This seems very iffy. Let's duplicate the
strings properly
2026-05-21 18:02:05 +02:00
Zbigniew Jędrzejewski-Szmek 3ecd6b69cf user-util: stop mangling groupname in get_group_creds
The param was input/output, which is unexpected and confusing and
actually made most callers much more complicated than they needed to be.
The function was playing fast and loose with the return value. In some
cases it was returning a static string, which would be completely fine.
But in other case it was returning a pointer into the getgrgid static
buffer, i.e. that return value could be overwritten. AFAICT, this didn't
matter in any of the callers, but we shouldn't do that anyway.

So use a separate output param with an allocated string that the caller
is responsible for.

It turns out that all callers pass NULL (outside of tests) and zero for
flags. So the function _could_ be simplified. But get_user_creds is
called with all the params actually used, and I think having the the
functions so different wouldn't be nice. I first wrote a commit to
drop the unused params, but then I discarded it.

The error message in exec-invoke.c is fixed.
2026-05-21 18:02:05 +02:00
Zbigniew Jędrzejewski-Szmek 3d0a05dcc3 core/exec-invoke: fix bogus error code
r was bogus here. getusername_malloc() can only fail on oom,
so we can simplify this.
2026-05-21 18:02:05 +02:00
Luca Boccassi 20615d2d47 core: add FileDescriptorStorePreserve=on-success option (#42160)
Currently with FileDescriptorStorePreserve=yes the FD store is kept
around
regardless of what happens to a unit, which is useful in many cases. But
in
some cases, for example when complex services crash horribly, it's hard
to
reason about what was in the intermediate state, and it's better to
start
fresh.

Add a new 'on-success' option for the FileDescriptorStorePreserve=
setting
that keeps it around only for as long as the unit doesn't go to a
persistently
failed state.

This is especially useful in combination with LUO, where we don't want
to
keep around LUO sessions created by units that then proceeded to crash
and
burn, and might be in a bad state afterwards.
2026-05-21 12:08:33 +01:00
Daan De Meyer a080cb356c core: better errors and more fields for io.systemd.Unit.StartTransient (#42161)
core: add User,Group,SupplementaryGroups,Nice to varlink
 Unit.StartTransient

This commit adds more writable fields to the
io.systemd.Unit.StartTransient
varlink method. With this its possible to set:
User,Group,SupplementaryGroups,Nice values.

Plus tests for them.

---

core: report unsupported service fields in varlink calls

Just like for the unsupported/bad exec_fields we should show
a message about what field is bad for service parameters. This
commit adds it using the same pattern. The JSON parser works in
fail-fast mode so we only display the first bad field (and
it depends on the parser what it finds first).
2026-05-21 13:03:29 +02:00
Luca Boccassi 67dea1409b core: add FileDescriptorStorePreserve=on-success option
Currently with FileDescriptorStorePreserve=yes the FD store is kept around
regardless of what happens to a unit, which is useful in many cases. But in
some cases, for example when complex services crash horribly, it's hard to
reason about what was in the intermediate state, and it's better to start
fresh.

Add a new 'on-success' option for the FileDescriptorStorePreserve= setting
that keeps it around only for as long as the unit doesn't go to a persistently
failed state.

This is especially useful in combination with LUO, where we don't want to
keep around LUO sessions created by units that then proceeded to crash and
burn, and might be in a bad state afterwards.
2026-05-21 10:14:08 +01:00