Remove the static blockdev/device/snapshot INI config sections and
the SCSI controller setup for both the root image drive and extra
drives. Replace with DriveInfos that are constructed in the parent
after fork: vmspawn opens all image files and passes fds to QEMU via
the add-fd path. For ephemeral mode, anonymous overlay files are
created via O_TMPFILE or memfd.
The resolve_disk_driver() helper maps DiskType to the appropriate
QEMU driver name and serial format.
The post-fork device-info preparation is split into helpers:
prepare_primary_drive() and prepare_extra_drives() for per-drive
construction, assign_pcie_ports() for naming the pre-allocated
pcie-root-port bridges once every device type is known, and
prepare_device_info() that stitches them together against the
MachineConfig aggregate.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Remove the static chardev/device INI config sections for both the
root filesystem and runtime mount virtiofs instances. Replace with
VirtiofsInfos that capture socket paths and tags for each virtiofs
mount, passed to vmspawn_varlink_setup_virtiofs() for runtime
configuration via QMP.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Remove the static vsock0 INI config section and the related pass_fds
plumbing. Replace with a VsockInfo struct that captures the vhost fd
and guest CID, passed to vmspawn_qmp_setup_vsock() for runtime
configuration via QMP. The VSOCK fd is now sent to QEMU via QMP getfd
+ SCM_RIGHTS instead of being inherited.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Remove the static netdev/nic INI config sections for both privileged
TAP, nsresourced TAP, and user-mode networking. Replace them with a
NetworkInfo struct that captures the network type, TAP fd or interface
name, and MAC address, passed to vmspawn_varlink_setup_network() for
runtime configuration via QMP.
For the nsresourced TAP path the fd is now passed to QEMU via QMP
getfd + SCM_RIGHTS instead of being inherited through pass_fds.
Declare the MachineConfig aggregate that this and the following
conversion patches populate, zero-initialized with explicit -EBADF
for the fd fields so every sub-structure cleans up safely regardless
of which device types the invocation ends up using.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Create a QMP socketpair for QEMU machine monitor control, configure
the QMP chardev+mon via the QEMU config file, and wire up the bridge
infrastructure.
After fork, vmspawn initializes the QMP bridge, probes QEMU feature
support synchronously (driving the QMP handshake to RUNNING
transparently), resumes vCPUs, then sets up the varlink server for
runtime VM control. The control socket path is passed to machined via
the controlAddress field in machine registration.
Device configuration still uses the legacy INI config path and will
be converted to bridge calls in subsequent commits.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
On PCIe machine types (q35, virt), QMP device_add is always hotplug —
even with vCPUs stopped. The root PCIe bus (pcie.0) does not support
hotplugging; only pcie-root-port bridges do. Pre-allocate enough root
ports in the QEMU config file for all devices that will be set up via
QMP, plus 10 spare ports for future runtime hotplug.
Add ARCHITECTURE_NEEDS_PCIE_ROOT_PORTS macro to guard PCIe-specific
setup on x86, ARM, RISC-V, and LoongArch (the architectures whose
QEMU machine type is q35 or virt).
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Create the QMP-to-varlink bridge layer (vmspawn-qmp.{c,h}) and the
varlink server layer (vmspawn-varlink.{c,h}).
The QMP bridge (VmspawnQmpBridge) owns the QmpClient connection and
manages pending background jobs (e.g. blockdev-create continuations).
vmspawn_qmp_init() creates the client and attaches it to the event
loop. vmspawn_qmp_probe_features() drives io_uring and qcow2
discard-no-unref probes synchronously via a qmp_client_process() +
qmp_client_wait() loop — the QMP handshake completes transparently on
the first invoke. vmspawn_qmp_start() resumes vCPUs via an async
"cont" command.
The varlink server (VmspawnVarlinkContext) exposes three interfaces:
- io.systemd.MachineInstance: generic machine control (Terminate,
PowerOff, Reboot, Pause, Resume, Describe, SubscribeEvents).
Method handlers forward to QMP commands asynchronously — the
varlink reply is deferred until the QMP response arrives.
- io.systemd.VirtualMachineInstance: VM-specific (placeholder for
future snapshot/migration methods).
- io.systemd.QemuMachineInstance: QEMU-specific (AcquireQMP stub).
The server listens on <runtime_dir>/control with mode 0600.
Event streaming follows the importd Pull pattern: SubscribeEvents
sends an initial {ready:true} notification, then fans out QMP events
to all subscribers. The disconnect handler only unrefs subscriber
links (matching resolved's vl_on_notification_disconnect pattern).
Introduce the MachineConfig aggregate in vmspawn-qmp.h grouping the
per-device info structures (DriveInfos, NetworkInfo, VirtiofsInfos,
VsockInfo) together with machine_config_done() that chains the
individual done helpers. Callers populate it field-by-field and rely
on the _cleanup_ attribute for orderly teardown regardless of which
device types the invocation ends up using.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Async QMP client for talking to QEMU's machine monitor from
libsystemd-shared. The I/O core (buffered read/write, output queue,
event source management) follows sd-varlink's patterns.
State machine:
INITIAL -> GREETING_RECEIVED -> CAPABILITIES_SENT -> RUNNING
|
v
DISCONNECTED
The QMP handshake (greeting + qmp_capabilities) is driven transparently
by qmp_client_invoke() through an internal qmp_client_ensure_running()
helper, matching sd-bus's bus_ensure_running() pattern. Callers never
wait for it explicitly.
qmp_client_invoke() is the only command interface: asynchronous, with
per-command callback. Slots are tracked in a Set keyed by id; replies
are dispatched by id match. SCM_RIGHTS fd passing is bundled through
QmpClientArgs and the QMP_CLIENT_ARGS_FD macro.
qmp_client_process() and qmp_client_wait() are exposed publicly,
mirroring sd_varlink_process() and sd_varlink_wait(). Callers that
need to drive the client synchronously — e.g. feature probing before
entering the sd_event main loop — can loop on them exactly like
varlink_call_internal() does on its varlink equivalents.
Other features:
- Buffered stream reader for QMP's \r\n-delimited JSON, handling
multi-read responses (query-qmp-schema is ~200 KiB).
- Fdset id allocation via qmp_client_next_fdset_id().
- Synthetic SHUTDOWN event on unexpected disconnect.
- Disconnect detection with callback notification and pending-command
cleanup.
- -ENOBUFS from the 16 MiB input-buffer cap is treated as recoverable
(not a transport error).
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Move json_stream_description(), json_stream_log(), and
json_stream_log_errno() from json-stream.c into json-stream.h so that
consumers like the QMP client can use the same description-prefixed
logging that json-stream itself uses internally.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Follow the existing sshAddress pattern to add a controlAddress field
that allows machine registrants (like vmspawn) to advertise a varlink
socket address for direct VM control. machined stores and exposes
the address but never connects to it itself.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Add three varlink interface definitions for the machine instance control
hierarchy:
- io.systemd.MachineInstance: generic operations applicable to both
containers and VMs (PowerOff, Reboot, Pause, Resume, QueryStatus,
SubscribeEvents). nspawn could implement this same interface later.
- io.systemd.VirtualMachineInstance: VM-specific but VMM-agnostic
operations. Empty for now, future home for AddBlockDevice and similar.
- io.systemd.QemuMachineInstance: QEMU-specific operations. Defines
AcquireQMP() for protocol upgrade to a direct QMP connection.
The "Instance" suffix avoids collision with machined's existing
io.systemd.Machine interface.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
* 207e2d0044 Stop building support for openssl engines
* 36a234147f Upload sources
* 3681163f81 Version 260.1
* 8f4f0f58e3 Version 260
* e3fab23aa0 Version 260~rc4
* e4c1c2100b Version 260~rc3
* 453696813e Fix typo in unit name in %post scriptlet
* 154edb7cdb Silence false positive "HWID match failed, no DT blob" error (rhbz#2444759)
* 03b6637c35 riscv64 port has LTO disabled
* ce1dec6a40 Version 260~rc2
* 809049777c Add patch for symlink creation error
* 6ff27708f7 Enable getty@.service through presets
* ba7807fbce Drop scriptlet for upgrades from versions <253
* 455f277188 Move support for tpm2 to systemd-udev subpackage
* 0183bc784e Version 260~rc1
Using the format specifier +%s%6N with GNU date is honored, and only
prints 6 digits of the nanoseconds portion of the seconds since epoch.
The uutils implementation of date does not honor this, and always prints
all 9 digits. This is a known bug[1], but can be worked around by
adapting this test to use nanoseconds instead of microseconds.
[1] https://github.com/uutils/coreutils/issues/11658
Follow-up to #40972. Convert remaining plain string fields to proper
varlink enum types across all interfaces, per the policy that
user-controlled/API fields should be declared as proper enums in the
IDL.
Interfaces converted:
- io.systemd.Manager — LogTarget, DefaultStandardOutput/Error,
DefaultMemory/CPU/IOPressureWatch, DefaultOOMPolicy,
CtrlAltDelBurstAction (8 fields)
- io.systemd.Unit — CPUSchedulingPolicy, IOSchedulingClass, NUMAPolicy,
MountFlags (4 fields)
- io.systemd.Machine — class, whom (2 fields, input dispatch converted
to JSON_DISPATCH_ENUM_DEFINE for automatic dashify fallback)
- io.systemd.oom / io.systemd.ManagedOOM — mode in ControlGroup (1
field)
Shared types moved to varlink-idl-common: ExecOutputType,
CGroupPressureWatch, EmergencyAction, ManagedOOMMode — these are reused
across multiple interfaces.
Each interface change includes a corresponding enum sync test to catch
future drift between C string tables and varlink IDL definitions.
Add guidance on when a field should use a proper varlink enum type
versus remaining a plain string: user-controlled/API fields should be
enums, engine-internal state fields may stay as strings.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Convert the mode field in ControlGroup from plain string to the
ManagedOOMMode enum type from varlink-idl-common. Register
ManagedOOMMode in both io.systemd.oom and io.systemd.ManagedOOM
interfaces since both use the ControlGroup struct.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Convert the class field (Register input, List output) from plain string
to MachineClass enum type, and the whom field (Kill input) to KillWhom
enum type.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Convert CPUSchedulingPolicy, IOSchedulingClass, NUMAPolicy and MountFlags
fields from plain strings to proper varlink enum types in the io.systemd.Unit
interface. Update the corresponding serialization code to use
json_underscorify() for correct enum value formatting.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Convert 8 string fields in the io.systemd.Manager varlink interface to
proper enum types:
- LogTarget: new enum (console, console_prefixed, kmsg, journal, ...)
- DefaultStandardOutput/Error: reuse ExecOutputType from common
- DefaultMemory/CPU/IOPressureWatch: reuse CGroupPressureWatch from common
- DefaultOOMPolicy: new enum (continue, stop, kill)
- CtrlAltDelBurstAction: reuse EmergencyAction from common
Output serialization updated to use JSON_BUILD_PAIR_ENUM for automatic
underscorification of dash-containing values.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
It seems to be interfering with systemd:check-help-systemd-executor
test in CI. In practice, any messages from parse_argv() are going
to be from manual invocations, since if called from PID1 the option
syntax is going to be correct. So I hope this fixes the redirection
of --help but otherwise is of little consequence.
E.g. --deserialize=15 would cause the program to abrt in safe_close.
But in fact, we shouldn't try to do the close in any case: if the
fd is not valid, we should return an error without modifying state.
And if it _is_ valid, we set O_CLOEXEC on it, so it'll be closed
automatically later.
…gind
logind could read UAPI.1 Boot Loader Spec entries from
/run/boot-loader-entries/ in addition to ESP/XBOOTLDR. This was pretty
half-assed, and to my knowledge was never actually used much.
Let's remove support for it and simplify our codebase.
Let's schedule it for removal via NEWS in a future version, to give
people a chance to speak up.
Add USB device IDs for additional SteelSeries Arctis headset models to
the sound card hardware database.
Newly added device IDs:
- Arctis Nova 7x v2 (22AD)
- Arctis Nova 7 Diablo IV (22A9)
- Arctis Nova 7X (22A4)
- Arctis Nova 7X (22A5)
- Arctis Nova 7P V2 (22A7)
When --trust=all disables CURLOPT_SSL_VERIFYPEER, the residual
CURLOPT_SSL_VERIFYHOST check is ineffective since an attacker can
present a self-signed certificate with the expected hostname. Disable
both for consistency and log that server certificate verification is
disabled.
Follow-up for 8847551bcb
Instead of interpolating the user name directly into the sh -c script
body via asprintf %s, pass it as a positional parameter ($1) in a
separate argv entry. This avoids the user string being parsed as part
of the shell script syntax.
Also validate the user name in bus_machine_method_open_shell() with
valid_user_group_name(), matching the validation already done on the
Varlink path via json_dispatch_const_user_group_name().
Follow-up for 49af9e1368
method_set_wall_message() and the property setter only checked the
message length but not its content. Since wall messages are broadcast
to all TTYs, control characters in the message could interfere with
terminal state. Reject messages containing control characters other
than newline and tab.
Follow-up for 9ef15026c0
Follow-up for e2fa5721c3
Add mac_selinux_unit_access_check_varlink() to the unit enumeration
loop in vl_method_list_units(), silently skipping units the caller
is not permitted to see, matching the D-Bus ListUnits behavior.
Add mac_selinux_access_check_varlink() to vl_method_describe_manager().
Follow-up for 472abf7bec
Follow-up for 736349958e
In ccecae0efd ("vmspawn: use machine name in runtime directory path")
support for RUNTIME_DIRECTORY was dropped which makes it difficult to
run systemd-vmspawn in a service unit which doesn't have write access to
the regular /run but should use its own managed RUNTIME_DIRECTORY. What
worked before was --keep-unit --system but we can't use XDG_RUNTIME_DIR
and --user because then --keep-unit breaks which we need because it
can't create a scope as there is no session. Switch back to
runtime_directory which handles RUNTIME_DIRECTORY and tells us whether
we should use it as is without later cleanup or if we need to use the
regular path where we create and delete the directory ourselves.
logind could read UAPI.1 Boot Loader Spec entries from
/run/boot-loader-entries/ in addition to ESP/XBOOTLDR. This was pretty
half-assed, and to my knowledge was never actually used much.
Let's remove support for it and simplify our codebase.
Let's schedule it for removal via NEWS in a future version, to give
people a chance to speak up.
- Use persist-credentials: false for actions/checkout, so we don't
leak the github token credentials to subsequent jobs.
- Remove one / from the Edit/Write permissions. Currently, with the
absolute path from github.workspace, we expand to three slashes while
we only need two.
Move ExecOutputType, CGroupPressureWatch, EmergencyAction and
ManagedOOMMode enum type definitions from varlink-io.systemd.Unit to
varlink-idl-common, as these types are shared across multiple varlink
interfaces.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>