Commit Graph
88381 Commits
Author SHA1 Message Date
Lennart Poettering e4e3ec811a volume: add an "io.systemd.StorageProvider" IPC API that is supposed to be used by vmspawn/nspawn/pid1 to provide storage volumes in a generic fashion (#41776)
BindPath= in unit files, and --bind= in nspawn/vmspawn doesn't really
cut it to connect arbitrary storage infra to it. Let's do something
about it, and implement a simple, light-weight API for acquiring an fd
to a storage volume. Benefits:

1. the interface can be implemented by anyone, connecting anything to
vmspawn/nspawn/service management
2. very lose coupling: just bind a socket into a well-known dir, done
3. mounting can happen on-demand
2026-04-29 15:51:52 +02:00
Zbigniew Jędrzejewski-Szmek 53f7c1a8cc sd-boot related work from #41543 (add "extra" stanza to bls type 1) (#41863)
This implements the "extra" stanza for type 1 entries in systemd-boot,
see:


https://github.com/uapi-group/specifications/commit/bde167a46c866c44e1240120695f70f0bf70aadc

It comes with a really thorough test suite matching our currently level
of testing of systemd-boot (read: there is none, I ask you to trust me,
Claude, and your review on this one)...

Split out of #41543
2026-04-29 15:25:38 +02:00
Zbigniew Jędrzejewski-Szmek a79c4fdf93 Small cleanups in sd-varlink and sd-json (#41861) 2026-04-29 15:03:00 +02:00
Zbigniew Jędrzejewski-Szmek 6c7726193e sd-bus: store the strv size when extending it (#41864)
So strv_push_with_size() doesn't have to recalculate the size every
time.
2026-04-29 15:01:12 +02:00
Lennart Poettering 6b1324fb86 man: add a brief note about type 1 extra lines 2026-04-29 13:36:56 +02:00
Lennart Poettering a3d0e761d4 boot: downgrade log level for an error we ignore 2026-04-29 13:36:56 +02:00
Lennart Poettering d5572aca2c boot: load extra files for UKIs into memory and register as initrds
This generates on-the-fly cpio initrds from 'extra' resources declared
in Type #1 entries and installs them via the Linux initrd protocol so
that they get passed to the Linux kernel.

Replaces: #39286
2026-04-29 13:36:56 +02:00
Lennart Poettering feba5dcc5f boot: parse 'extra' type 1 stanza too
This loads the new 'extra' stanza, but doesn't actually do anything with
it yet. That's added in a later commit.

Replaces: #39286

Implements: https://github.com/uapi-group/specifications/pull/212
2026-04-29 13:36:56 +02:00
Lennart Poettering c3ace5621b cpio: move TPM PCR info into CpioTarget
The PR to measure into is closely associated with where we place a
resource in the initrd cpios. Hence, let's also track it in CpioTarget,
thus simplifying our function parameter lists that way.

No change in behaviour.
2026-04-29 13:36:47 +02:00
Frantisek Sumsal 51a88ac723 core: limit the number of units that can be requested over ListUnitsByNames 2026-04-29 12:58:58 +02:00
Frantisek Sumsal 0d71d58da0 sd-bus: store the strv size when extending it
So strv_push_with_size() doesn't have to recalculate the size every
time.
2026-04-29 12:58:22 +02:00
Lennart Poettering eccfd2c97b TODO: track StorageProvider follow-ups, sketch a NetworkProvider sibling
Records the still-missing StorageProvider integrations (nspawn,
vmspawn, service-manager BindVolume=) and replaces the now-obsolete
generic "storage API via varlink" entry with a NetworkProvider
proposal modelled on it.
2026-04-29 12:26:52 +02:00
Lennart Poettering 804bf405d9 test: add integration test for storagectl and storage providers
VM-only test that exercises both shipped providers through storagectl:
verifies the well-known sockets exist, lists providers/volumes/
templates, creates and acquires volumes from each template
(sparse-file, allocated-file, directory, subvolume), attaches a loop
device to cover the block provider, and exercises the mount.storage
helper.
2026-04-29 12:26:52 +02:00
Lennart Poettering 4002a7e8be storage: add 'storagectl' command-line tool
CLI for inspecting and using storage providers. Scans
/run/systemd/io.systemd.StorageProvider/ (or the user-mode equivalent)
for AF_UNIX sockets and talks to each one over Varlink. Verbs:
"volumes" lists volumes across all providers, "templates" lists
supported creation templates, "providers" lists the endpoints
themselves.

Also installed as a mount.storage helper, so
'mount -t storage PROVIDER:VOLUME /mnt' (or 'mount -t storage.<fstype>'
to put a fresh filesystem on a block volume) acquires the volume and
mounts it. Ships with bash/zsh completions and a man page.
2026-04-29 12:25:47 +02:00
Lennart Poettering 9825195c25 storage: add systemd-storage-fs@.service provider
Second StorageProvider implementation, exposing regular files and
directories from a backing filesystem. In system mode the backing
directory is /var/lib/storage/, in user mode $XDG_STATE_HOME/storage/;
entries with a .volume suffix are exposed, with the inode type
determining whether the volume is reported as reg, dir or (via
symlinked/bind-mounted device node) blk.

Unlike the block provider, this one supports creating volumes
on-demand from a small set of built-in templates: sparse-file,
allocated-file, directory and subvolume.
2026-04-29 12:25:47 +02:00
Lennart Poettering 4fd0df2a4b storage: add systemd-storage-block@.service provider
First implementation of io.systemd.StorageProvider, exposing all block
devices known to udev (disks, partitions, dm nodes, …) as volumes of
type "blk". Names are picked from stable /dev/mapper and /dev/disk/by-*
symlinks; content-derived identifiers (by-uuid, by-label, …) are
intentionally avoided for security. Volume creation is not supported by
this backend.

Socket-activated via /run/systemd/io.systemd.StorageProvider/block.
Also adds shared storage-util.[ch] (VolumeType / CreateMode helpers)
that subsequent providers reuse.
2026-04-29 12:25:47 +02:00
Lennart Poettering 087fa20166 shared: add io.systemd.StorageProvider Varlink interface
Generic Varlink API for services that hand out file descriptors to
storage volumes. Three methods: Acquire() returns an fd for a named
volume (optionally creating it from a template), ListVolumes()
enumerates available volumes, ListTemplates() enumerates supported
creation templates. Volume types follow kernel inode-type naming:
blk (block device), reg (regular file), dir (directory).

Intent is that multiple providers can sit behind AF_UNIX sockets in a
well-known directory and be consumed uniformly by nspawn, vmspawn,
the service manager (BindVolume=) and similar tools.
2026-04-29 12:25:46 +02:00
Daan De Meyer 5948ff5fe2 libsystemd: Clean up meson.build
Merge the two blocks adding tests, since there seems to be
no obvious reason to have two separate blocks, as they both
contain tests from the same libraries.
2026-04-29 12:03:21 +02:00
Zbigniew Jędrzejewski-Szmek d9e0883316 sd-json: stop printing debug messages about extension fields
The intent was good, but we now print two or three of those messages
for each report metrics received on the wire. If the json object is
extensible, then it's all good and we don't need to inundate the user
with this trivial information. (And the message also sounds like
something is wrong or unexpected, when it totally isn't.)

...
(string):1:73: Unrecognized object field 'object', assuming extension.
(string):1:89: Unrecognized object field 'value', assuming extension.
json-stream: Received message: {"parameters":{"name":"io.systemd.Network.CarrierState","object":"virbr0","value":"degraded-carrier"},"continues":true}
(string):1:66: Unrecognized object field 'object', assuming extension.
(string):1:83: Unrecognized object field 'value', assuming extension.
json-stream: Received message: {"parameters":{"name":"io.systemd.Network.CarrierState","object":"lo","value":"carrier"},"continues":true}
(string):1:66: Unrecognized object field 'object', assuming extension.
(string):1:79: Unrecognized object field 'value', assuming extension.
json-stream: Received message: {"parameters":{"name":"io.systemd.Network.CarrierState","object":"wlp0s20f3","value":"carrier"},"continues":true}
(string):1:66: Unrecognized object field 'object', assuming extension.
(string):1:86: Unrecognized object field 'value', assuming extension.
...
2026-04-29 11:24:03 +02:00
Zbigniew Jędrzejewski-Szmek 242fca7516 sd-varlink: reduce size of varlink structs
struct sd_varlink:
- /* size: 448, cachelines: 7, members: 21 */
+ /* size: 432, cachelines: 7, members: 21 */

struct sd_varlink_server:
- /* size: 160, cachelines: 3, members: 21 */
+ /* size: 152, cachelines: 3, members: 21 */
2026-04-29 11:23:02 +02:00
Zbigniew Jędrzejewski-Szmek 01bf2b9f52 sd-varlink: drop pointless bitfield
As is often the case, in this case because of alignment, we are actually
not saving any space. With the bitfield we are using one bit of the 8 bytes
allocated, and without the bitfield we are using 8 bits of that.

But we're paying a price in generated code, at every access site to the
field:

$ diff <(objdump -S build/libsystemd.so.old) <(objdump -S build/libsystemd.so.new)
...
       v->protocol_upgrade = false;
-   fa2d2:	48 8b 45 a8          	mov    -0x58(%rbp),%rax
-   fa2d6:	0f b6 90 90 01 00 00 	movzbl 0x190(%rax),%edx
-   fa2dd:	83 e2 fe             	and    $0xfffffffe,%edx
-   fa2e0:	88 90 90 01 00 00    	mov    %dl,0x190(%rax)
+   fa2a9:	48 8b 45 a8          	mov    -0x58(%rbp),%rax
+   fa2ad:	c6 80 90 01 00 00 00 	movb   $0x0,0x190(%rax)
2026-04-29 11:23:01 +02:00
Daan De Meyer bb17ded158 mkosi: Install liburing
Make sure liburing is installed so it's available for 
experimentation in sd-event integration.
2026-04-29 09:20:57 +01:00
Michael Vogt 43576036bd core: add io.systemd.Unit.StartTransient() to the varlink API (#41583)
This commit adds a simple version of io.systemd.Unit.StartTransient
for varlink. It is similar to the dbus version, but there is a key
difference:
1. Instead of building the unit from key/value properties it
takes a structured json object "UnitContext" with a "Service" field
inside.
   It is also only implementing a minimal set of what can be done with a
   service.
2. No aux units (for now)
3. When called with --more the varlink socket can notify about
   state changes depending on the notify{Job,Unit}Changes parameter

This aligns to the json objects/format from
https://github.com/systemd/systemd/pull/39391
and to show how the format can be shared it adds a new
(minimal) `ServiceContext` that is now part of
`io.systemd.Unit.List()`.
2026-04-29 08:20:56 +02:00
Daan De Meyer f6b15dc63d ci: Reduce noise from claude-review workflow 2026-04-28 23:34:01 +02:00
Zbigniew Jędrzejewski-Szmek 2e591bb1e7 Add "namespaces" to option macros, convert systemd-run+run0 (#41844) 2026-04-28 19:38:04 +02:00
Lennart Poettering 46bd1d1e88 update TODO 2026-04-28 18:24:43 +02:00
Zbigniew Jędrzejewski-Szmek 4c640beba6 shared/options: add an assert loop to verify ordering
If things are misordered, we need to catch this. Use assert_se to make
the check also in custom builds that otherwise disable assertions.
2026-04-28 17:39:32 +02:00
Zbigniew Jędrzejewski-Szmek 0a85be9ccf run: use a "named namespace" also for the main option parser
It seems that clang reorders the entries in the options array that
originate from different functions, but not within a function. Using
"named namespaces" exclusively should sidestep the issue.

(A bigger hammer would be to sort the array. We *can* do this, since the
options have the increasing .id field. But that'd require duplicating
the memory or making it writable. Let's avoid this until we know for
sure that it's needed.)
2026-04-28 17:13:24 +02:00
Zbigniew Jędrzejewski-Szmek 03a58fe251 run: convert run0 option parser to macros
This exercises the new option namespace code.

--help output is generally the same, except for the formatting changes
related to use of the new output helpers and the common option macros.

--same-root-dir is now documented (followup for
  475729b805).

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 17:13:24 +02:00
Zbigniew Jędrzejewski-Szmek 4c0e12b3b9 run: convert parse_argv() to OPTION macros
--system is now documented (fixup for 66b1e74605).
--capsule is now documented (fixup for 759b3c082d).

--help output is generally the same, except for the formatting changes
related to use of the new output helpers and common option macros.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 17:13:24 +02:00
Zbigniew Jędrzejewski-Szmek ff902c7ccd run: reorder switch cases to match help() output order
Both parse_argv() and parse_argv_sudo_mode() handled options in an
order that no longer matched the help text. Reorder the case statements
so the source order mirrors what the user sees in --help.

In parse_argv_sudo_mode(), drop the case 'i' → ARG_VIA_SHELL fall-through
so the cases can be sequenced independently; 'i' now sets arg_via_shell
directly.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-28 17:13:24 +02:00
Zbigniew Jędrzejewski-Szmek 1600978f5f shared/options: introduce "namespaces" for options
This allows multiple option parsers to be defined in a single
compilation unit. We put the OPTION_NAMESPACE("name") to split
up the options. The basic implementation is similar to groups,
except that groups only matter for help display, while namespaces
matter for both help display and actual option parsing. When parsing,
we locate the appropriate range between the beginning of options
and the next namespace marker or between two namespace markers and
only look at that range.
2026-04-28 17:13:24 +02:00
Clayton Craft 47d408163b loop-util: don't reuse partition fd when partscan needed
Some devices (e.g. android phones running pmOS) cannot have their OEM
partition table altered without breaking the firmware, so the distros's
partitions live inside a nested GPT carved into one of the OEM
partitions. Exposing these subpartitions requires wrapping the outer
partition in a loop device with partscan enabled, since the kernel does
not go into nested partition tables.

systemd already detects this case in udev-builtin-blkid
(ID_PART_GPT_AUTO_ROOT_DISK_NEEDS_LOOP) and acts on with
systemd-loop@.service, but this fails towards the end.
loop_device_make_internal has an optimization where if the input is
already a block device with a matching sector size, it skips creating
a loop and just hands back the original fd. That's fine for whole disks
but wrong for partitions, which don't support partscan, so this causes
dissect_image to fail with EPROTONOSUPPORT.

This patch changes the behavior to only take the shortcut when the input
is a whole disk, or when partscan was not requested.

Co-Authored-By: Clayton Craft <clayton@craftyguy.net>
2026-04-28 15:25:07 +01:00
Zbigniew Jędrzejewski-Szmek d0f726ed8f shared/options: fix --help indentation for long options
In 4339197f5d the helper to format -o/--opt=
was split out, but the indentation was for --long-options was messed up.
We'd print:
Options:
  -h --help             Show this help
  --version             Show package version
  --no-ask-password     Do not prompt for password
  ...
But we want
  -h --help             Show this help
     --version          Show package version
     --no-ask-password  Do not prompt for password
  ...

The prefix argument was arguably ugly, even if it allowed one alloc to be
avoided. Let's get rid of it and let the handler prefix the string as
appropriate. This makes other callers nicer too.

Fixup for 4339197f5d.
2026-04-28 15:44:28 +02:00
Lennart Poettering 37c272228d core: ensure all types from execute.h start with Exec
Until very recently all types defined by execute.h started with "Exec"
in the name. I think that was useful, since it made clear that the types
are associated with the ExecContext infrastructure. Let's hence restore
this.

(If we every move these types out of execute.h we should drop the "Exec"
prefix again. But today is not that day.)

No real code changes, just dumb renaming.
2026-04-28 12:37:21 +01:00
Lennart Poettering e596867ed6 meson: rerun 'update-man-rules' 2026-04-28 12:05:14 +01:00
Luca Boccassi 1cccb5362c A couple of sanitizer-related tweaks (#41808)
The sanitizer job was FUBAR on Fedora Rawhide (and RHEL 10 to some
extent) due to several changes:
- latest LLVM (v22) introduced a change that occasionally generates a
false-positive warning when running with sanitizers
  - several tools had to be "ASan-wrapped" because:
- util-linux started linking against libsystemd which propagated to
other tools depending on its shared libraries (like libmount)
- libssh started depending on libfido2, which depends on libudev; this
then translated to an interesting depedency chain where tpm2 utils got a
dependency on libudev through libcurl -> libssh -> libfido2
- polkit added MemoryMax= to its service file, which is incompatible
with ASan-runs (at least with the current limits)

See the commits for more detailed descriptions.

Also, one note: the santizer job is currently still FUBAR on Fedora
Rawhide (or, more specifically, the TEST-50-DISSECT and TEST-58-REPART),
because mkfs.erofs also gained a dependency on libudev (through libcurl,
see above), but the wrapping currently doesn't work as it also depends
on libqpl which is linked with libtsan (which is incompatible with other
sanitizers). This is currently tracked in
https://bugzilla.redhat.com/show_bug.cgi?id=2461146
2026-04-28 12:04:45 +01:00
Dark Cronyx a192a5cc4d po: Translated using Weblate (German)
Currently translated at 100.0% (266 of 266 strings)

Co-authored-by: Dark Cronyx <darkcronyx@protonmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/de/
Translation: systemd/main
2026-04-28 11:59:21 +01:00
Daan De Meyer ed1373f889 fork-notify: Use callback instead of argv NULL code path with return (#41813) 2026-04-28 10:15:31 +02:00
Michael Vogt 328fd964a9 core: transition job to JOB_FINISHED on uninstall
When a job reaches the job_uninstall() stage we used to set the
state to JOB_WAITING. However now that we have a JOB_FINISHED state [1]
we should use that instead. This is more accurate so when
varlink_job_send_removed_signal() is called the job is in the expected
state and that is what the user will see.

Note that this does not change the D-Bus API because there
bus_job_send_removed_signal() doesn't send the state, it only sends
the result.

[1] https://github.com/systemd/systemd/pull/41811
2026-04-28 09:01:54 +02:00
Daan De Meyer 181a9f65a7 udev: don't assert on worker cap after killing a broken idle worker
manager_can_process_event() considers an event processable if either
there is room below children_max to spawn, or an idle worker exists.
When only the latter holds, event_run() picks the idle worker and
tries device_monitor_send(). If that send fails, event_run() SIGKILLs
the worker, marks it WORKER_KILLED and continues the loop. With no
other idle worker available, it falls through to worker_spawn(),
guarded by:

    assert(hashmap_size(manager->workers) < manager->config.children_max);

The just-killed worker is still in manager->workers until its SIGCHLD
is reaped by on_worker_exit(), so at the cap this assertion trips and
udevd aborts:

    Assertion 'hashmap_size(manager->workers) < manager->config.children_max'
    failed at src/udev/udev-manager.c:635, function event_run(). Aborting.

Instead of asserting, bail out when we are already at the worker
limit. The event remains in EVENT_QUEUED; once the killed worker's
SIGCHLD arrives and frees it from the hashmap, on_post() re-runs
event_queue_start() and the event is retried.
2026-04-27 21:14:08 +02:00
Lennart Poettering ce6a5f4164 options: add a proper state machine field
Let's track the state of the option parser in an explicit 'state' field.

Benefits:

1. We can make sure that a parser that got into a failure state will
   be invalidated for good (i.e. further operations are guaranteed to
   fail too).

2. As a side effect this cleans up the option_parse() return parameter
   handling: we'll now always initialize ret_option/ret_arg when
   returning >= 0, as per coding style.
2026-04-27 20:21:04 +02:00
Lennart Poettering bd2d2fec80 options: tighten validation of argc/argv
If argc/argv do no match a lot of our assumptions are invalid, hence
let's check this explicitly once, instead of ignoring the issue.
2026-04-27 20:12:46 +02:00
Lennart Poettering b10d3631f3 options: drop redundant enum value declaration 2026-04-27 20:12:46 +02:00
Zbigniew Jędrzejewski-Szmek b2d72eabcd tree-wide: change option_parse() to return option and arg via internal state (#41833) 2026-04-27 19:42:52 +02:00
Kai Lüke 70d75c22d7 machine-register: don't unref borrowed varlink reply
ASAN showed a use-after-free error for systemd-vmspawn's
machine_register call because the reply got accessed and freed again
through _cleanup. The same problem exists in two
verb_machine_control_one/unregister_machine.
Fix these call sites to not set up _cleanup.
2026-04-27 22:14:05 +09:00
Kai Lüke 41cf689121 nsresource: fix buffer overrun reported by ASAN
This came up when running systemd-vmspawn with ASAN to fix another bug
and thus I had to fix this overrun here first: The dispatch tables were
missing the terminator, add it.
2026-04-27 22:14:05 +09:00
Kai Lüke 4dbcc319ca fork-notify: Use callback instead of argv NULL code path with return
In 012d87c1fc/cc8f398202 it was made possible for fork_notify() to
return in the child but at that point all FDs were closed and the
_cleanup path from the return causes assertion failures due to invalid
FDs in notify_event_source/event, leading to a vmspawn failing to start
with a SIGABRT logged in coredump.
Instead of TAKE_PTR on a bunch of things which is fragile, rather avoid
the return and instead add an explicit callback handler and guarantee
to exit directly after it. A userdata argument is also added but not
used yet I think it's quite normal to have for a callback.
2026-04-27 22:14:05 +09:00
Christian Brauner 0d6d2c9ebd vmspawn-varlink: treat QMP disconnect as success for Terminate
QMP "quit" tells QEMU to exit, which races the reply with the socket
EOF: sometimes the disconnect lands in qmp_client_fail_pending() with
-ECONNRESET before the reply has been parsed. The shared completion
callback then translates that into io.systemd.MachineInstance.NotConnected,
turning the desired outcome into a varlink error.

This is exactly what TEST-87-AUX-UTILS-VM exposes during its repeated
start/pause/resume/terminate stress loop: a successful Pause/Describe
followed milliseconds later by a Terminate that fails with NotConnected
when the disconnect path wins the race.

Give Terminate its own completion callback that treats disconnect-class
errors as success, since QEMU shutting down is the whole point of "quit".
The other simple commands (Pause, Resume, PowerOff, Reboot) keep the
existing semantics: they expect QMP to remain alive, so NotConnected is
the correct reply for them.

Link: https://github.com/systemd/systemd/actions/runs/24986080288/job/73159585425?pr=41835
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-04-27 15:07:26 +02:00
Michael Vogt 1cde1cc3ba test: add varlink io.systemd.Unit.StartTransient() test
This commit adds a bunch of integration tests for the new varlink
based io.systemd.Unit.StartTransient().
2026-04-27 13:49:24 +02:00