This will allow maintainers to mention claude in comments on issues
and prs to do stuff like review something or try to reproduce a bug
or other stuff. Let's give it a try and see whether we like it or
not.
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.
ENOENT means /dev/loop-control isn't there which means we're in a
container and should go via mountfsd.
At the same time, reverse the check for fatal actions as almost all
actions can be done via mountfsd, only --attach needs the loop device.
- Allow foreign UID range
- Allow delegated UID ranges
Both of these can now be mapped by nsresourced into user namespaces
and hence should be accepted by mountfsd.
Whenever delegating UID ranges to a user namespace, it can also be
useful to map the foreign UID range, so that the container running in
the user namespace with delegated UID ranges can download container
images and unpack them to the foreign UID range.
Let's add an option mapForeign to make this possible. Note that this option
gives unprivileged users full access to the any foreign UID range owned directory
that they can access. Hence it is recommended (and already was recommended) to
store foreign UID range owned directories in a 0700 directory owned by the
owner of the tree to avoid access and modifications by other users.
This is already the case for the main users of the foreign UID range,
namely /var/lib/machines, /var/lib/portables and /home/<user> which all
use 0700 as their mode.
Users will also be able to create foreign UID range owned inodes in any
directories their own user can write to (on most systems this means /tmp,
/var/tmp and /home/<user>).
mkosi does all of its environment setup in an unprivileged user
namespace with an identity mapping. When it invokes nspawn and nspawn
tries to get a transient userns from nsresourced, this fails as no
transient ranges are mapped into mkosi's unprivileged userns (as doing
so would require privileges).
To fix this problem, let's allow allocating unprivileged self user
namespaces in nsresourced, similar to what the kernel allows, except that
we also support delegations for these. This means that mkosi can get its
unprivileged userns as before from nsresourced, but it can also request a
delegated 64K range inside that userns as well, which nsresourced can then
allocate to nspawn later when it asks for one.
Similar to the kernel, we disallow setgroups for self mappings. However,
instead of doing this via /proc/self/setgroups, which applies to the current
user namespace and all its child user namespaces, we use the BPF LSM to deny
setgroups instead, so that it can still be allowed for child user namespaces.
We need this because as soon as a container launches in a child user namespace
using one of the delegated mappings, it has to be able to do setgroups() to be
able to function properly.
To allow mapping the root user, we need to add the CAP_SETFCAP capability to
nsresourced.
We want to support the scenario where we bind mount the nsresourced
varlink socket into a container to allow nested containers where the
outer container runs in its own transient range from nsresourced but
can still allocate transient ranges for its own nested containers.
To support this use case let's add support for delegation. Delegated
ranges are allocated when allocating the primary range and are propagated
1:1 to the user namespace. We track delegated ranges in ".delegate" files
in the userns registry so that they can't be used for other range allocations.
We make one exception for delegated ranges though, if we get a request from
a user namespace that is a child of the user namespace that owns the delegated
ranges, we allow allocating from the delegated range. The parent userns already
has full ownership over the child userns, so it doesn't matter that the parent
userns and the child userns share the same range. This allows making use of
delegated ranges without having to run another copy of nsresourced inside the
parent userns to hand out from the delegated range.
To support recursive delegations, we keep track of the previous owners of the
delegated range and restore ownership to the last previous owner when the current
owner is freed.
The purpose of the userns-restrict BPF-LSM program is to prevent the
transient ranges leaking to disk, so let's allow operations outside the
transient UID ranges, even if the mount is not allowlisted.
This is preparation for the next commits where we'll add support for mapping
the current user and the foreign UID range into the user namespaces provisioned
by nsresourced. Operations creating files/directories as these UIDs/GIDs should
not need the corresponding mount to be allowlisted with nsresourced.
xfsprogs 6.17.0 added support for populating xfs filesystems from
directories. As this supports extended attributes unlike our current
hack with protofiles. Let's make use of the new feature in mkfs-util.c
As there's no clean way to do feature detection on the mkfs.xfs binary,
we drop support for the old hack with protofiles that we had before.
If we include a verity signature but the corresponding key is not in
the kernel keyring or userspace, try to get polkit auth similar to how
we do the same if the image doesn't pass the policy.
If we're asked to look up our own user namespace mapping, don't go
via fd as trying to setns() to our own user namespace in
userns_enter_and_pin() would fail with EPERM as the kernel doesn't
allow switching to your own userns.
This allows building with musl on glibc systems as follows:
env \
CC=musl-gcc \
CXX=musl-gcc \
CFLAGS="-idirafter /usr/include" \
CXXFLAGS="-idirafter /usr/include" \
meson setup --auto-features=disabled -Dlibc=musl musl
This was made a strv to handle either directories or raw images but
since we now handle that via multiple PickFilter instances, we don't
need suffixes to be a strv anymore.
You can register whatever process you want in the user machined instance
that is running in the same namespace as pid 1 as machined won't be allowed
to do anything privileged anyway that could be dangerous when running as a user
instance.
We have to skip the check as we user machined instances don't have
privileges to inspect pid1's user namespaces.
Let's check if we're already in the right namespaces and call connect()
directly if that's the case. This can easily happen when the machine is
specified as .host or so.
These checks may rely on /proc on older kernels which we could lose access
to by joining namespaces so let's do all the checks first and then join
namespaces.
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.
The default behavior is to sync repository metadata for every image
that does not have a cache and we recently changed behavior to
invalidate
all cached images whenever we decide the repository metadata needs to
be resynced.
In systemd we have two images that are not cached because they use
BaseTrees=
hence set CacheOnly=metadata to explicitly indicate these two images
should never cause a repository metadata if resync even though they are
not cached.
The default behavior is to sync repository metadata for every image
that does not have a cache and we recently changed behavior to invalidate
all cached images whenever we decide the repository metadata needs to
be resynced.
In systemd we have two images that are not cached because they use BaseTrees=
hence set CacheOnly=metadata to explicitly indicate these two images
should never cause a repository metadata if resync even though they are
not cached.
* 66d51024b7 man: Update caching section
* 4eac60f168 Remove all cached images if repository metadata will be synced
* 025c6c0150 Move Incremental= to inherited settings in docs
* 427970d8fd Make MakeScriptsExecutable= a multiversal setting
* 53bd2da6fe Look at all CacheOnly= settings to determine if we need to sync metadata
* 114ae558ef config / qemu: add Console=headless
There's no need to pass in a boolean to decide whether we use
namespace_enter_delegated() or not. Instead, we can just check if we
have CAP_SYS_ADMIN in our own user namespace. If we don't, then we have
to insist on a child user namespace being passed in and we have to enter
it first to get CAP_SYS_ADMIN as without CAP_SYS_ADMIN we wouldn't be
able
to call setns() in the first place. If we do have CAP_SYS_ADMIN, we can
always enter the other namespaces first before entering the user
namespace.
Additionally, we don't fail anymore if we can't reset the UID/GID since
a
root user might not always be available in every user namespace we might
enter.
There's no need to pass in a boolean to decide whether we use
namespace_enter_delegated() or not. Instead, we can just check if we
have CAP_SYS_ADMIN in our own user namespace. If we don't, then we have
to insist on a child user namespace being passed in and we have to enter
it first to get CAP_SYS_ADMIN as without CAP_SYS_ADMIN we wouldn't be able
to call setns() in the first place. If we do have CAP_SYS_ADMIN, we can
always enter the other namespaces first before entering the user namespace.
Additionally, we don't fail anymore if we can't reset the UID/GID since a
root user might not always be available in every user namespace we might
enter.
If /proc/self/gid_map is empty, the kernel will refuse setgroups(),
so don't attempt it if that's the case on top of the /proc/self/setgroups
check we already have.
Using --first-parent --no-merges seems to exclude not just the merge
commits but all the commits from the merge as well. Let's use only
--no-merges to get just the commits without merges.
Building these over and over again is extremely wasteful. Let's just
build them once and not touch them again unless -ff is specified or
their cache is out-of-date, which is exactly what Incremental=relaxed
does.
This means mkosi.extra/ and such changes won't be picked up for these
anymore unless -ff is used, but that slight annoyance is totally
outweighed by the time saved building the images.
A more straightforward way to extend the default initrd rather than
using a subimage. This mainly allows us to take advantage of mkosi
automatically figuring out whether the initrd needs to be built or not,
speeding up builds when building directory images as the initrd can be
skipped in that case.
* d6ddc66acb Use python3.12 as interpreter in CentOS Stream 9 zipapp
* 89d876c86f tests: fix running pytest on undetected distro
* 61a47eeb1c centos: Fix EPEL repositories for RHEL 10
* e5aa19e2bc oci: allow user defined labels and annotations
* 1680fc5789 man: be more precise that the tools tree distribution is decided by the host distribution
* 7025b8e67d Support resizing output image
We don't want to vacuum anything if we're just going to fail just
afterwards because a GPT partition label exceeds the maximum size
so let's compute the temporary paths for all transfers before we do
any vacuuming or acquiring.
Currently, if we're copying a file, we won't copy the owner UID/GID
from the source. If we're copying a directory, we will copy the owner
UID/GID from the source. Let's give users a bit more control over this
behavior by introducing --copy-ownership= which will default to the
current behavior but allows users to explicitly enable/disable copying
of ownership.
Let's check for CAP_SYS_ADMIN instead of root for these, and make
unmounting more graceful if we can't access the backing loop device
because of permission issues. This allows mounting and unmounting images
from an unprvileged mount namespace. The actual files in the image will
end up owned by nobody:nobody because we'll be in an unprivileged user
namespace, but assuming the directory permissions are not too strict, this
still allows interacting with the image in useful ways.
These actions interact with the host. The former needs privileges to
write into the image, the latter needs privileges to write on the host.
Neither will have the privileges required if the image is attached under
a private userns, hence, don't use one.
Streaming methods which are not used as a continuous subscription but
instead only send a series of objects all end up with the same workaround
to be able to figure out when to send sd_varlink_reply() or sd_varlink_notify().
Let's generalize this in sd-varlink itself.
Let's introduce the concept of a sentinel, which is a reply that will be sent
by sd-varlink if no other reply was queued by a method callback. The sentinel
is configured with varlink_set_sentinel(). If a sentinel is configured,
sd_varlink_reply() can be used more than once in streaming methods to queue
multiple values to stream to the client. The last queued reply is not sent
until the callback finishes. When the callback finishes, the last reply is
sent without "continues: more". If no reply was queued, the sentinel is sent.
This always using only sd_varlink_reply() in such streaming methods and
leaves sd_varlink_notify() available solely for continuous subscription
streaming methods, where we never use sd_varlink_reply() and instead disconnect
when the server exits.
This contains the "bootctl install" related work from the #38764 split
out, but also includes the preparatory work already split out into
#40446.
I'll rebase this PR once the prep work is merged.
This has a simple CI test already, and has docs
open_tree() will fail with EINVAL when passed a directory file descriptor
that comes from another mount namespace. While this should be fixed in a
future kernel, let's workaround the issue for now by entering the mount
namespace of the peer if needed and calling open_tree() there and then
passing the fd back to the mountfsd process.
* 215a9497cc fedora: Use N-1 key as well when querying rawhide GPG key
* 842a37ed6c Add MakeScriptsExecutable= setting to optionally try to
make scripts executable before bailing out
* 814f2004bb build(deps): bump github/codeql-action from 4.31.9 to
4.32.0
* d8f4f628bf build(deps): bump actions/checkout from 6.0.1 to 6.0.2
* 3e55361142 docs: remove superfluous definition colon
* 5901524c48 mkosi-tools: add libarchive-tools package.
* 968392f1b9 docs: Add information about gui mkosi-tools profile
* 0e2960c245 Add missing call to run_locale_gen()
* 41cd2067bc rpm: Set pkgverify_level to digest
* 86fe0f448a dnf: Give advanced users some control over plugins
* 50a1feee52 run: Improve sandbox command logging
* b1dffe1c3c Fix environment variable name for systemd-repart
* 07726068d9 Allow specifying "default" value for Initrds=
* 704f163ec0 Allow setting PORTABLE_PREFIXES= via Environment=
* e6588afb45 opensuse: More GPG key handling fixes
* c367f993dd opensuse: Fetch remote keys as well if RepositoryKeyFetch=
is enabled
* 31852c9314 ci: Use mkosi box for unit test CI as well
* e4229f5bf5 Make sure we pass the right context to
finalize_default_initrd()
* 9b431b783a tools: don't pull in virtiofsd in bookworm tools trees
* ae2d88d463 build(deps): bump github/codeql-action from 4.31.6 to
4.31.9
* 933401a8b6 build(deps): bump actions/checkout from 6.0.0 to 6.0.1
* 6bfeb4ac86 opensuse: Import GPG keys for all repositories
* 9829b9136f Add support for locale-gen
* 63ae86ec04 nixos: Use repository key fetching by default on nixos
* f01ca9904b docs: Reword dependencies vs tools tree requirement a bit
* ab47ba25ef docs: Minor correction on enabling unprivileged namespaces
* 7bd46a417e docs: Update unprivileged user namespace docs
* 14d2d37a19 sandbox: Make sure we're dumpable before writing uidmap files
* 215a9497cc fedora: Use N-1 key as well when querying rawhide GPG key
* 842a37ed6c Add MakeScriptsExecutable= setting to optionally try to make scripts executable before bailing out
* 814f2004bb build(deps): bump github/codeql-action from 4.31.9 to 4.32.0
* d8f4f628bf build(deps): bump actions/checkout from 6.0.1 to 6.0.2
* 3e55361142 docs: remove superfluous definition colon
* 5901524c48 mkosi-tools: add libarchive-tools package.
* 968392f1b9 docs: Add information about gui mkosi-tools profile
* 0e2960c245 Add missing call to run_locale_gen()
* 41cd2067bc rpm: Set pkgverify_level to digest
* 86fe0f448a dnf: Give advanced users some control over plugins
* 50a1feee52 run: Improve sandbox command logging
* b1dffe1c3c Fix environment variable name for systemd-repart
* 07726068d9 Allow specifying "default" value for Initrds=
* 704f163ec0 Allow setting PORTABLE_PREFIXES= via Environment=
* e6588afb45 opensuse: More GPG key handling fixes
* c367f993dd opensuse: Fetch remote keys as well if RepositoryKeyFetch= is enabled
* 31852c9314 ci: Use mkosi box for unit test CI as well
* e4229f5bf5 Make sure we pass the right context to finalize_default_initrd()
* 9b431b783a tools: don't pull in virtiofsd in bookworm tools trees
* ae2d88d463 build(deps): bump github/codeql-action from 4.31.6 to 4.31.9
* 933401a8b6 build(deps): bump actions/checkout from 6.0.0 to 6.0.1
* 6bfeb4ac86 opensuse: Import GPG keys for all repositories
* 9829b9136f Add support for locale-gen
* 63ae86ec04 nixos: Use repository key fetching by default on nixos
* f01ca9904b docs: Reword dependencies vs tools tree requirement a bit
* ab47ba25ef docs: Minor correction on enabling unprivileged namespaces
* 7bd46a417e docs: Update unprivileged user namespace docs
There's no reason to refuse copying out capsule@abc.service even if
capsule@.service already exists on the host, so let's optionally not
search for templates if we can't find an instance when looking up
units and use it in portabled.
For many use cases DynamicUser= just doesn't cut it. Specifically lots
of stuff wants to run as root. Let's support this use case by relaxing
our checks for capsules a bit.
If we fail to create a parent directory, then the error from
make_mount_point_inode_from_path() will always be
"No such file or directory" which doesn't tell us anything. Add logging
for the mkdir_parents() call as well so we get a useful error.
This does not yet support directory images properly
as systemd itself does not support unpriv directory
images properly yet.
The user profiles are a copy of the system profiles but without
DynamicUser=yes (can't be used by user managers) and without
ProtectHome=yes (this masks /home which breaks StateDirectory= which
is lcoated inside /home)