fd_is_fs_type() returns < 0 for errors, 0 for false, and > 0 for true, so
in the r > branch we'd most likely report EPERM together with the error
message which is misleading.
If range is NULL (i.e. when PrivateUsers= doesn't contain ':'),
both later error paths will then pass NULL to log_syntax():
~# cat foo.nspawn
[Exec]
PrivateUsers=9999999999999999999
~# SYSTEMD_LOG_LEVEL=debug systemd-nspawn -D foo |& grep foo.nspawn
Found settings file: /root/foo.nspawn
/root/foo.nspawn:2: UID/GID shift invalid, ignoring: (null)
or
~# cat foo.nspawn
[Exec]
PrivateUsers=4294967294
~ # SYSTEMD_LOG_LEVEL=debug systemd-nspawn -D foo |& grep foo.nspawn
Found settings file: /root/foo.nspawn
/root/foo.nspawn:2: UID/GID shift and range combination invalid, ignoring: (null)
Let's just use rvalue in both of these cases instead.
This simply mirrors the same overflow check we already have in
strrepa(), in case someone passed us a sufficiently long string.
strrep() is currently used only in tests, so this is just hardening.
iov.iov_len doesn't change after calling recvmsg() so it remains set to
sizeof(ntpmsg), which makes the check for a short packet always false.
Let's fix that by checking the actual size of the received data instead.
This simply mirrors the same overflow check we already have in
strrepa(), in case someone passed us a sufficiently long string.
strrep() is currently used only in tests, so this is just hardening.
All non-test users iovec_wrapper define the struct as a field in a
bigger structure, so we never free it individually. Let's simplify the
code and assume it is never null.
RFC 8996 says:
> This document formally deprecates Transport Layer Security (TLS)
> versions 1.0 (RFC 2246) and 1.1 (RFC 4346). Accordingly, those
> documents have been moved to Historic status. These versions lack
> support for current and recommended cryptographic algorithms and
> mechanisms, and various government and industry profiles of
> applications using TLS now mandate avoiding these old TLS versions.
> TLS version 1.2 became the recommended version for IETF protocols in
> 2008 (subsequently being obsoleted by TLS version 1.3 in 2018),
> providing sufficient time to transition away from older versions.
> Removing support for older versions from implementations reduces the
> attack surface, reduces opportunity for misconfiguration, and
> streamlines library and product maintenance.
This code probably only talks to our own receiver which uses
libmicrohttpd. That in turn delegates to GnuTLS, which supports
1.2, 1.3, 3.0, etc.
Previously we compiled curl-util.c at least two times, and then also
shared it using the extract+object. Let's build a static "convenience lib"
for it.
(Using extract+object everywhere is not possible because the different
places where it is used are conditionalized independently so we don't
have a single "source" that is always available.)
The descriptions for boolean options are adjusted to work better
with BOOL as the metavar.
Description of --copy is fixed, fixup for
f649325ba7.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Metavars in --help are adjusted to make the left column less
wide. --no-ask-password and --quiet are now shown in help.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
A few --help strings are changed to the common option variants.
The optional args for --unit, --user-unit, --xattr, --cgroup-id
are shown in synopsis.
A define is defined for the default of --depth to make things
clearer.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
This is a bit tricky. Previously, the --help string said
"-x --xattr=BOOL", which normally means that '-x BOOL' and '--xattr BOOL'
and '--xattr=BOOL' are all accepted and equivalent. But actually only
the third form was accepted. '-x' should have been and is now documented
as "Same as --xattr=true". The man page tried to explain this, but not
very strongly. So update the man page to have more emphasis and restore
the special behaviour for -x and -c. This is a on old program, so I
think in this case, maintaining compatiblity in behaviour is important.
arg_names is changed to be a normal strv. In the new parser code,
the argument is returned as a const char*. Dropping the const
to stuff it into the array would be too ugly.
The metavars for optional args are now shown in --help.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Ensure only privileged users can call the system scope machined's
APIs that get data out of a machine
Follow-up for 1bd979dddb
Follow-up for 9153b02bb5
The parsing "mode" is specified as an exclusive mode, i.e. a combination
of "+" and "-" is not supported. In principle this could be supported,
but we don't use that in our code and are unlikely ever to do so.
As soon as machinectl list-images has an mstack entry updatectl fails
because systemd-sysupdated crashes with an assertion failing because
the mstack case was not handled.
For now mstack is not supported as image for sysupdate to operate on
and we can skip it.
Fixes https://github.com/systemd/systemd/issues/41649
This will make it easier to add new modes of operation later.
But I'm happy with how this came out — I think the mode setting
is nicer to read then the old bool.
Move more common definitions in the header file instead of repeating
them in bunch of places. src/import/curl-util.[ch] is renamed so that
it's shared more naturally with other components.
sd_varlink_error() deliberately returns a negative errno mapped from
the error id on success so callbacks can `return sd_varlink_error(...);`
to enqueue the reply and propagate a matching errno at once. When
varlink_dispatch_method() dispatches a configured error sentinel itself,
it doesn't need that mapping — but it was treating any negative return
as a dispatch failure and logging "Failed to process sentinel" even
though the error reply had been successfully enqueued.
Detect success via the state transition to VARLINK_PROCESSED_METHOD
instead, so only genuine enqueue failures are logged.
Add a test that launches QEMU with -machine none (no bootable image
needed) and exercises the QMP client library against the real QMP
implementation:
- test_qmp_client_qemu_handshake_and_schema: sends query-qmp-schema
(~200KB response that exercises the buffered multi-read() path)
via qmp_client_invoke(), then cleanly shuts down QEMU via quit.
The QMP handshake completes transparently inside invoke().
- test_qmp_client_qemu_query_status: validates query-status response
parsing, stop/cont command sequencing with id correlation, and state
verification between commands
The test is automatically skipped when QEMU is not installed.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Test the QMP client library using a mock QMP server over a socketpair:
- test_qmp_client_basic: Verifies full handshake, query-status with
response parsing, stop/cont commands, and asynchronous STOP event
delivery via the sd-event I/O callback
- test_qmp_client_eof: Verifies that the client properly detects
server disconnection (EOF) and returns a disconnect error
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Add new verbs for controlling vmspawn VMs:
machinectl poweroff <machine>
machinectl pause <machine>
machinectl resume <machine>
Each verb discovers the machine's varlinkAddress via machined's
Machine.List, connects directly to vmspawn's varlink socket, and
calls the corresponding io.systemd.MachineInstance method.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
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>