Commit Graph
1780 Commits
Author SHA1 Message Date
Daan De Meyer 1e084aad7d shared: move machine registration to shared machine-register.{c,h}
Move register_machine() and unregister_machine() from
vmspawn-register.{c,h} into shared machine-register.{c,h} so both
nspawn and vmspawn can use the same implementation.

The unified register_machine() uses varlink first (for richer
features like SSH support and unit allocation) with a D-Bus
RegisterMachineWithNetwork fallback for older machined. The
interface adds a class parameter ("vm" or "container") and
local_ifindex for nspawn's network interface support.

The unified unregister_machine() similarly tries varlink first
(io.systemd.Machine.Unregister) before falling back to D-Bus.

Both register_machine() and unregister_machine() only log at debug
level internally, leaving error/notice logging to callers.

Add register_machine_with_fallback() which tries system and/or user
scope registration based on a RuntimeScope parameter
(_RUNTIME_SCOPE_INVALID for both), and
unregister_machine_with_fallback() as its counterpart. Both use
RET_GATHER() to collect errors from each scope.

Make --register= a tristate (yes/no/auto) defaulting to auto. When
set to auto, registration failures are logged at notice level and
ignored. When set to yes, failures are fatal.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 17:13:40 +02:00
Daan De Meyer c8a68dc7b3 nspawn: move boot_id and kmsg backing file creation to outer child
Follow-up for af5126568a ("nspawn: keep backing files for boot_id and
kmsg bind mounts alive").

The backing files for the boot_id and kmsg bind mounts were previously
created in the inner child. However, /run/host/ is remounted read-only
by mount_all() in the inner child (via the MOUNT_IN_USERNS mount table
entry) before setup_boot_id() and setup_kmsg() run, so creating files
there would fail with EROFS.

Fix this by splitting the file creation into separate functions
(setup_boot_id_file() and setup_kmsg_fifo()) that run in the outer
child, where /run/host/ is still writable. The bind mounts onto /proc
remain in the inner child, since procfs is only mounted there.

Also move the backing files from /run/ to /run/host/ and drop the dot
prefix, since /run/host/ is the container-manager-owned namespace and
there is no need to hide these files there. Additionally, apply
userns_lchown() to the created files, matching the convention used by
all other outer child functions that create files in the container.
2026-04-01 18:19:55 +01:00
Daan De MeyerandClaude Opus 4.6 af5126568a nspawn: keep backing files for boot_id and kmsg bind mounts alive
Both setup_boot_id() and setup_kmsg() previously created temporary files
in /run, bind mounted them over their respective /proc targets, and then
immediately unlinked the backing files. While the bind mount keeps the
inode alive, the kernel marks the dentry as deleted.

This is a problem because bind mounts backed by unlinked files cannot be
replicated: both the old mount API (mount(MS_BIND)) and the new mount
API (open_tree(OPEN_TREE_CLONE) + move_mount()) fail with ENOENT when
the source mount references a deleted dentry. This affects
mount_private_apivfs() in namespace.c, which needs to replicate these
submounts when setting up a fresh /proc instance for services with
ProtectProc= or similar sandboxing options — with an unlinked backing
file, the boot_id submount simply gets lost.

Fix this by using fixed paths (/run/proc-sys-kernel-random-boot-id and
/run/proc-kmsg) instead of randomized tempfiles, and not unlinking them
after the bind mount. The files live in /run which is cleaned up on
shutdown anyway.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 12:46:09 +02:00
Daan De Meyer 614509699a loop-util: use auto-detect open mode for loop device setup
When callers do not explicitly request read-only mode, pass open_flags
as -1 (auto-detect) instead of hardcoding O_RDWR. This enables the
existing O_RDWR-to-O_RDONLY retry logic in loop_device_make_by_path_at()
which falls back to O_RDONLY when opening the backing device with O_RDWR
fails with EROFS or similar errors.

Previously, callers passed O_RDWR explicitly when read-only mode was not
requested, which bypassed the retry logic entirely. This meant that
inherently read-only block devices (such as CD-ROMs) would fail to open
instead of gracefully falling back to read-only mode.

Also propagate the unresolved open_flags through
loop_device_make_by_path_at() into loop_device_make_internal() instead
of resolving it to O_RDWR early. For loop_device_make_by_path_memory(),
resolve to O_RDWR immediately since memfds are always writable.

In mstack, switch from loop_device_make() to
loop_device_make_by_path_at() with a NULL path, which reopens the
O_PATH file descriptor with the appropriate access mode. This is
necessary because the backing file descriptor is opened with O_PATH,
which prevents loop_device_make_internal() from auto-detecting the
access mode via fcntl(F_GETFL).
2026-04-01 10:02:15 +02:00
Daan De Meyer 526b8eeb5d More assorted coverity fixes (#41413) 2026-03-30 23:34:44 +02:00
Michael Vogt f3c49a597f nspawn: make check-pointer-deref clean
Add the needed assert changes to make the code clean
for the new check-pointer-deref script.
2026-03-30 13:36:00 +02:00
Luca Boccassi 569c849be4 nspawn-oci: add asserts for UID/GID validity after dispatch
Coverity flags UINT32_MAX - data.container_id as an underflow
when container_id could be UID_INVALID (UINT32_MAX). After
successful sd_json_dispatch_uid_gid(), the values are guaranteed
valid, but Coverity cannot trace through the callback. Add
asserts to document this invariant.

CID#1548072

Follow-up for 91c4d1affd
2026-03-30 10:55:33 +01:00
Luca Boccassi 7b85f5498a nspawn: normalize pivot_root paths
Originally reported on yeswehack.com as:
YWH-PGM9780-116

Follow-up for b53ede699c
2026-03-12 00:24:01 +00:00
Luca Boccassi 61bceb1bff nspawn: apply BindUser/Ephemeral from settings file only if trusted
Originally reported on yeswehack.com as:
YWH-PGM9780-116

Follow-up for 2f89304490
Follow-up for a2f577fca0
2026-03-12 00:24:01 +00:00
Mike Yuan 769b0bf746 various: mark arg_* as static 2026-03-04 14:32:15 +01:00
Frantisek Sumsal 864c08f575 import,nspawn: fix a couple of typos in mountfsd 2026-03-03 00:03:19 +01:00
Frantisek Sumsal 83b8daa032 nspawn: actually mask certain files under /proc/
/run/systemd/inaccessible/ exists only on host - in the container we have
/run/host/inaccessible/, and since all the inaccessible mounts have
MOUNT_IN_USERNS we need to use the latter one, otherwise the masking
gets silently skipped:

~# SYSTEMD_LOG_LEVEL=debug systemd-nspawn -q --directory=foo ls -la /proc/kallsyms
...
Bind-mounting /run/systemd/inaccessible/reg on /proc/kallsyms (MS_BIND "")...
Failed to mount /run/systemd/inaccessible/reg (type n/a) on /proc/kallsyms (MS_BIND ""): No such file or directory
Changing mount flags /proc/kallsyms (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND "")...
Failed to mount n/a (type n/a) on /proc/kallsyms (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND ""): Invalid argument
Bind-mounting /run/systemd/inaccessible/reg on /proc/kcore (MS_BIND "")...
Failed to mount /run/systemd/inaccessible/reg (type n/a) on /proc/kcore (MS_BIND ""): No such file or directory
Changing mount flags /proc/kcore (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND "")...
Failed to mount n/a (type n/a) on /proc/kcore (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND ""): Invalid argument
...
Inner child finished, invoking payload.
-r--r--r--. 1 root root 0 Feb 25 13:19 /proc/kallsyms
2026-03-02 20:22:06 +01:00
Thomas Weißschuh 93101e7ef0 nspawn: allow cachestat systemcall
cachestat(2) is essentially a better variant of mincore(2).
As mincore(2) is already allowed, also allow cachestat(2).
2026-03-02 09:29:27 +01:00
Daan De Meyer 3363693935 nspawn: Add support for delegated UID ranges
We expose this via --private-users-delegate= which takes the number of
ranges to delegate. On top of delegating the ranges, we also mount in
the nsresourced socket and the mountfsd socket so that nested containers
can use nsresourced to allocate from the delegated ranges and mountfsd to
mount images.

Finally, we also create /run/systemd/dissect-root with systemd-tmpfiles to
make sure it is always available as unpriv users won't be able to create it
themselves.
2026-02-25 11:31:06 +01:00
Lennart Poettering 68ed4f3c66 mountfsd,nsresource: allow recycling mountfsd/nsresourced client connections
So far we opened a new Varlink connection for every mountfsd/nsresourced
method call. Given each tool only does a very small number of calls
(usually 1…5) on them and the connections are cheap this is not too
wasteful. Nonetheless, let's do something about it, and allow reusing
the connection for multiple calls.

This not only makes things a bit more efficient, but has one more
important benefit: Varlink connections pin the security context of the
client when connecting. This means that varlink method calls done with a
connection established while some code was privileged will still operate
as privieged once privs are dropped, until the connection is closed.
This pinning effect is really nice, as it gives us behaviour in a
"capability system" like scheme. Later code is going to use that to
continue doing certain priv userns ops even after unsharing userns and
becoming fully unpriv.
2026-02-19 15:08:19 +01:00
Lennart Poettering 116394f7ce tree-wide: move logging from varlink clients in nsresource.c/dissect-image.c into callers
These calls are "library-like", hence better should only debug log on
their own, not more.
2026-02-19 15:05:15 +01:00
Lennart Poettering 1bc237dd7a nspawn: add support for running mstack container images 2026-02-19 15:05:15 +01:00
Daan De Meyer f6bcd125db nspawn: Join network namespace with setns()
We don't have /proc mounted which means namespace_enter() won't work
on older kernels, so use setns() instead.
2026-02-17 11:45:01 +01:00
Daan De Meyer 48c84fe730 nspawn-mount: Use setns() in wipe_fully_visible_api_fs()
namespace_enter() now does a is_our_namespace() check, which requires
/proc on older kernels, which is not available anymore after we call
do_wipe_fully_visible_api_fs() in wipe_fully_visible_api_fs().

Let's just call setns() instead as namespace_enter() is overkill to
enter a single namespace anyway.
2026-02-17 04:55:24 +01:00
nikstur 5b193a8e23 meson: read more progs from PATH
Find more progs on PATH instead of hardcoding them.
2026-02-16 14:32:38 +01:00
Zbigniew Jędrzejewski-Szmek b4df0a9ee6 nspawn: split out helper to parse --private-users
This is just to make parse_argv() slightly more managable.
2026-02-13 11:07:22 +01:00
Zbigniew Jędrzejewski-Szmek 26de1563d0 nspawn: simplify parsing of --hostname/--machine 2026-02-11 12:50:51 +01:00
Michael Vogt 6e67fc2938 vmspawn: add --ephemeral option similar to nspawn
This patch adds a `--ephemeral` option to vmspawn that will turn
on snapshot mode on the qemu disk passed via `--image` or the
directory passed via `--directory`. For disk images it uses the
native mechanism that qemu provides. For directories it (re)uses
the snapshot mechanism that nspawn is using, i.e. it will create
a btrfs snapshot if possible and if not falls back to a traditional
directory copy.
2026-02-03 20:22:14 +01:00
Michael Vogt 96dd2df514 nspawn: extract snapshot creation into new shared helper
This commit extracts the creation of the snapshot for
nspawn into a shared helper. Its not a lot of code but its
subtle so having a single place seems beneficial.

While extracting the snapshot code got tweaked/simplified based
on the feedback from Yu (many thanks!).

With that we can simplify the snapshot delete and error handling
as well. The shared helper is then going to be used by vmspawn
when it also gets the --ephemeral option.
2026-02-02 09:04:37 +01:00
Mike Yuan 6753bd8a2f mountpoint-util: assume MS_NOSYMFOLLOW is available
Since our kernel baseline is v5.10 now.
2026-01-19 13:33:26 +01:00
Mike Yuan 742308caba nspawn: drop compat glue for kernel < 3.14 2026-01-19 12:51:55 +01:00
Luca Boccassi 3e2a5dc2e1 dissect: support mount options when going through mountfsd, requiring privileges via polkit (#39394)
RootImageOptions=/ExtensionImages=/MountImages= all support custom
mount options, but mountfsd does not support it. Add varlink
parameters to allow callers to specify mount options so that
those directives can work as expected. Require additional privs via
polkit.
2026-01-16 14:55:02 +00:00
Daan De Meyer 3fa3a4fd15 vpick: Fix pick_filter_image_any
Currently, pick_filter_image_any matches any image
with any suffix, which is way more than it should
be doing. It should only be matching images with
the .raw suffix.

Let's address this shortcoming by allowing to pass
multiple filters to path_pick(), and define
pick_filter_image_any as the combination of the
raw and directory image filters.

Fixes #40083
2026-01-16 13:07:47 +01:00
Yu Watanabe 7f6cf19513 mountpoint-util: make is_mount_point_at() take usual dir_fd + path style arguments 2026-01-13 10:21:05 +09:00
Luca Boccassi 3a8759e5d4 dissect: support mount options when going through mountfsd
RootImageOptions=/ExtensionImages=/MountImages= all support
custom mount options, use the new mountfsd parameters to
configure them if they are specified.

This requires additioanl privileges via polkit due to security
implications of mount options, so document an example policy
that allows to use the nosuid mount option.
2026-01-07 00:47:53 +01:00
Daan De Meyer 52ecf376fa tree-wide: Migrate to pidref_safe_fork()
Let's migrate all remaining callers of safe_fork()
to pidref_safe_fork() and get rid of safe_fork().
2026-01-02 20:08:41 +01:00
Yu Watanabe 431fc656bc Bump required minimum version of libseccomp to 2.4.0
Major distributions already have libseccomp 2.5.x or newer.
Let's bump to the required minimum version to 2.4.0, which provides
SCMP_ACT_KILL_PROCESS, SCMP_ACT_LOG, SCMP_ARCH_PARISC, and
SCMP_ARCH_PARISC64.

Note, libseccomp 2.4.0 was released on 2019-03-15.

See also #38608.
2026-01-02 12:54:18 +09:00
Daan De Meyer aec52c1e6e string-table: Introduce DECLARE_STRING_TABLE_LOOKUP() and friends
Let's introduce these for the following two reasons:
- Using them makes sure the parameter names match between declaration
  and definition (if both use the corresponding macros).
- They make sure developers can't forget the _const_ and _pure_
  attributes for the declarations.

This commit also includes some include sorting fixes
2026-01-02 04:05:45 +09:00
Daan De Meyer fbd276cb86 tree-wide: Use pidref_wait_for_terminate_and_check()
Let's use the pidref variants for waiting and
checking a process everywhere and get rid of the
non pidref variants.
2025-12-20 15:50:47 +01:00
Yu Watanabe 93378148d4 tree-wide: normalize comment style 2025-12-15 08:50:13 +09:00
Daan De Meyer 6a9f0641cd tree-wide: Fix declaration/definition parameter name mismatches 2025-11-26 19:02:31 +09:00
Daan De Meyer 9a6a8f35eb tree-wide: Small fixes for various clang-tidy warnings 2025-11-26 16:22:00 +09:00
Lennart Poettering 77a1e2dec6 Revert "nspawn: Fix broken host links for container journals" 2025-11-24 16:34:00 +01:00
Lennart Poettering 39c343daa6 nspawn: fix CI 2025-11-24 15:53:47 +01:00
Lennart Poettering 800d11c36c nspawn: load three libraries we'll need later before we fork() a child 2025-11-24 11:49:44 +01:00
Lennart Poettering 2c7bdaf9f1 dlfcn-util: let's make our dlopen() code fail if we enter a container namespace
Now that we dlopen() so many deps, it might happen by accident that we
end up dlopen()ening stuff when we entered a container, which we should
really avoid, to not mix host and container libraries.

Let's add a global variable we can set when we want to block dlopen() to
ever succeed. This is then checked primarily in
dlopen_many_sym_or_warn(), where we'll generate EPERM plus a log
message.

There are a couple of other places we invoke dlopen(), without going
through dlopen_many_sym_or_warn(). This adds the same check there.
2025-11-24 09:19:33 +01:00
Daan De Meyer 87fbd33372 clang-tidy: Fix all remaining misc-include-cleaner violations
- Remove unused includes
- Add common false positive headers to misc-include-cleaner.IgnoreHeaders
- Add IWYU pragma keep for uncommon false positive headers
2025-11-22 10:19:41 +01:00
Chris Down 11eebc2357 nspawn: Fix broken host links for container journals
Commit 88252ca changed nspawn to always run from a temporary mount
directory (e.g., /tmp/nspawn-root-XXXXXX). This was a good
simplification for mount logic, but it unintentionally broke the
--link-journal feature.

The setup_journal() helper was subsequently passed this ephemeral path
instead of the persistent machine path (from --directory= or --image=).
This caused the host to create broken symlinks pointing to a temporary
directory that would soon be gone.

Fix this by storing the original path and plumbing it through to
setup_journal().

All other mount-related logic in outer_child() continues to use the
temporary `directory` variable.

Fixes: #39472
2025-11-21 21:04:34 +08:00
Zbigniew Jędrzejewski-Szmek 5220bb8c3f meson: automatically add 'extract' to 'sources'
In all cases, everything that we list in 'extract', we also list in
'sources'. We can simplify things by automatically appending the first
list to the second.

In the listings, move 'extract' key right below 'sources', since now
they are both "sources", just with slightly different meanings.
2025-11-20 10:03:48 +09:00
Lennart Poettering a5023c7a4b nspawn: move oci code to use json_dispatch_strv_environment() 2025-11-17 16:53:13 +01:00
Lennart Poettering 28fd2a66f4 nspawn: fix flags type for chase() 2025-11-18 00:36:58 +09:00
Yu Watanabe a8156588fa cgroup-util: drop 'controller' argument from cg_get_path()
The argument is not used anymore. Let's drop it.
2025-11-17 21:31:50 +09:00
Yu Watanabe b525a72f7b cgroup-util: drop cgroup v1 support from cg_pid_get_path()
We have dropped cgroup v1 support in v258. Let's drop legacy code.
Then, we can drop 'controller' argument from cg_pid_get_path() and
cg_pidref_get_path().
2025-11-17 21:30:29 +09:00
Yu Watanabe 6475926a59 cgroup-util: drop 'controller' argument from cg_path_open()
Nowadays it always takes SYSTEMD_CGROUP_CONTROLLER as controller.
Let's drop it.

No functional change, just refactoring.
2025-11-17 21:30:29 +09:00
Lennart Poettering 08d75cfb99 dissect-image,execute: switch root hash/root hash sig storage to struct iovec
let's go one step further on our iovec'ification journey.

No change in behaviour, just rework to make struct iovec used
everywhere.
2025-11-16 23:36:11 +01:00