Commit Graph
88878 Commits
Author SHA1 Message Date
Yu Watanabe ff32569f2a sd-dhcp-client: set TOS and socket priority by default
Also this renames sd_dhcp_client_set_service_type() to _set_ip_service_type().
2026-05-17 01:34:44 +09:00
Yu Watanabe e7c550895a sd-dhcp-client: split out setting anonymize parameter
No effective functional change. Just refactoring.
2026-05-17 01:33:43 +09:00
Yu Watanabe b2e64f53b7 sd-dhcp-client: use new message parser (#42123)
In 26b7c5ff3b, we introduced a new parser
for received DHCP message, but it was not used at that time. This PR
replaces the legacy parser with the new one, and makes the fuzzer also
use the new parser.
2026-05-17 00:33:43 +09:00
Zbigniew Jędrzejewski-Szmek d71c1e7d89 Convert machinectl to option and verb macros (#42117) 2026-05-16 17:18:10 +02:00
Zbigniew Jędrzejewski-Szmek 3b37439afb machinectl: convert to OPTION and VERB macros
For the shell verb we want switches specified after the program name to
be passed to the program to execute, not processed by us. Mirror the
approach in 'userdbctl ssh-authorized-keys': start with
OPTION_PARSER_RETURN_POSITIONAL_ARGS, then lates switch to
STOP_AT_FIRST_NONOPTION for "shell" or NORMAL otherwise.

VERB declarations are placed directly above each function; functions
that dispatch multiple verb names get stacked VERB() declarations.
chainload_importctl() now takes the args strv instead of relying on the
global optind.

--help output is mostly the same.
--no-pager/--no-legend/--no-ask-password/-q/--quiet are now at the end.
bind-volume/unbind-volume are documented.

Fixes c9f461a806.

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 15:59:15 +02:00
Zbigniew Jędrzejewski-Szmek cab5c5ef81 shared/verbs: add VERB_DEFAULT_NOARG 2026-05-16 15:54:18 +02:00
Yu Watanabe 8de24db5de sd-dhcp-client: do not trigger assertion when running on interface with small MTU
This also drops spurious default value. If mtu is unset, now the correct
default value is set in client_new_message() in dhcp-client-send.c.
2026-05-16 22:34:25 +09:00
Yu Watanabe 1a0f2c1fb2 sd-dhcp-client: drop unnecessary T1/T2 adjustment logic
It is already done in client_parse_ack() -> dhcp_lease_new_from_message().
2026-05-16 22:34:25 +09:00
Yu Watanabe de079ebc04 sd-dhcp-lease: drop unused dhcp_lease_unref_and_replace() 2026-05-16 22:34:25 +09:00
Yu Watanabe 0435151bc8 sd-dhcp-client: use dhcp_client_parse_message()
This also unify two IO event source handlers.
2026-05-16 22:34:25 +09:00
Yu Watanabe fcf2de89bb fuzz-dhcp-client: fuzz dhcp_client_parse_message()
Also, if the fuzzing engine provides a valid message, then try to build
json variant and UDP payload from the parsed message. We will drop
dhcp_lease_save() and dhcp_lease_load(), hence the tests for them are
dropped.
2026-05-16 22:34:25 +09:00
Yu Watanabe 6ae696a956 socket-util: extend the buffer in sockaddr_union to make it consistent with hw_addr_data
Concerned by Claude:
https://github.com/systemd/systemd/pull/42119#discussion_r3251133516
2026-05-16 22:33:40 +09:00
Yu Watanabe 8fe6094450 dhcp-message: introduce dhcp_message_send_{udp,raw}() 2026-05-16 22:33:00 +09:00
Daan De Meyer a0a6a614ce network: preparation for using serialized DHCP message in Describe() method (#42122) 2026-05-16 14:17:58 +02:00
Fco. Javier F. Serrador 980e4132ac po: Translated using Weblate (Spanish)
Currently translated at 100.0% (266 of 266 strings)

Co-authored-by: Fco. Javier F. Serrador <fserrador@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/es/
Translation: systemd/main
2026-05-16 13:16:50 +01:00
Luca Boccassi c043b90187 Revert "shared/pager: add support for more(1) pager in secure mode" 2026-05-16 09:38:25 +09:00
Yu Watanabe ace3a7b500 udev,sd-device: drop old database support (#40801)
Closes #40776.
2026-05-16 08:26:16 +09:00
Yu Watanabe c0e40b14ad networkctl: load information about DHCP client from varlink
By the previous commit, networkd now exposes the received DHCP message
in the Descibe() DBus/Varlink method. Let's make networkctl deserialize
the DHCP message and use it where necessary.
2026-05-16 08:05:01 +09:00
Yu Watanabe 29e221c9e6 network: append DHCP message in json output
Also, get private options from sd_dhcp_message object if sd_dhcp_lease
has it.

With this change, networkctl will be able to use the serialized DHCP
message object. Preparation for later changes.
2026-05-16 08:05:01 +09:00
Yu Watanabe 26b7c5ff3b sd-dhcp-lease: introduce dhcp_client_parse_message()
It parses a received DHCP message and create corresponding sd_dhcp_lease
object for the message. Internally, it uses sd_dhcp_message object.

Note, the new parser is not used yet. The currently used one will be
replaced in later commit.
2026-05-16 08:04:45 +09:00
Yu Watanabe f39c071f31 dhcp-client-send: introduce dhcp_client_send_message()
This internally uses sd_dhcp_message object, and replaces functions
for creating and sending DHCP messages.

By using sd_dhcp_message internally, now we can correctly send long
(> 255 bytes) option data that cannot be fit in a single DHCP option TLV.

This also fixes the value in DHCP option 57 (Maximum Message Size).
Previously the IP and UDP header size is subtracted from the interface
MTU, but it should not.

Except for the above, this should not change any effective behaviors.
2026-05-16 08:03:15 +09:00
Yu Watanabe 206f0391a6 varlink: MethodNotImplemented: drop extraneous dot; vl_error_MethodNotFound: an method (#42112) 2026-05-16 05:10:38 +09:00
Luca Boccassi 446b0393ff test-network: retry networkctl status in wait_operstate()
networkctl status may transiently fail right after start_networkd() because networkd has not yet picked up the freshly-created link from the kernel. The retry loop in wait_operstate() did not catch the resulting subprocess.CalledProcessError, so the test aborted on the first attempt instead of retrying for the configured timeout.

Observed in TEST-85-NETWORK-NetworkdBridgeTests, subtest test_bridge_configure_without_carrier[no-slave]:

  [   19.600156] systemd-networkd-tests.py[526]: Failed to issue io.systemd.Network.Link.Describe() varlink call: Invalid argument
  [   53.124982] systemd[1]: systemd-networkd.service: Changed start -> running
  [   53.336167] systemd-networkd-tests.py[526]: ERROR: test_bridge_configure_without_carrier (__main__.NetworkdBridgeTests.test_bridge_configure_without_carrier) (test='no-slave')
  [   53.336167] systemd-networkd-tests.py[526]:     self.wait_operstate('bridge99', operstate=r'(no-carrier|routable)', setup_state=None, setup_timeout=30)
  [   53.336167] systemd-networkd-tests.py[526]: subprocess.CalledProcessError: Command '['/usr/bin/networkctl', '-n', '0', 'status', 'bridge99']' returned non-zero exit status 1.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 05:08:35 +09:00
Daan De Meyer 047036bf54 meson: Drop two unnecessary dependencies 2026-05-15 22:05:07 +02:00
Daan De Meyer 0bd979025a meson: drop vestigial libgpg-error dependency
libgpg-error was added in 2017 (commit 76c8741060, Michael Biebl) to
gate HAVE_GCRYPT on its presence because src/resolve referenced
libgpg-error directly at the time. That usage is long gone — no source
file references any gpg-error API today — so the dependency only served
to fail HAVE_GCRYPT detection when gpg-error-dev wasn't installed.

libgcrypt's pkg-config Requires already pulls in the gpg-error headers
(via the transitive #include <gpg-error.h> in <gcrypt.h>), so dropping
the dep doesn't break compilation.
2026-05-15 22:04:39 +02:00
Zbigniew Jędrzejewski-Szmek 6b8c3af359 machinectl: reorder cases in parse_argv() to match order in --help
--no-pager, --no-legend, --no-ask-password, --quiet are shifted to
the end.

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 21:49:05 +02:00
Zbigniew Jędrzejewski-Szmek 3f96c89a52 machinectl: reorder verb functions to match --help
The net diff is negative because some spurious whitespace and forward
declarations were dropped. One new forward declaration was added. (For
verb_poweroff_machine. The func could be moved, but I think it's better
to keep it adjacent to verb_reboot_machine which is very similar.)
2026-05-15 21:49:05 +02:00
Daan De Meyer bce7b82268 nsresourced: detect and clean up registry entries for dead user namespaces (#42070)
The BPF kprobe that fires on user namespace destruction is the only
thing
that triggers registry cleanup, so any time it doesn't run — ring buffer
overflow, kprobe missing, fdstore entry dropped outside our cleanup path
— a registry entry is left behind forever.

Stamp each registry entry with the kernel's unique namespace identifier
(NS_GET_ID, kernel ≥ 6.13) at allocation time. At manager startup, after
the existing fdstore→registry sweep, walk the registry and ask the
kernel
to look each namespace up by id via open_by_handle_at() on nsfs; if the
lookup returns -ESTALE the namespace is gone and we release the entry.
Old entries written before this change carry no identifier and are left
alone.

Add a namespace_open_by_id() helper for the lookup. The kernel restricts
open_by_handle_at() on nsfs to processes in the initial user namespace,
collapsing both permission denials and dead namespaces onto -ESTALE; the
helper refuses early with -EPERM outside the initial user namespace
so callers can tell the two apart.
2026-05-15 21:19:15 +02:00
Daan De Meyer 5e04304793 Convert homectl to option and verb macros (#42113) 2026-05-15 20:15:06 +02:00
Luca Boccassi 7f9dd1366e shell-completion: add --when to systemctl
Fixes https://github.com/systemd/systemd/issues/41672
2026-05-15 19:07:00 +01:00
Daan De Meyer 23f2204718 nsresourced: detect and clean up registry entries for dead user namespaces
The BPF kprobe that fires on user namespace destruction is the only thing
that triggers registry cleanup, so any time it doesn't run — ring buffer
overflow, kprobe missing, fdstore entry dropped outside our cleanup path
— a registry entry is left behind forever.

Stamp each registry entry with the kernel's unique namespace identifier
(NS_GET_ID, kernel ≥ 6.13) at allocation time. At manager startup, after
the existing fdstore→registry sweep, walk the registry and ask the kernel
to look each namespace up by id via open_by_handle_at() on nsfs; if the
lookup returns -ESTALE the namespace is gone and we release the entry.
Old entries written before this change carry no identifier and are left
alone.

Add a namespace_open_by_id() helper for the lookup. The kernel restricts
open_by_handle_at() on nsfs to processes in the initial user namespace,
collapsing both permission denials and dead namespaces onto -ESTALE; the
helper refuses early with -EHOSTDOWN outside the initial user namespace
so callers can tell the two apart.
2026-05-15 18:05:21 +00:00
Zbigniew Jędrzejewski-Szmek 3b5495c041 homectl: fix unlocking of multiple homes
Fixes 4aa0a8ac3e.
2026-05-15 18:52:01 +02:00
Zbigniew Jędrzejewski-Szmek 6cadf7b108 homectl: convert verbs to VERB macros
--help looks pretty much the same. "[list]" is shown in parentheses
because it's the default.

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:51:58 +02:00
Zbigniew Jędrzejewski-Szmek 9a7b2d0d87 homectl: convert parse_argv to OPTION macros
Rewrite help() with help-util.h primitives + option_parser_get_help_table_group
for each User Record Properties section. The verbs[] table stays
unchanged for now; run() switches from dispatch_verb() (which depended
on the global optind) to _dispatch_verb_with_args() fed by
option_parser_get_args().

Explanations are improved for --birth-date[=DATE] (correct placement of
'['), --skel=, --shell= (short options listed). Some minor rewordings
for other options. The explanation for -E and -EE is split.
(OPTION_HELP_ENTRY_VERBATIM is used for -EE.)

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:51:56 +02:00
Zbigniew Jędrzejewski-Szmek 82b87471ad shared/options: fix display of OPTION_HELP_ENTRY_VERBATIM
So far it was used only once, in bootctl. It should not be indented:
  -R --print-root-device
  -RR
  ^
2026-05-15 18:47:17 +02:00
Zbigniew Jędrzejewski-Szmek feb1078462 homectl: reorder cases in parse_argv() to match order in --help
Display options --no-pager, --no-legend, --no-ask-password are placed at
the end, after --mute-console=yes, rather than near the top.

Co-developed-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 18:47:11 +02:00
Zbigniew Jędrzejewski-Szmek 321c894828 homectl: reorder verb functions to match order in --help
Just a hand-crafted moving of blocks of code up and down, no other
changes. The net diff is -2 because add_signing_keys_from_credentials
forward declaration was dropped.
2026-05-15 18:08:20 +02:00
наб 0304ba263a varlink: vl_error_MethodNotFound: an method 2026-05-15 17:55:20 +02:00
наб 6fbb3c55f1 varlink: MethodNotImplemented: drop extraneous dot 2026-05-15 17:54:42 +02:00
Luca Boccassi 053470f2db core: support FD Store propagation through manager instances, and preservation through kexec via LUO (#41683)
First of all, FD store propagation is enabled between manager instances,
and nspawn instances, via LISTEN_FDS and sd_notify. These can be nested
arbitrarily deeply all the way up to the system manager, and on restart
will be propagated all the way down to the origin. The FDs payload of an
nspawn container running as a user unit will be preserved, all the way
up to the system manager, and then down again.

The kernel Live Update Orchestrator (LUO) exposes /dev/liveupdate, which
lets userspace hand a set of "preservable" kernel objects to the new
kernel across a kexec-based reboot. For now it only supports memfds,
with more object types (virtio devices, etc.) expected to be added
later.

This is a natural fit for systemd's FD Store feature: services hand
memfds (containing serialized state or other service data) to PID 1 via
FDSTORE=1 sd_notify() messages, and get them back on their next start.
Today this works across service restarts, soft reboots and initrd→rootfs
transitions. With LUO, this series extends the same mechanism to work
across kexec too. The nesting preservation of FD stores thus now is
extended across kexec.

All preservable fds are collected into a single LUO session named
"systemd". Each fd is uploaded with an index (token). Token 0 is
reserved for a "mapping" memfd, which carries a JSON object describing
how to dispatch the other tokens back to units on the next boot.

Unit names are used as the unit identifier, as they are stable across
daemon-reexec, switch-root and kexec. token refers to the LUO index
assigned to the object in the session.

On shutdown for MANAGER_KEXEC, just before manager_free(), systemd walks
all services and serializes their persistent fd store contents (fds +
FDNAMEs + cgroup paths) into a JSON memfd. The fds themselves are
gathered into an FDSet. The fdset and the serialization memfd are passed
to systemd-shutdown via the SYSTEMD_LUO_SERIALIZE_FD environment
variable providing the fd number, so the actual LUO session creation and
ioctls happen as the very last step before kexec.

On boot, manager_luo_restore_fd_stores() opens /dev/liveupdate, tries to
retrieve the "systemd" session, reads the mapping memfd, then for each
entry retrieves the fd from the session and attempts to attach it to the
matching unit's fd store.

Because the initrd-stage PID 1 runs before the real rootfs units are
loaded, fds whose target unit is not (yet) known are not dropped: they
are stashed in a new luo_held_fds hashmap keyed by cgroup path. They are
re-tried in two places: after deserialization, and from unit_load(), so
fds land in the correct fd store as soon as the owning unit is parsed,
allowing units to be plugged in at runtime.

Non-kexec shutdown paths are unaffected: if MANAGER_KEXEC is not the
final objective, no serialization file is produced and no LUO session is
ever created. Likewise if /dev/liveupdate does not exist, nothing
happens.

The LUO session creation is performed by systemd-shutdown, rather than
by PID 1, deliberately: it is the last point where we can be sure all
other processes have already been killed, so nothing else can race us
into creating (or worse, hijacking) the "systemd" session.
/dev/liveupdate is a singleton and session names are global. In
addition, any kernel-visible side effects of preserving objects (memory
pinning, etc.) are delayed until the absolute last moment, minimizing
the window in which they could affect the running system. There is no
behaviour change for shutdown paths other than kexec, or for kexec when
systemd didn't hand over a serialization fd (e.g. because no service had
any fds stored, or because LUO wasn't supported at serialization time).

Finally, since LUO sessions cannot be nested under other sessions,
third-party sessions need to be handled explicitly and held open in the
shutdown binary alongside our own internal session, to allow services to
create and preserve their own sessions. The requirement comes from VMMs
that wish to preserve VM state across kexec: some file descriptors (e.g.
KVM's vmfd from the KVM_CREATE_VM ioctl) cannot be transferred between
processes via SCM_RIGHTS, so they cannot be stashed in the FD Store
directly. Additionally, some file descriptors must be handled
all-or-nothing, again tied to KVM, where a VM and its associated devices
are one indivisible group.

https://docs.kernel.org/userspace-api/liveupdate.html
https://docs.kernel.org/core-api/liveupdate.html
https://docs.kernel.org/admin-guide/mm/kho.html
2026-05-15 16:07:48 +01:00
Daan De Meyer 76ac669737 mkosi: Make sure mkosi.clangd maps to mkosi/mkosi.tools
The tools tree is now stored in mkosi/mkosi.tools, so update
the script to match.
2026-05-15 14:24:01 +01:00
Luca Boccassi c10c2674f3 LUO: add support for preserving third party sessions
LUO sessions cannot be nested under other sessions. This means we need
to handle them explicitly, and held them open in the shutdown binary
like we do with our own internal session, to allow services to create
their own.

The requirement to support third party sessions comes from VMMs that
wish to preserve VM(s) state(s) across kexec, as some file descriptors
(KVM's vmfd from the KVM_CREATE_VM ioctl) cannot be transfered between
processes via SCM_RIGHTS, so they cannot be stashed in the FD Store
directly. Also some file descriptors have to be handled all together or
not at all, again to do with KVM and devices that are all part of the
same vm.
2026-05-15 13:46:08 +01:00
Luca Boccassi 0854ac48ef docs: document LUO support 2026-05-15 13:46:08 +01:00
Luca Boccassi 14f773ce5e test: add integration test for LUO 2026-05-15 13:46:08 +01:00
Luca Boccassi 3dddbee290 shutdown: prepare LUO session for FD Stores before kexec
Wires up the systemd-shutdown side of the kexec-via-LUO fd store preservation.

When rebooting via kexec, systemd builds a JSON description of the fd
stores of all loaded services and passes it to systemd-shutdown through
the SYSTEMD_LUO_SERIALIZE_FD environment variable. The FDs themselves
come in as part of the normal shutdown FDSet. systemd-shutdown's job is
then, at the very last moment before invoking the kexec syscall, to
move that state into a kernel LUO session so it survives the reboot.

Doing the LUO session creation here, rather than in PID 1, is
deliberate:

 * It's the last point where we can be sure all other processes have
   already been killed, so nothing else can race us into creating (or
   worse, hijacking) the "systemd" session, as /dev/liveupdate is a
   singleton and a session name is global.
 * Any kernel-visible side effects of preserving objects (memory
   pinning etc.) are delayed until the absolute last moment, minimizing
   the window in which they could affect the running system

No behaviour change for shutdown paths other than kexec, or for kexec
when systemd didn't hand over a serialization fd (e.g. because no
service had any fds stored, or because LUO wasn't supported at
serialization time).
2026-05-15 13:46:08 +01:00
Luca Boccassi 257c35c1a3 core: support FD Store preservation through kexec via LUO
The kernel Live Update Orchestrator (LUO) exposes /dev/liveupdate, which
allows userspace to hand a set of "preservable" kernel objects to the
new kernel across a kexec-based reboot. For now it only supports memfds,
with more object types (virtio devices, etc.) expected to be added later.

This is a natural fit for systemd's FD Store feature: services hand
memfds (containing serialized state or other service data) to PID 1 via
FDSTORE=1 sd_notify() messages, and get them back on their next start.
Today this works across service restarts, soft reboots and
initrd→rootfs transitions. With LUO we can extend the same mechanism to
work across kexec, too.

The protocol on the PID 1 side works roughly as follows:

 * All preservable fds are collected into a single LUO session named
   "systemd". Each FD gets uploaded with a token. Token 0 in that session
   is reserved for a "mapping" memfd, which carries a JSON object
   describing how to dispatch the other tokens back to units on the next
   boot:

       {
         "foo.service": [
           { "type": "fd", "name": "stateA", "token": 1 },
           { "type": "fd", "name": "stateB", "token": 2 }
         ],
         ...
       }

   unit IDs are used as the unit identifier, as they're stable
   across daemon-reexec, switch-root and kexec. token refers to the
   LUO token assigned to the object in the session.

 * On shutdown for MANAGER_KEXEC, just before manager_free(), systemd
   walks all services and serializes their persistent fd store contents
   (fds + FDNAMEs + unit IDs) into a JSON memfd. The FDs themselves are
   gathered into a FDSet to be kept around. The fdset and the
   serialization memfd are passed to systemd-shutdown via the
   SYSTEMD_LUO_SERIALIZE_FD environment variable providing the fd number,
   so the actual LUO session creation and ioctls can happen as the very
   last step before kexec (shutdown implementation is the next commit).

 * On boot, manager_luo_restore_fd_stores() opens /dev/liveupdate,
   tries to retrieve the "systemd" session, reads the mapping memfd,
   then for each entry retrieves the fd from the session and attempts
   to attach it to the matching unit's fd store.

 * The FDs are injected in the appropriate unit's FD stores using the
   same mechanism as the LISTEN_FDS propagation that was set up earlier.

Non-kexec shutdown paths are unaffected: if MANAGER_KEXEC is not the
final objective, no serialization file is produced and no LUO session
is ever created. Likewise if /dev/liveupdate does not exist, nothing
happens.
2026-05-15 13:46:08 +01:00
Luca Boccassi 79ac52b810 Add helpers for talking to /dev/liveupdate
This character device is the main kernel interface to deal with the
Live Update Orchestrator (LUO) feature. Add some basic wrappers for
the ioctls.

https://docs.kernel.org/userspace-api/liveupdate.html
2026-05-15 13:46:08 +01:00
Luca Boccassi bc1c56543f Import linux/liveupdate.h UAPI header
From kernel 7.0
2026-05-15 13:46:08 +01:00
Luca Boccassi 9de91f0f4c nspawn: support forwarding FDs from payloads to managers
When there is a NOTIFY_SOCKET, and FDs are received from the
payload following the FD Store protocol, forward them up the
chain to the service manager that is managing nspawn.

This allows FD Store persistence across container restarts,
and can chain up for user managers as well to survive restarting
those, or reexecs, and in the future reboots too via LUO.

Add a new test case to exercise the PID1 -> user session -> nspawn -> payload
chain.
2026-05-15 13:46:08 +01:00
Luca Boccassi 5608575e01 core: propagate FDs from store from user to system manager
In order to allow FD Stores of user units to survive a user
session restart, propagate FDs received via the protocol up one
level from user to system manager via sd_notify.

And the other way around, propagate them down via LISTEN_FDS
tagging them with the unit name so that the child manager can
inject them in the appropriate unit.

Ensure units that are dead or not loaded can get FDs added to
their stores, and that they are correctly propagated once the
unit is started or loaded. When the unit is not loaded we don't
know what the FD max limit is, so simply increase it for each FD
injected, and then when the unit is realised prune it down to
match the unit's now available config in case the limit is lower
than the number of FDs in the store.

Each FD sent up or down is assigned a monotonic index, and the manager
also sends a JSON map that associates the index with the original
unit and FDNAME:

 {
   "unit-name.service": [
     { "name": "fdname1", "index": 1 },
     { "name": "fdname2", "index": 2 }
   ],
   ...
 }

This allows the manager to assign back the FDs to the appropriate
unit using the appropriate name, given the FDNAMEs are not unique.
2026-05-15 13:46:08 +01:00