]> git.ipfire.org Git - thirdparty/systemd.git/log
thirdparty/systemd.git
7 days agobootctl: refactor get_file_version() to use proper PE parsing 42246/head
Lennart Poettering [Fri, 22 May 2026 02:34:54 +0000 (04:34 +0200)] 
bootctl: refactor get_file_version() to use proper PE parsing

This irked me for a while. Let's not scan for strings stupidly, but
properly parse PE files to find the magic marker.

It's easy with our own PE APIs, hence we should do it.

This moves logging to the callers (previously, this was all mixed up).

7 days agope-binary: tweak pe_read_section_data() error codes
Lennart Poettering [Fri, 22 May 2026 02:36:15 +0000 (04:36 +0200)] 
pe-binary: tweak pe_read_section_data() error codes

Let's return -EBADMSG if the PE headers reference stuff missing in the
file, regardless if that's because the offsets are larger than SSIZE_MAX
or just larger than the file size. We generally use EBADMSG for all
cases we deem the file to not be a conformant PE file, and these two
cases are the same. Hence, let's be systematic here.

7 days agosysupdate: Add separate polkit actions for cancellation (#42209)
Lennart Poettering [Fri, 22 May 2026 08:35:49 +0000 (10:35 +0200)] 
sysupdate: Add separate polkit actions for cancellation (#42209)

This allows us to have a separate, more permissive, policy for
cancelling ongoing sysupdate jobs. The new default policy for
cancellation actions is to allow them for the active user, without admin
authentication, because typically the user can just pull the plug on the
computer to cancel a job anyway.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: https://github.com/systemd/systemd/issues/38568
7 days agoefi-api: fix unaligned access in efi_guid_to_id128()
Daan De Meyer [Thu, 21 May 2026 22:00:28 +0000 (22:00 +0000)] 
efi-api: fix unaligned access in efi_guid_to_id128()

EFI_GUID requires 4-byte alignment due to its uint32_t Data1 field, but
callers may pass pointers at arbitrary offsets into serialized EFI
variable buffers (e.g. bootctl walking BootXXXX entries). UBSan flagged
the misaligned member access; the old comment claiming the struct was
packed was wrong. Copy the bytes into an aligned local first.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
7 days agohwdb: reject out-of-bounds fnmatch prefixes
Luca Boccassi [Thu, 21 May 2026 22:24:32 +0000 (23:24 +0100)] 
hwdb: reject out-of-bounds fnmatch prefixes

Ensure that fnmatch traversal doesn't go off the hwdb.bin in case of
a corrupted file

Originally reported on yeswehack.com as #YWH-PGM9780-70

For the unit test:
Co-developed-by: GitHub Copilot <github-copilot[bot]@users.noreply.github.com>
7 days agosd-dhcp-server: use sd_dhcp_message to parse/build DHCP messages (#42240)
Yu Watanabe [Fri, 22 May 2026 06:28:52 +0000 (15:28 +0900)] 
sd-dhcp-server: use sd_dhcp_message to parse/build DHCP messages (#42240)

7 days agosd-dhcp-server: drop unused enum
Yu Watanabe [Fri, 22 May 2026 00:43:11 +0000 (09:43 +0900)] 
sd-dhcp-server: drop unused enum

Follow-up for 2e5580a8c12427ddf421b7fee7be3677ff41bd5b.

7 days agosd-dhcp-server: use sd_dhcp_message object on sending reply 42240/head
Yu Watanabe [Sun, 10 May 2026 13:17:05 +0000 (22:17 +0900)] 
sd-dhcp-server: use sd_dhcp_message object on sending reply

This also makes the conditions in dhcp_server_send_message() uses
the message that will be sent, rather than we received.

This does not change basic functionality, but changes/fixes several
minor behaviors, e.g.
- fix when the broadcast flag assignment,
- set server identifier in DHCPFORCERENEW.

7 days agosd-dhcp-server: use sd_dhcp_message to parse received messages
Yu Watanabe [Thu, 7 May 2026 04:30:00 +0000 (13:30 +0900)] 
sd-dhcp-server: use sd_dhcp_message to parse received messages

This is mostly refactoring. This does not change basic behavior, but
changes/fixes some minor/corner cases, e.g.

- extend the minimum default lease time from 1 second to 30 seconds, as
  1 second is too short and causes the network unstable (though 30
  seconds is stll too short, but hopefully that does not make the
  network unstable).
- error code on broken/malicious message received may be changed.

7 days agodhcp-server-request: drop invalid short-cut logic
Yu Watanabe [Mon, 18 May 2026 00:37:27 +0000 (09:37 +0900)] 
dhcp-server-request: drop invalid short-cut logic

Even if no pool is allocated, the server may have a static lease
matching with the DHCPDISCOVER message.

7 days agodhcp: move definition of enum DHCPState to dhcp-protocol.[ch]
Yu Watanabe [Sun, 10 May 2026 14:13:07 +0000 (23:13 +0900)] 
dhcp: move definition of enum DHCPState to dhcp-protocol.[ch]

It will be also used in DHCP server, later.

7 days agosd-dhcp-relay: use forward declarations
Yu Watanabe [Thu, 21 May 2026 22:10:46 +0000 (07:10 +0900)] 
sd-dhcp-relay: use forward declarations

7 days agosd-dhcp-server: several trivial cleanups (#42235)
Yu Watanabe [Thu, 21 May 2026 21:44:07 +0000 (06:44 +0900)] 
sd-dhcp-server: several trivial cleanups (#42235)

This should mostly not change behavior, except for some corner cases.
Just refactoring and preparation for later changes.

7 days agoUpdate NEWS
Luca Boccassi [Thu, 21 May 2026 20:59:17 +0000 (21:59 +0100)] 
Update NEWS

7 days agobootctl: add A/B fallback for sd-boot updates (#41650)
Luca Boccassi [Thu, 21 May 2026 20:56:05 +0000 (21:56 +0100)] 
bootctl: add A/B fallback for sd-boot updates (#41650)

On `bootctl install`, two EFI boot entries are registered: one for the
primary sd-boot binary and one for a fallback. On `bootctl update`, the
existing primary binary is rotated to the fallback path before the new
version is installed, so the fallback entry always points to the
previous known-good binary.

```
$ sudo bootctl install
...
Created EFI boot entry "Linux Boot Manager".
Created EFI boot entry "Fallback Linux Boot Manager".
$ sudo bootctl update
Copied "/boot/EFI/systemd/systemd-bootaa64.efi" to "/boot/EFI/systemd/systemd-boot-fallbackaa64.efi".
Copied "/usr/lib/systemd/boot/efi/systemd-bootaa64.efi" to "/boot/EFI/systemd/systemd-bootaa64.efi".
$ efibootmgr
...
Boot0004* Linux Boot Manager        HD(...)/\EFI\systemd\systemd-bootaa64.efi
Boot0005* Fallback Linux Boot Manager     HD(...)/\EFI\systemd\systemd-boot-fallbackaa64.efi
```

Fixes: #23805
7 days agoUpdate NEWS
Luca Boccassi [Thu, 21 May 2026 20:49:22 +0000 (21:49 +0100)] 
Update NEWS

7 days agoboot,stub: explicitly measure select SMBIOS objects (#42233)
Luca Boccassi [Thu, 21 May 2026 20:44:42 +0000 (21:44 +0100)] 
boot,stub: explicitly measure select SMBIOS objects (#42233)

This is supposed to protect our SMBIOS type 11 importing for
credentials. Note that firmwares are supposed to measure SMBIOS anyway
to PCR 1. Alas firmware doesn't really do that in various cases. Hence
let's do so again, for select objects.

This closes a gap where some of the input for OS (i.e. system
credentials places in smbios11) isn't measured properly.

(I really want this to get into v261, because this will fuck up the PCRs
a bit more, and we already have the new separator measurement in v261,
hence there's value in getting this merged at the same time, so that we
don't break the measurements a 2nd time)

7 days agoupdate TODO 42233/head
Lennart Poettering [Thu, 21 May 2026 15:13:40 +0000 (17:13 +0200)] 
update TODO

7 days agopcrlock: port --help to help-util.[ch] apis
Lennart Poettering [Thu, 21 May 2026 16:16:32 +0000 (18:16 +0200)] 
pcrlock: port --help to help-util.[ch] apis

7 days agopcrlock: decode new smbios events
Lennart Poettering [Thu, 21 May 2026 16:16:45 +0000 (18:16 +0200)] 
pcrlock: decode new smbios events

7 days agobootctl: show SMBIOS feature flags
Lennart Poettering [Thu, 21 May 2026 15:27:13 +0000 (17:27 +0200)] 
bootctl: show SMBIOS feature flags

7 days agodocs: document the new smbios measurements
Lennart Poettering [Thu, 21 May 2026 15:26:20 +0000 (17:26 +0200)] 
docs: document the new smbios measurements

7 days agoUpdate NEWS
Luca Boccassi [Thu, 21 May 2026 20:13:10 +0000 (21:13 +0100)] 
Update NEWS

7 days agoUse malloc'ed strings instead of static libc buffers for user and group lookup (...
Yu Watanabe [Thu, 21 May 2026 20:09:56 +0000 (05:09 +0900)] 
Use malloc'ed strings instead of static libc buffers for user and group lookup (#42184)

Preparation for other work.

7 days agohostnamed,pid1,firstboot: introduce "machine tags" concept (#42223)
Luca Boccassi [Thu, 21 May 2026 19:57:34 +0000 (20:57 +0100)] 
hostnamed,pid1,firstboot: introduce "machine tags" concept (#42223)

Fixes: #38591
7 days agoci: ignore failures to chown journal in GHA jobs
Luca Boccassi [Thu, 21 May 2026 18:21:19 +0000 (19:21 +0100)] 
ci: ignore failures to chown journal in GHA jobs

Otherwise when the build fails, this fails, and the GUI jumps to the
chown failure instead of the actual failure

Follow-up for 35bf1c826454bfcaa3c93cae950d36fa216ac3ce

7 days agodhcp-server-request: check server address in DHCPDECLINE and DHCPRELEASE 42235/head
Yu Watanabe [Thu, 7 May 2026 03:19:25 +0000 (12:19 +0900)] 
dhcp-server-request: check server address in DHCPDECLINE and DHCPRELEASE

Otherwise, we may do something wrong by messages for another DHCP server.
Let's silently ignore messages with unmatching server identifier.

Also, logs something when we receive DHCPRELEASE but found lease does
not match the reported address.

7 days agosd-dhcp-server: store more information in DHCPRequest
Yu Watanabe [Thu, 7 May 2026 02:59:23 +0000 (11:59 +0900)] 
sd-dhcp-server: store more information in DHCPRequest

This makes DHCPRequest stores
- the message type of the received message,
- acquired address,
- found static DHCP lease,

This also moves call of dhcp_request_get_lifetime_timestamp() from
dhcp_server_ack() to dhcp_server_set_lease(), and rename
DHCPRequest.server_id -> .server_address.

No functional change, just refactoring.

7 days agosd-dhcp-server: use struct hw_addr_data to manage client hardware address parsed...
Yu Watanabe [Mon, 4 May 2026 19:55:03 +0000 (04:55 +0900)] 
sd-dhcp-server: use struct hw_addr_data to manage client hardware address parsed from DHCP message

Then, this drops garbage in DHCP server lease in DBus and Varlink message.

This also drops fallback to use client ID as hardware address when chaddr
field is not set. In that case, we should broadcast reply.

7 days agodhcp-server-send: rework sending DHCP reply message
Yu Watanabe [Mon, 4 May 2026 13:08:40 +0000 (22:08 +0900)] 
dhcp-server-send: rework sending DHCP reply message

This should mostly not change anything, except for some corner cases.
Just refactoring.

7 days agosd-dhcp-server: make IP service type (TOS) configurable
Yu Watanabe [Thu, 7 May 2026 03:41:38 +0000 (12:41 +0900)] 
sd-dhcp-server: make IP service type (TOS) configurable

7 days agosd-dhcp-server: refactoring for socket fd handling
Yu Watanabe [Mon, 4 May 2026 10:57:49 +0000 (19:57 +0900)] 
sd-dhcp-server: refactoring for socket fd handling

This makes
- UDP socket fd is owned by IO event source,
- open RAW socket fd just before sending first packet,
- set TOS and socket priority,
- use AF_UNIX soxket pair in the unit test and fuzzer, so the unit test
  can now run by unprivileged user.

7 days agodhcp-serve-request: move message size check to dhcp_server_handle_message()
Yu Watanabe [Mon, 4 May 2026 21:57:33 +0000 (06:57 +0900)] 
dhcp-serve-request: move message size check to dhcp_server_handle_message()

7 days agodhcp-server-request: modernize server_receive_message()
Yu Watanabe [Mon, 4 May 2026 07:59:04 +0000 (16:59 +0900)] 
dhcp-server-request: modernize server_receive_message()

7 days agosd-dhcp-server: split into small pieaces
Yu Watanabe [Mon, 4 May 2026 04:24:33 +0000 (13:24 +0900)] 
sd-dhcp-server: split into small pieaces

No functional change, just several functions are moved/split/renamed.

7 days agotest-dhcp-server: several cleanups
Yu Watanabe [Mon, 4 May 2026 11:42:27 +0000 (20:42 +0900)] 
test-dhcp-server: several cleanups

No effective change, just rafactoring.

7 days agomeson: Add libucontext to libshared_deps
Daan De Meyer [Thu, 21 May 2026 17:51:07 +0000 (17:51 +0000)] 
meson: Add libucontext to libshared_deps

Fixes #42236

7 days agobootctl: remove fallback EFI Boot#### variable on uninstall 41650/head
Clayton Craft [Thu, 30 Apr 2026 03:32:19 +0000 (20:32 -0700)] 
bootctl: remove fallback EFI Boot#### variable on uninstall

This cleans up the fallback Boot#### entry that was registered on
install. The logic cleaning up variables was moved from verb_remove into
a new remove_variables function, which mirrors the install side.

7 days agobootctl: register fallback EFI Boot#### entry on install
Clayton Craft [Thu, 30 Apr 2026 01:46:13 +0000 (18:46 -0700)] 
bootctl: register fallback EFI Boot#### entry on install

This adds a second install_boot_option call to register a Boot#### entry
pointing at systemd-boot-fallback{arch}.efi, and place it immediately
after the primary entry in BootOrder.

The fallback file does not exist on the ESP on first install and is
only created on first update when the existing primary binary is
rotated to the fallback path. We register the variable anyway, so
that the entry exists in the BootOrder once the fallback file shows up.
Until then, firmware that reaches the fallback entry will fail to
load it and fall through to the next entry in BootOrder, which is
fine. install_boot_option gains a require_existing parameter so the
existing early return on a missing ESP path can be skipped for the
fallback, where a missing path is expected.

This also does a bit of refactoring by splitting the bottom part of
run_install() into a new install_variables() function that handles
registering both the primary and fallback entries.

7 days agobootctl: back up sd-boot binary to fallback path on update
Clayton Craft [Thu, 30 Apr 2026 01:24:21 +0000 (18:24 -0700)] 
bootctl: back up sd-boot binary to fallback path on update

When a primary sd-boot binary already exists on the ESP and is being
updated, it is copied to systemd-boot-fallback{arch}.efi before installing
the new version. This gives firmware a fallback Boot#### entry pointing
to the previous binary in case the new one fails to load.

The fallback is preserved (not overwritten) when its product and version
match the currently booted bootloader (read from the LoaderInfo EFI
variable), since that means it already holds the known good binary that
booted this session. In all other cases it is overwritten with the current
primary, when no fallback exists yet, when LoaderInfo is unavailable, or
when the fallback's product or version differs from what booted.

This also moves the version_check() call up so its result determines
both the rotation decision and the main copy, and avoids a duplicate
check (and duplicate "Skipping..." log) when the binary is already
current.

7 days agobootctl: add after_slot parameter to insert_into_order()
Clayton Craft [Thu, 30 Apr 2026 00:35:05 +0000 (17:35 -0700)] 
bootctl: add after_slot parameter to insert_into_order()

This adds an after_slot parameter that, when not set to UINT16_MAX,
requests that the new slot be placed immediately after the given slot in
BootOrder. When after_slot is set and the new slot already exists in
BootOrder, it will leave its position alone. This is so that if a user
reorders it, we don't stomp on their changes.

7 days agobootctl: add description and ret_slot parameters to install_boot_option()
Clayton Craft [Thu, 30 Apr 2026 00:10:05 +0000 (17:10 -0700)] 
bootctl: add description and ret_slot parameters to install_boot_option()

This moves creation of the EFI boot option description out of
install_boot_option and into the caller, and adds a ret_slot output
parameter for capturing the assigned BootOrder slot. This allows reusing
the function for installing variables with different descriptions.

7 days agobootctl: rename install_variables/remove_variables to install/remove_boot_option
Clayton Craft [Tue, 12 May 2026 17:47:17 +0000 (10:47 -0700)] 
bootctl: rename install_variables/remove_variables to install/remove_boot_option

These functions install or remove a single EFI Boot#### entry, not
"all variables," so this renames them to better reflect what they do.

7 days agobootctl: fix removing variables on uninstall
Clayton Craft [Thu, 30 Apr 2026 02:33:58 +0000 (19:33 -0700)] 
bootctl: fix removing variables on uninstall

remove_variables looks up the EFI boot entry by matching both the path
and the partition UUID and it wasn't actually removing any entries
because verb_remove was passing SD_ID128_NULL, so the lookup never
matched and Boot#### entries were left behind on uninstall.

Fixes 38433a6

8 days agosystemctl: also attempt kexec image extraction on EINVAL
Rocker Zhang [Thu, 21 May 2026 15:47:48 +0000 (23:47 +0800)] 
systemctl: also attempt kexec image extraction on EINVAL

load_kexec_kernel() retries kexec_file_load() with an extracted kernel
(decompressed Image / ZBOOT PE / UKI) when the kernel rejects the image,
but it only does so when kexec_file_load() failed with ENOEXEC. On arm64
that retry never happens: arm64's image_probe()
(arch/arm64/kernel/kexec_image.c) returns -EINVAL on an ARM64_IMAGE_MAGIC
mismatch, whereas x86's bzImage64_probe() and the generic
kexec_image_probe_default() return -ENOEXEC. So `systemctl kexec` of a
UKI on arm64 skips the extraction path and falls back to the
/usr/sbin/kexec binary, which is no longer a dependency since e107c7ead0
("systemctl: replace kexec-tools dependency with direct kexec_file_load()
syscall") -- leaving kexec broken.

Accept EINVAL in addition to ENOEXEC. This is safe: the extraction in
kexec_maybe_decompress_kernel() re-gates on the actual file magic (MZ /
compression headers) and is a no-op returning 0 for anything else, so an
EINVAL that is not a format mismatch just falls through to the existing
fallback as before.

Fixing this in systemd (rather than only in the kernel) is appropriate:
systemd must keep working with already-shipped arm64 kernels whose
kexec_file_load() returns EINVAL for an unrecognized image magic.

Relates to: https://github.com/systemd/systemd/issues/28538

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
8 days agoboot: measure select SMBIOS objects explicitly
Lennart Poettering [Thu, 21 May 2026 15:26:02 +0000 (17:26 +0200)] 
boot: measure select SMBIOS objects explicitly

8 days agoupdate TODO 42223/head
Lennart Poettering [Thu, 21 May 2026 06:42:43 +0000 (08:42 +0200)] 
update TODO

8 days agoci: add test for new machine-tags concept
Lennart Poettering [Thu, 21 May 2026 07:47:16 +0000 (09:47 +0200)] 
ci: add test for new machine-tags concept

8 days agofirstboot: allow configuring machine tags via firstboot
Lennart Poettering [Thu, 21 May 2026 06:39:23 +0000 (08:39 +0200)] 
firstboot: allow configuring machine tags via firstboot

8 days agocondition: add a condition that matches against the machine tags
Lennart Poettering [Wed, 20 May 2026 21:23:15 +0000 (23:23 +0200)] 
condition: add a condition that matches against the machine tags

8 days agohostnamectl: add support for tagging the machine
Lennart Poettering [Wed, 20 May 2026 16:44:45 +0000 (18:44 +0200)] 
hostnamectl: add support for tagging the machine

8 days agohostnamectl: port to new --help API
Lennart Poettering [Wed, 20 May 2026 16:32:59 +0000 (18:32 +0200)] 
hostnamectl: port to new --help API

8 days agohostnamed: introduce "machine tags" concept
Lennart Poettering [Wed, 20 May 2026 16:45:12 +0000 (18:45 +0200)] 
hostnamed: introduce "machine tags" concept

For management purposes it's useful to be able to "tag" a machine with
various labels. Let's add a field for that to /etc/machine-info and make
it settable.

Fixes: #38591
8 days agohostnamed: port to regular string_is_safe()
Lennart Poettering [Wed, 20 May 2026 15:03:39 +0000 (17:03 +0200)] 
hostnamed: port to regular string_is_safe()

8 days agotpm2: add nvpcr allocation priorities (#42227)
Lennart Poettering [Thu, 21 May 2026 16:19:39 +0000 (18:19 +0200)] 
tpm2: add nvpcr allocation priorities (#42227)

nvindex space is very scarce, let's hence introduce "priorities" on
nvpcrs, so that if we haven't got enough space for all we have some
control which ones get dropped and which ones kept.

8 days agocore: introduce ConditionFraction= that is true on a certain percantage of the fleet
Lennart Poettering [Thu, 21 May 2026 13:32:24 +0000 (15:32 +0200)] 
core: introduce ConditionFraction= that is true on a certain percantage of the fleet

8 days agoTEST-08-INITRD: Set up exitrd on boot rather than including in image
Daan De Meyer [Thu, 21 May 2026 10:25:03 +0000 (10:25 +0000)] 
TEST-08-INITRD: Set up exitrd on boot rather than including in image

Just copy the initramfs from the VM rather than doing it during
the image build.

8 days agouser-util: return malloc'ed strings in get_user_creds 42184/head
Zbigniew Jędrzejewski-Szmek [Tue, 19 May 2026 21:22:06 +0000 (23:22 +0200)] 
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

8 days agouser-util: stop mangling groupname in get_group_creds
Zbigniew Jędrzejewski-Szmek [Tue, 19 May 2026 15:59:57 +0000 (17:59 +0200)] 
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.

8 days agocore/exec-invoke: fix bogus error code
Zbigniew Jędrzejewski-Szmek [Thu, 21 May 2026 16:01:29 +0000 (18:01 +0200)] 
core/exec-invoke: fix bogus error code

r was bogus here. getusername_malloc() can only fail on oom,
so we can simplify this.

8 days agoTranslations update from Fedora Weblate (#42231)
Luca Boccassi [Thu, 21 May 2026 15:16:33 +0000 (16:16 +0100)] 
Translations update from Fedora Weblate (#42231)

Translations update from [Fedora
Weblate](https://translate.fedoraproject.org) for
[systemd/main](https://translate.fedoraproject.org/projects/systemd/main/).

Current translation status:

![Weblate translation
status](https://translate.fedoraproject.org/widget/systemd/main/horizontal-auto.svg)

8 days agopo: Translated using Weblate (Arabic) 42231/head
joo es [Thu, 21 May 2026 15:01:53 +0000 (15:01 +0000)] 
po: Translated using Weblate (Arabic)

Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: joo es <jonnyse@users.noreply.translate.fedoraproject.org>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/ar/
Translation: systemd/main

8 days agopo: Translated using Weblate (Korean)
김인수 [Thu, 21 May 2026 15:01:50 +0000 (15:01 +0000)] 
po: Translated using Weblate (Korean)

Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: 김인수 <simmon@nplob.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/ko/
Translation: systemd/main

8 days agoUpdate NEWS
Luca Boccassi [Thu, 21 May 2026 15:05:52 +0000 (16:05 +0100)] 
Update NEWS

8 days agotest: cover lingering users surviving a soft-reboot in TEST-82
Rocker Zhang [Thu, 21 May 2026 10:29:24 +0000 (18:29 +0800)] 
test: cover lingering users surviving a soft-reboot in TEST-82

Regression coverage for the soft-reboot linger bug fixed in
9f25feb4ed18 ("logind: keep lingering users at startup-time GC", #41789):
a lingering user's user@.service was started after a hardware reboot but
not after `systemctl soft-reboot`, because logind GC'd the user at
startup before user_start() ran.

On the first boot, enable lingering for the pre-existing testuser and
wait for its user@UID.service to come up. After the first soft-reboot
(which keeps the same persistent rootfs), assert the service is active
again — this is the regression check. Disable lingering again before the
nextroot switch in the second boot so the lingering user doesn't leak
into the later boots' minimal overlay rootfs.

Verified locally in a qemu/KVM VM: passes with the fix present, and with
the fix reverted the second-boot assertion times out (the lingering user
is GC'd in logind startup and user@UID.service never comes back),
confirming the test exercises the bug.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
8 days agoci: add a CI test for nvpcr priorization 42227/head
Lennart Poettering [Thu, 21 May 2026 12:22:29 +0000 (14:22 +0200)] 
ci: add a CI test for nvpcr priorization

8 days agodocs: document the .nvpcr file format superficially
Lennart Poettering [Thu, 21 May 2026 12:22:03 +0000 (14:22 +0200)] 
docs: document the .nvpcr file format superficially

8 days agotpm2-util: be more graceful with nvindex space exhaustion issues
Lennart Poettering [Thu, 21 May 2026 12:21:28 +0000 (14:21 +0200)] 
tpm2-util: be more graceful with nvindex space exhaustion issues

Let's tone down the language, and say how many we skipped.

8 days agosd-dhcp-relay: reimplement DHCP relay agent and drop legacy DHCP relay mode from...
Daan De Meyer [Thu, 21 May 2026 14:23:44 +0000 (16:23 +0200)] 
sd-dhcp-relay: reimplement DHCP relay agent and drop legacy DHCP relay mode from sd-dhcp-server (#42130)

8 days agoIntroduce support for running code in fibers (#39771)
Daan De Meyer [Thu, 21 May 2026 14:21:13 +0000 (16:21 +0200)] 
Introduce support for running code in fibers (#39771)

Traditionally, asynchronous programming in systemd has been achieved
using
sd-event along with the asynchronous interfaces of sd-bus and
sd-varlink.
This works well when the system is reacting to events and all code
triggered
by those events can run without blocking. In these scenarios, the global
Manager object is passed as userdata to the callback, and the callback
can
use the stack as usual, declaring local state and ensuring proper
cleanup via
_cleanup_. Control flow structures, such as loops, work as expected, and
everything runs smoothly.

However, challenges arise when the code needs to perform long-running
operations within these callbacks. Since the system cannot block
execution
within the callback, we can't directly invoke a long-running operation
and
wait for its result without introducing complexities. Instead, we need
to
initiate the long-running task, register for completion with sd-event,
sd-bus, or sd-varlink, and provide a callback to be invoked when the
operation completes.

This callback, however, only receives a single userdata pointer, which
forces us to bundle all local variables into a struct and pass it along
as
part of the callback. On top of that, after queuing the asynchronous
operation, the caller continues executing. As the caller's stack unwinds
when the function exits, the resources and state within the local scope
may
be prematurely cleaned up. Therefore, the struct must store copies of
the
local variables or ensure proper reference counting to prevent premature
resource cleanup.

When multiple long-running operations need to be initiated within a
loop,
the complexity grows further. We must introduce additional shared state
to
track the completion of all operations before we can run any code that
depends on their results.

Furthermore, since the daemon may be shut down at any time, we must
track
the lifecycle of each long-running operation in the global Manager
struct,
ensuring proper cleanup even when stack unwinding can no longer manage
the
resources for us.

Fibers, or green threads, provide a more natural way of handling
asynchronous operations. By enabling cooperative multitasking within a
single thread, fibers allow us to write code that looks like it’s
running
synchronously, but with the ability to yield control at predefined
points,
such as when waiting for long-running tasks to complete.

With fibers, we can simplify the control flow by running asynchronous
operations within a fiber, allowing us to "pause" execution while
waiting
for the long-running operation to finish and then "resume" the operation
once
it's complete. This eliminates the need for multiple callback chains,
extensive state tracking, and the potential pitfalls of stack unwinding.

This commit introduces the ability to execute long-running operations in
a
non-blocking manner while maintaining the simplicity and readability of
synchronous code. The fiber-based approach will significantly improve
the
handling of complex workflows, making the code easier to write and
maintain.

The implementation is based on ucontext.h's makecontext() (with a
fallback
to the venerable sigaltstack() approach on musl),
sigsetjmp()/siglongjmp()
and sd-event. ucontext.h provides us with alternate stacks that we can
switch
between. We use sigsetjmp()/siglongjmp() instead of swapcontext()
because the
latter forcibly saves/restores a per context signal mask every time it
is called.
Using sigsetjmp()/siglongjmp(), we can avoid the unnecessary syscall and
maintain
a per thread signal mask, which makes much more sense than having a per
fiber
signal mask.

The default stack size is the same as a regular thread. Because we
use mmap() to allocate the stack, the memory won't actually be used
until it
is paged in by the kernel, so we don't actually use 8MB per fiber.

To integrate fibers with the event loop, each fiber is assigned a
deferred
event source which resumes the fiber when enabled. The deferred event
source
is oneshot by default so the fiber will run immediately until it yields
or
suspends. If it yields, the deferred event source is enabled again
(oneshot)
immediately. If it suspends, before it suspends, one or more event
sources
are registered with sd-event that will enable the deferred event source
(oneshot) to resume the fiber once the operation it is waiting for
completes.

Yielding or suspending the fiber is done by calling sd_fiber_yield() or
sd_fiber_suspend() respectively. Both of these return zero on success or
any
error value from the async operation that caused the fiber to resume.

This is also how fiber cancellation is implemented. When a fiber is
cancelled,
sd_fiber_yield() and sd_fiber_suspend() will return ECANCELED when the
fiber
is resumed, allowing the fiber to unwind its stack (which allows cleanup
to
happen automatically) and finish.

Instead of having applications work directly with fibers, we hide them
behind
a generic futures interface to represent long-running operations,
regardless of
whether those operations are running on a fiber or not. Aside from
fibers, the
futures library (sd-future) will for example allow waiting for sd-event
sources
and doing sd-bus calls in the background as well. Fibers can suspend
until a
future is ready with sd_fiber_await() or by having the future wake up
the fiber
explicitly in its callback. A future always defaults to waking up the
current
fiber.

Each future kind plugs into the library by providing an sd_future_ops
vtable
(alloc, free, cancel, set_priority). The library treats the impl pointer
returned by alloc() as a black box. Future Implementations retrieve it
via
sd_future_get_private().

A future starts in SD_FUTURE_PENDING and transitions exactly once to
SD_FUTURE_RESOLVED, carrying an integer result. Consumers can react to
that
transition either by installing a one-shot callback with
sd_future_set_callback() (callback-style code) or by waiting on it from
a
fiber via sd_fiber_await() (synchronous-looking fiber code).
sd_fiber_await()
is itself built on a "wait future" that resolves when its target
resolves;
sd_future_new_wait() exposes the same primitive directly so non-fiber
callers
can chain futures without involving a fiber.

Cancellation is cooperative: sd_future_cancel() invokes the future
impl's
cancel callback, which is responsible for tearing down its work and
ultimately
resolving the promise with -ECANCELED. For fiber futures this is what
surfaces as the ECANCELED return from
sd_fiber_yield()/sd_fiber_suspend()
mentioned above.

Fire-and-forget fibers — created by passing a NULL ret to sd_fiber_new()

take a self-reference on their future so they outlive the caller's
scope.
The self-ref is dropped when the fiber resolves. This floating mechanism
(sd_fiber_set_floating()) is restricted to fiber futures because they
uniquely guarantee resolution; allowing it for arbitrary future kinds
would
risk silent leaks for kinds that may never resolve.

Note that fiber cleanup depends on the runtime operating normally. Each
fiber's _cleanup_-style cleanups live on the fiber's own stack and run
only when the fiber is resumed and allowed to unwind, which requires a
working event loop to drive it to completion. The exit event source
registered for top-level fibers ensures unwind on a normal
sd_event_exit(),
but if the event loop itself terminates abnormally (e.g. an
unrecoverable
allocation failure mid-dispatch) before all fibers have resolved, their
stacks never unwind and any resources they own leak.

The code lives in libsystemd as sd-future (not exported) for the
following reasons:
- We may want to make this a public libsystemd API in the future
- The code can't live in src/basic as it makes heavy use of sd-event
- The code can't live in src/shared as sd-bus and sd-event make use of
it

The log and log-context headers are updated with functions to allow
fibers to have their own log prefix and log context.

8 days agonvpcr: define some reasonable priorities for the nvpcrs we already defined
Lennart Poettering [Thu, 21 May 2026 12:21:02 +0000 (14:21 +0200)] 
nvpcr: define some reasonable priorities for the nvpcrs we already defined

8 days agoanalyze: show priority in 'nvpcrs' output
Lennart Poettering [Thu, 21 May 2026 12:20:37 +0000 (14:20 +0200)] 
analyze: show priority in 'nvpcrs' output

8 days agotpm2-setup: introduce a 'priority' concept for NvPCRs
Lennart Poettering [Thu, 21 May 2026 12:19:42 +0000 (14:19 +0200)] 
tpm2-setup: introduce a 'priority' concept for NvPCRs

8 days agoupdatectl: Apply --no-ask-password argument to polkit agent
Philip Withnall [Thu, 21 May 2026 10:40:19 +0000 (11:40 +0100)] 
updatectl: Apply --no-ask-password argument to polkit agent

Accidentally missed out of commit
8c0f9073c7da808461acfc016cc291e4aba9c1a2.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: 8c0f9073c7da808461acfc016cc291e4aba9c1a2
8 days agoinclude/uapi: add linux/openat2.h (#42220)
Zbigniew Jędrzejewski-Szmek [Thu, 21 May 2026 11:29:28 +0000 (13:29 +0200)] 
include/uapi: add linux/openat2.h (#42220)

We include the header through src/include/override/fcntl.h, hence we should
have the latest copy of the header.

(E.g. compilation fails with musl-libc-1.2.5-6.fc44.x86_64 and older kernel
headers.)

8 days agocore: add FileDescriptorStorePreserve=on-success option (#42160)
Luca Boccassi [Thu, 21 May 2026 11:08:33 +0000 (12:08 +0100)] 
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.

8 days agotest-btrfs: skip info test when GET_SUBVOL_INFO ioctl is unsupported
Daan De Meyer [Wed, 20 May 2026 20:46:40 +0000 (20:46 +0000)] 
test-btrfs: skip info test when GET_SUBVOL_INFO ioctl is unsupported

On 32-bit userspace running against a 64-bit kernel
BTRFS_IOC_GET_SUBVOL_INFO returns -ENOTTY: struct
btrfs_ioctl_get_subvol_info_args embeds four btrfs_ioctl_timespec
values, and that timespec struct (__u64 sec; __u32 nsec) packs to 12
bytes on i386 but 16 on x86_64 due to differing __u64 alignment.
sizeof(struct) is part of the ioctl cmd number via _IOR(), so the cmd
emitted by 32-bit userspace doesn't match the case label compiled by
the 64-bit kernel and the switch falls through to -ENOTTY.

btrfs already handles this exact class of bug for
BTRFS_IOC_SET_RECEIVED_SUBVOL via a btrfs_ioctl_timespec_32 struct
plus a _32 cmd alias in fs/btrfs/ioctl.c, but GET_SUBVOL_INFO (added
in 2018, four years after that fix) didn't get the same treatment.
Until a kernel patch lands the test can't exercise the ioctl on
32-bit, so convert TEST(info) to TEST_RET(info) and return
EXIT_TEST_SKIP with a clear message when -ENOTTY comes back. The
other tests in the file use ioctls that already have working compat
paths and remain unaffected.

8 days agonetwork: several fixlets for NDisc (#42218)
Luca Boccassi [Thu, 21 May 2026 11:05:34 +0000 (12:05 +0100)] 
network: several fixlets for NDisc (#42218)

Unfortunately, previously the path to test-ndisc-send has been wrong, so
some test cases have not been checked in our mkosi CIs. And two test
cases have been broken.

The test case `test_ndisc_redirect` was not updated when the logic in
networkd was changed by 9142bd5a8e9ed94ecbb1e335305e24760b90ad2a. The
change itself should be OK. So, the test case is updated.

The test case `test_ndisc_mtu` was broken when the commit
32417c172383847ec78b672c537594e3efe8f0e0 is merged. The commit is not
correct, as we cannot set IPv6 MTU larger than interface MTU. So, the
offending commit is reverted.

8 days agocore: better errors and more fields for io.systemd.Unit.StartTransient (#42161)
Daan De Meyer [Thu, 21 May 2026 11:03:29 +0000 (13:03 +0200)] 
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).

8 days agomath-util: round to declared FP precision consistently across architectures
Daan De Meyer [Wed, 20 May 2026 12:37:15 +0000 (12:37 +0000)] 
math-util: round to declared FP precision consistently across architectures

Add -fexcess-precision=standard so gcc inserts ISO C99 conformant
rounding at assignments, casts, and returns — without it, double values
on x87 happily stay at 80-bit extended precision across operations and
diverge from the SSE/x86_64 behavior, making strict equality comparisons
architecture-dependent.

The flag doesn't fully cover x87: per gcc PR#323
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323), a function return
value carried in ST(0) can arrive at the caller still at 80-bit, so a
double that ought to compare equal to a same-magnitude literal picks up
extra mantissa bits and doesn't. Wrap fp_equal in volatile-double
temporaries to force a memory roundtrip — the only operation that
reliably truncates on x87 — so its callers get consistent results
regardless of how the operands were produced.

Add a TEST(fp_equal) case that exercises the previously-broken pattern:
a runtime 1.0/10.0 computed inside a noinline helper, returned across
the function ABI boundary, then compared against the literal 0.1.
Without the volatile truncation this assertion fails on 32-bit gcc.

8 days agosysupdate: Fix a minor typo in the polkit policy 42209/head
Philip Withnall [Wed, 20 May 2026 16:10:06 +0000 (17:10 +0100)] 
sysupdate: Fix a minor typo in the polkit policy

‘cleanup’ is a noun; ‘clean up’ is a verb.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
8 days agosysupdate: Add separate polkit actions for cancellation
Philip Withnall [Wed, 20 May 2026 16:08:03 +0000 (17:08 +0100)] 
sysupdate: Add separate polkit actions for cancellation

This allows us to have a separate, more permissive, policy for
cancelling ongoing sysupdate jobs. The new default policy for
cancellation actions is to allow them for the active user, without admin
authentication, because typically the user can just pull the plug on the
computer to cancel a job anyway.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: https://github.com/systemd/systemd/issues/38568
8 days agotest-qmp-client: run mock QMP servers as fibers on the shared event loop 39771/head
Daan De Meyer [Fri, 24 Apr 2026 09:49:10 +0000 (09:49 +0000)] 
test-qmp-client: run mock QMP servers as fibers on the shared event loop

The mock servers used to be driven out-of-band: each test created a
socketpair, forked a child, ran a hand-coded request/response script
against the raw fd, and sent SIGTERM to tear it down. That worked but
required pidref/process-util/signal plumbing in every test, two
distinct execution contexts that couldn't share state, and a JsonStream
attached to the mock side that pretended to be event-loop-driven while
actually being driven manually via blocking reads.

Now that JsonStream suspends when on a fiber, the mocks can live
inside the same process and event loop as the client. Each mock is
rewritten as an sd-fiber that runs alongside the client fiber: so the
mock fiber yields on I/O and the event loop schedules the client in the
meantime. Both sides progress cooperatively, no fork/SIGTERM/PID tracking,
no manual phase tracking.

Two cleanups fall out of the rewrite:

- A QMP_TEST(name, mock_fn) { ... } macro encapsulates the per-test
  scaffolding (event loop, socketpair, mock fiber spawn, exit-on-idle
  shim) and injects an already-connected QmpClient *client into the
  test body. Each test now reads as a flat sequence of
  qmp_client_call() invocations against that client.

- Repeated mock command/reply scripting is factored into
  mock_qmp_expect(), mock_qmp_reply(), mock_qmp_expect_and_reply(),
  mock_qmp_handshake(), and mock_qmp_query_status_running(). The
  greeting JSON is built with sd_json_buildo() instead of being parsed
  from a literal.

The file shrinks from 756 to 494 lines, mostly through deletions.

8 days agoqmp-client: add fiber-aware call paths
Daan De Meyer [Fri, 24 Apr 2026 09:49:02 +0000 (09:49 +0000)] 
qmp-client: add fiber-aware call paths

The synchronous qmp_client_call() pumps the event loop until its reply
arrives, pinning the parsed reply on c->current so it can hand out
borrowed pointers to the caller. That model only fits one in-flight
sync call: a second qmp_client_call() on the same client clears
c->current before issuing its own send, invalidating the first
caller's borrowed pointers. On a single-threaded event loop that was
fine, but with fibers two concurrent calls on the same client can
interleave through the pump (json_stream_wait() suspends the running
fiber) and trample each other.

To fix this, make qmp_client_call() detect when it's running on a fiber
whose event loop matches the client and transparently delegate to
qmp_client_call_suspend(), which makes use of a new QmpFuture to allow
multiple concurrent calls to qmp_client_call().

To make this work concurrently, we also change qmp_client_call() to
hand out references and copies of errors so that we don't have to store
the borrowed pointers we hand out in the QmpClient struct.

8 days agosd-varlink: make sd-varlink fiber-aware
Daan De Meyer [Tue, 14 Apr 2026 08:54:49 +0000 (08:54 +0000)] 
sd-varlink: make sd-varlink fiber-aware

Add varlink_server_bind_fiber() and varlink_server_bind_fiber_many()
in varlink-util.{c,h} for registering a method handler that should
run on a dedicated fiber per dispatch. The fiber-bound methods live
in a separate s->fiber_methods map alongside the regular s->methods;
bind_internal()/bind_many_internal() are factored out so the regular
and fiber bind variants share their parsing/insertion code.
Registering the same method in both maps is rejected because the
dispatcher consults the regular map first and would otherwise
silently shadow the fiber binding.

varlink_dispatch_fiber() builds a VarlinkFiberData (refs to the
connection, parameters, and method name), spawns a fiber via
sd_fiber_new(), and makes the future floating so the fiber
self-manages its lifetime — neither the dispatcher nor the
connection has to track it. The fiber's priority is set to one
below the connection's quit event source so that on graceful
shutdown the fiber's exit handler fires (and runs its cleanup)
before varlink's quit_callback() closes the connection underneath
it; this is what lets a fiber-bound handler reply or flush its
sentinel on a still-open connection during shutdown.

The connection state transitions are reordered so they happen before
the fiber spawn rather than after the synchronous callback returns:
the fiber runs after dispatch has already moved past PROCESSING, which
matches the behaviour expected for a deferred reply (the fiber may
either reply immediately, or stash the connection and reply later, in
which case the post-callback logic treats it as a PENDING_METHOD).

Note that all the synchronous varlink APIs (sd_varlink_call() and friends)
already behave properly when on a fiber because they call json_stream_wait()
which calls ppoll_usec() which we already fixed to suspend when called from
a fiber.

The client/server varlink tests are migrated to fibers (threads → mock
server fibers on the same event loop) to exercise the new paths.

8 days agosd-bus: make sd-bus fiber-aware
Daan De Meyer [Mon, 11 May 2026 14:27:34 +0000 (16:27 +0200)] 
sd-bus: make sd-bus fiber-aware

Two changes to teach sd-bus how to behave when called from a fiber, in
order of increasing depth:

2. sd_bus_call() now redirects to a new bus_call_suspend() helper when
   the caller is a fiber whose event loop is the same one the bus is
   attached to. The plain bus_poll() path serializes all bus traffic on
   the slot's reply (only one method call can be in flight per
   sd_bus*), which would defeat the point of running multiple fibers
   against one bus. bus_call_suspend() builds on the async sd-bus API:
   it wraps the call in a new BusFuture (sd-bus/bus-future.{c,h}) that
   resolves when the reply or method-error arrives, lets the fiber
   await that future, and surfaces the reply to the caller via
   future_get_bus_reply(). Because the futures live on the event loop
   rather than a per-bus slot, multiple fibers can drive concurrent
   method calls against the same bus.

3. A new private SD_BUS_VTABLE_METHOD_FIBER flag dispatches a vtable
   method handler on its own fiber, so handlers are free to use
   sd_bus_call() against the same bus, sd_fiber_sleep(), loop_read(),
   etc. without stalling the event loop for other connections or
   handlers. The flag stays out of sd-bus-vtable.h (its bit value is
   reserved there to prevent collisions) — the fiber runtime is a
   systemd-internal implementation detail.

Lifecycle of fiber-dispatched handlers is tracked on the bus itself: a
new bus->fiber_futures set holds a ref to each in-flight handler.
bus_enter_closing() cancels every entry and process_closing() returns
with the bus still in CLOSING state until the set drains, so we can be
sure no fiber handler outlives the bus. bus_fiber_resolved() removes
the entry on completion. bus_free()'s assert(set_isempty()) makes the
invariant load-bearing.

Note that plain sd_bus_call() already works correctly on a fiber as it
calls ppoll_usec() which has already been modified to suspend when
running on a fiber.

To exercise these changes the existing thread-based client/server
sd-bus tests (test-bus-chat, test-bus-objects, test-bus-peersockaddr,
test-bus-server, test-bus-watch-bind) are migrated to fibers, and a
new test-bus-fiber is added that covers SD_BUS_VTABLE_METHOD_FIBER —
including handlers that issue nested sd_bus_call() on the same bus, the
cancel-on-close path, and concurrent dispatches across multiple fibers.

8 days agosd-event: suspend instead of blocking when sd_event_run() runs on a fiber
Daan De Meyer [Mon, 23 Mar 2026 09:15:27 +0000 (10:15 +0100)] 
sd-event: suspend instead of blocking when sd_event_run() runs on a fiber

sd_event_run() blocks the calling thread on the event loop's epoll fd
until something happens. When the caller is a fiber, that's the wrong
behaviour: blocking the thread also stalls every other fiber and the
outer event loop driving them. The most common way to hit this is a
fiber that creates its own inner event loop (e.g. a server-style fiber
that wants to dispatch its own sources independently of whatever loop
the test or supervising fiber is running on) — with the existing
implementation the inner sd_event_run() would hold the thread while the
outer scheduler should be free to advance other fibers.

Add an event_run_suspend() variant in sd-event/event-future.c that
performs the same prepare/wait/dispatch dance, but when the fast path
finds nothing ready it (a) creates an IO future watching the inner
event loop's epoll fd on the *outer* event loop, (b) optionally creates
a time future for the timeout, and (c) suspends the fiber. When either
future fires the fiber is resumed and the prepare/wait/dispatch sequence
runs once more to actually dispatch what's pending. sd_event_run()
checks sd_fiber_is_running() and delegates to this variant when on a
fiber; profile_delays accounting is intentionally skipped on that path
since the underlying prepare/wait/dispatch primitives already account
for themselves.

8 days agosd-future: make src/basic blocking helpers fiber-aware
Daan De Meyer [Sat, 25 Apr 2026 20:06:54 +0000 (22:06 +0200)] 
sd-future: make src/basic blocking helpers fiber-aware

Some helpers in src/basic — ppoll_usec_full() (used by fd_wait_for_event()),
loop_read(), loop_read_exact(), loop_write_full() and
pidref_wait_for_terminate_full() — block the calling thread. That's the
right behaviour outside a fiber but not inside one, where blocking the
thread also stalls every other fiber running on the same event loop.
Rewriting every caller to pick a fiber or non-fiber variant explicitly
would be a lot of churn and would split otherwise-shared code paths in
two.

Instead, the helpers detect at runtime whether they're running on a fiber
and dispatch to a suspending variant when they are. FiberOps in
fiber-ops.h holds five function pointers (ppoll, read, write, timeout,
cancel_wait_unref); a fiber_ops global constant is populated whenever we
enter a fiber with functions that delegate to suspending variants of common
syscalls. With this approach, the variants themselves stay in libsystemd
which is required because they make use of sd-event.

- loop_read()/loop_read_exact() take the fiber read hook on a fiber
  unless the caller asked for a non-blocking attempt (do_poll=false) and
  the fd is already non-blocking — in that case we fall through to read()
  to preserve the existing return-EAGAIN-immediately semantic. The hook
  itself suspends on EAGAIN until data is available, so neither the
  do_poll knob nor the explicit fd_wait_for_event() retry loop are
  needed on the fiber path.

- loop_write_full() likewise takes the fiber write hook on a fiber,
  except when timeout=0 with an already-non-blocking fd (preserving the
  fast-return-EAGAIN semantic). The fiber path runs inside a
  FIBER_OPS_TIMEOUT() scope so the caller's timeout is honoured via a
  deadline future, mirroring SD_FIBER_TIMEOUT() but reachable from
  src/basic without pulling in sd-future.h.

- pidref_wait_for_terminate_full() polls the pidfd via fd_wait_for_event()
  before each waitid() when either a finite timeout is set or we're on a
  fiber, and requires pidref->fd >= 0 in those cases (returning
  -ENOMEDIUM otherwise — extending the rule that already applied to
  finite timeouts). The poll suspends the fiber via the ppoll hook above;
  the subsequent waitid() doesn't block because the pidfd is already
  signalled.

8 days agosd-future: add fiber-aware non-blocking I/O wrappers
Daan De Meyer [Sat, 25 Apr 2026 20:31:58 +0000 (22:31 +0200)] 
sd-future: add fiber-aware non-blocking I/O wrappers

Add a family of sd_fiber_*() I/O wrappers that, when called from a
fiber, behave like blocking I/O from the caller's perspective but
yield to the event loop instead of blocking the thread:

  sd_fiber_read / sd_fiber_write
  sd_fiber_readv / sd_fiber_writev
  sd_fiber_recv / sd_fiber_send
  sd_fiber_connect
  sd_fiber_recvmsg / sd_fiber_sendmsg
  sd_fiber_recvfrom / sd_fiber_sendto
  sd_fiber_accept
  sd_fiber_ppoll

Most of them share a single helper, fiber_io_operation(), which when
invoked outside a fiber falls through to the underlying syscall
directly, preserving the regular blocking behaviour. Inside a fiber
the helper flips the fd to non-blocking (restoring its original mode
on return), tries the syscall once on the fast path, and on EAGAIN/
EWOULDBLOCK creates an sd-event-backed IO future via future_new_io(),
suspends the fiber, and retries the syscall once the event source
fires.

future_new_io() itself is added to sd-event/event-future.{c,h} as a
new IoFuture kind. It wraps sd_event_add_io() into an sd_future:
oneshot enable, EPOLLERR translated via SO_ERROR (suppressed for
non-sockets), and the fd duplicated with F_DUPFD_CLOEXEC to avoid
EEXIST when multiple sources watch the same descriptor.

Together these let fiber-using code write straight-line socket and
pipe I/O without bundling state into callbacks.

8 days agoIntroduce support for running code in fibers
Daan De Meyer [Wed, 12 Nov 2025 16:53:47 +0000 (17:53 +0100)] 
Introduce support for running code in fibers

Traditionally, asynchronous programming in systemd has been achieved using
sd-event along with the asynchronous interfaces of sd-bus and sd-varlink.
This works well when the system is reacting to events and all code triggered
by those events can run without blocking. In these scenarios, the global
Manager object is passed as userdata to the callback, and the callback can
use the stack as usual, declaring local state and ensuring proper cleanup via
_cleanup_. Control flow structures, such as loops, work as expected, and
everything runs smoothly.

However, challenges arise when the code needs to perform long-running
operations within these callbacks. Since the system cannot block execution
within the callback, we can't directly invoke a long-running operation and
wait for its result without introducing complexities. Instead, we need to
initiate the long-running task, register for completion with sd-event,
sd-bus, or sd-varlink, and provide a callback to be invoked when the
operation completes.

This callback, however, only receives a single userdata pointer, which
forces us to bundle all local variables into a struct and pass it along as
part of the callback. On top of that, after queuing the asynchronous
operation, the caller continues executing. As the caller's stack unwinds
when the function exits, the resources and state within the local scope may
be prematurely cleaned up. Therefore, the struct must store copies of the
local variables or ensure proper reference counting to prevent premature
resource cleanup.

When multiple long-running operations need to be initiated within a loop,
the complexity grows further. We must introduce additional shared state to
track the completion of all operations before we can run any code that
depends on their results.

Furthermore, since the daemon may be shut down at any time, we must track
the lifecycle of each long-running operation in the global Manager struct,
ensuring proper cleanup even when stack unwinding can no longer manage the
resources for us.

Fibers, or green threads, provide a more natural way of handling
asynchronous operations. By enabling cooperative multitasking within a
single thread, fibers allow us to write code that looks like it’s running
synchronously, but with the ability to yield control at predefined points,
such as when waiting for long-running tasks to complete.

With fibers, we can simplify the control flow by running asynchronous
operations within a fiber, allowing us to "pause" execution while waiting
for the long-running operation to finish and then "resume" the operation once
it's complete. This eliminates the need for multiple callback chains,
extensive state tracking, and the potential pitfalls of stack unwinding.

This commit introduces the ability to execute long-running operations in a
non-blocking manner while maintaining the simplicity and readability of
synchronous code. The fiber-based approach will significantly improve the
handling of complex workflows, making the code easier to write and maintain.

The implementation is based on ucontext.h's makecontext() (with a fallback
to the venerable sigaltstack() approach on musl), sigsetjmp()/siglongjmp()
and sd-event. ucontext.h provides us with alternate stacks that we can switch
between. We use sigsetjmp()/siglongjmp() instead of swapcontext() because the
latter forcibly saves/restores a per context signal mask every time it is called.
Using sigsetjmp()/siglongjmp(), we can avoid the unnecessary syscall and maintain
a per thread signal mask, which makes much more sense than having a per fiber
signal mask.

The default stack size is the same as a regular thread. Because we
use mmap() to allocate the stack, the memory won't actually be used until it
is paged in by the kernel, so we don't actually use 8MB per fiber.

To integrate fibers with the event loop, each fiber is assigned a deferred
event source which resumes the fiber when enabled. The deferred event source
is oneshot by default so the fiber will run immediately until it yields or
suspends. If it yields, the deferred event source is enabled again (oneshot)
immediately. If it suspends, before it suspends, one or more event sources
are registered with sd-event that will enable the deferred event source
(oneshot) to resume the fiber once the operation it is waiting for completes.

Yielding or suspending the fiber is done by calling sd_fiber_yield() or
sd_fiber_suspend() respectively. Both of these return zero on success or any
error value from the async operation that caused the fiber to resume.

This is also how fiber cancellation is implemented. When a fiber is cancelled,
sd_fiber_yield() and sd_fiber_suspend() will return ECANCELED when the fiber
is resumed, allowing the fiber to unwind its stack (which allows cleanup to
happen automatically) and finish.

Instead of having applications work directly with fibers, we hide them behind
a generic futures interface to represent long-running operations, regardless of
whether those operations are running on a fiber or not. Aside from fibers, the
futures library (sd-future) will for example allow waiting for sd-event sources
and doing sd-bus calls in the background as well. Fibers can suspend until a
future is ready with sd_fiber_await() or by having the future wake up the fiber
explicitly in its callback. A future always defaults to waking up the current
fiber.

Each future kind plugs into the library by providing an sd_future_ops vtable
(alloc, free, cancel, set_priority). The library treats the impl pointer
returned by alloc() as a black box. Future Implementations retrieve it via
sd_future_get_private().

A future starts in SD_FUTURE_PENDING and transitions exactly once to
SD_FUTURE_RESOLVED, carrying an integer result. Consumers can react to that
transition either by installing a one-shot callback with
sd_future_set_callback() (callback-style code) or by waiting on it from a
fiber via sd_fiber_await() (synchronous-looking fiber code). sd_fiber_await()
is itself built on a "wait future" that resolves when its target resolves;
sd_future_new_wait() exposes the same primitive directly so non-fiber callers
can chain futures without involving a fiber.

Cancellation is cooperative: sd_future_cancel() invokes the future impl's
cancel callback, which is responsible for tearing down its work and ultimately
resolving the promise with -ECANCELED. For fiber futures this is what
surfaces as the ECANCELED return from sd_fiber_yield()/sd_fiber_suspend()
mentioned above.

Fire-and-forget fibers — created by passing a NULL ret to sd_fiber_new() —
take a self-reference on their future so they outlive the caller's scope.
The self-ref is dropped when the fiber resolves. This floating mechanism
(sd_fiber_set_floating()) is restricted to fiber futures because they
uniquely guarantee resolution; allowing it for arbitrary future kinds would
risk silent leaks for kinds that may never resolve.

Note that fiber cleanup depends on the runtime operating normally. Each
fiber's _cleanup_-style cleanups live on the fiber's own stack and run
only when the fiber is resumed and allowed to unwind, which requires a
working event loop to drive it to completion. The exit event source
registered for top-level fibers ensures unwind on a normal sd_event_exit(),
but if the event loop itself terminates abnormally (e.g. an unrecoverable
allocation failure mid-dispatch) before all fibers have resolved, their
stacks never unwind and any resources they own leak.

The code lives in libsystemd as sd-future (not exported) for the following reasons:
- We may want to make this a public libsystemd API in the future
- The code can't live in src/basic as it makes heavy use of sd-event
- The code can't live in src/shared as sd-bus and sd-event make use of it

The log and log-context headers are updated with functions to allow
fibers to have their own log prefix and log context.

8 days agodocs: extend credentials docs with notes about imds
Lennart Poettering [Thu, 21 May 2026 08:11:53 +0000 (10:11 +0200)] 
docs: extend credentials docs with notes about imds

8 days agocore: add FileDescriptorStorePreserve=on-success option 42160/head
Luca Boccassi [Mon, 18 May 2026 14:47:32 +0000 (15:47 +0100)] 
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.

8 days agotest: avoid test-fdstore failing units when exiting
Luca Boccassi [Mon, 18 May 2026 14:49:23 +0000 (15:49 +0100)] 
test: avoid test-fdstore failing units when exiting

This is used as payload, so ensure the wrapping unit/container
doesn't register a failure when this exits

Follow-up for 9de91f0f4c715b278637af8b73cabac892d7e000

8 days agocleanup: VLAN Id -> VLAN ID
Sebastian Bernardt [Sat, 18 Apr 2026 11:31:04 +0000 (21:31 +1000)] 
cleanup: VLAN Id -> VLAN ID

"VLAN ID" is used throughout the documentation and codebase, but appears
(when present) in `networkctl status` tables as `VLan Id`.

8 days agonetwork: restart DHCPv6, NDisc, and RADV when tracked IPv6LL is dropped
Aritra Basu [Tue, 21 Apr 2026 23:09:20 +0000 (19:09 -0400)] 
network: restart DHCPv6, NDisc, and RADV when tracked IPv6LL is dropped

When the tracked IPv6 link-local address is removed, networkd clears
link->ipv6ll_address, but keeps DHCPv6, NDisc, and RADV running. These
engines keep using a stale source identity which affects the following:
- DHCPv6 client continues to send Solicit/Renew/Rebind from a nonexistent
  source address.
- NDisc continues to send Router Solicitations from a nonexistent source
  address. Router Advertisements cannot be received properly.
- RADV continues to advertise with a stale source address. This can lead
  to downstream hosts configuring invalid routes.
- DHCP-PD prefixes remain configured without a valid upstream DHCPv6 path.

Added link_ipv6ll_lost() to stop IPv6 dynamic engines and related states:
- sd_dhcp6_client_stop()
- ndisc_stop() + ndisc_flush()
- sd_radv_stop()

This is called from address_drop() when the dropped address matches the
tracked IPv6LL. After clearing the tracked address, it scans for another
ready link-local address on the interface. If found, this is set as
link->ipv6ll_address and link_ipv6ll_gained() is called to restart the
engines with the new source identity.

This resolves the FIXME in address_drop().

Signed-off-by: Aritra Basu <aritrbas+gh@cisco.com>
8 days agoNEWS: mention new DHCP relay agent 42130/head
Yu Watanabe [Tue, 12 May 2026 06:15:08 +0000 (15:15 +0900)] 
NEWS: mention new DHCP relay agent

8 days agosd-dhcp-server: drop legacy DHCP relay mode
Yu Watanabe [Sun, 3 May 2026 23:43:41 +0000 (08:43 +0900)] 
sd-dhcp-server: drop legacy DHCP relay mode

8 days agonetwork: drop use of legacy DHCP relay agent in sd-dhcp-server
Yu Watanabe [Sun, 3 May 2026 23:29:51 +0000 (08:29 +0900)] 
network: drop use of legacy DHCP relay agent in sd-dhcp-server

Then, this deprecates
- BindToInterface=
- RelayTarget=
- RelayAgentCircuitId=
- RelayAgentRemoteId=
settings in [DHCPServer] section.
These are gracefully translated as new settings.

8 days agoman: document DHCP relay configuration
Yu Watanabe [Sun, 10 May 2026 23:56:40 +0000 (08:56 +0900)] 
man: document DHCP relay configuration

8 days agotest-network: add test case for DHCP relay
Yu Watanabe [Sun, 10 May 2026 22:48:27 +0000 (07:48 +0900)] 
test-network: add test case for DHCP relay