Aside from the usual boilerplate of moving the shared logic to shared/,
we also rework the implementation of --bind-user= to be similar to what
we'll do in systemd-vmspawn. Instead of messing with the nspawn container
user namespace, we use idmapped mounts to map the user's home directory on
the host to the mapped uid in the container.
Ideally we'd also use the "userdb.transient" credentials to provision the
user records, but this would only work for booted containers, whereas the
current logic works for non-booted containers as well.
Aside from being similar to how we'll implement --bind-user= in vmspawn,
using idmapped mounts also allows supporting --bind-user= without having to
use --private-users=.
This moves coverage.h to src/coverage/, and specifies path to coverage.h
with files() directive, to make it can be included even when located
outside of the include directories. Otherwise, libc-wrapper cannot be
built when -Db_coverage=true option is enabled.
Follow-up for 543a48b653.
This adds missing glue to reasonably allow unpriv users VMs/containers
to register with the system machined.
This primarily adds two things:
1. machined can now properly track VMs/containers residing in subcgroups
of units, because that's effectively what happens for per-user
VMs/containers: they are placed below the system unit `user@….service`
in some user unit.
2. machines registered with machined now have an owning UID: users can
operate on their own machines withour re-authentication, but not on
others.
Note that this is only a first step regarding machined's hookup of
nspawn/vmspawn in the long run for unpriv operation.
I think eventually we should make it so that there's both a per-user and
a per-system machined instance (so far, and even with this PR there's
still one per-system instance), and per-user containers/VMs would
registering with *both*. Having two instances makes sense I think,
because it would mean we can make machined reasonably manage the
per-user image discovery, and also do the per-system network/hostname
handling.
Google Compute Engine are not only virtual but can be also physical
machines. Therefore checking only the dmi is not enough to detect if it
is a virtual machine. Therefore systemd-detect-virt return "google"
instead of "none" in c3-highcpu-metal machine.
SMBIOS will not help us to make the difference as for EC2 machines.
However, GCE use KVM hypervisor for these VM, we can use this
information to detect virtualization. [0]
Issue and changes has been tested on SUSE SLE-15-SP7 images with
systemd-254 for both GCE, bare-metal and VM.
[0] -
https://cloud.google.com/blog/products/gcp/7-ways-we-harden-our-kvm-hypervisor-at-google-cloud-security-in-plaintext
This new helper takes both a PID and and a pidfd ID, and initializes a
PidRef from it. It ensures they actually belong together and returns an
error if not.
Continuation of #37960.
The same concern as expalined in #37960 exists also in
missing_syscall.h. If we use enough new glibc, a function we want to use
may be already provided by glibc, but our baseline glibc may not. And it
is hard to detect in our daily development.
This moves all prototypes of syscalls to relevant headers, and missing
syscall functions are defined in relevant .c files of libc wrapper. This
way, we can use usual header as is, e.g. when we want to write code with
`move_mount()`, we can simply use sys/mount.h without checking if it is
supported by our baseline glibc.
Then, move syscall definitions to the wrapper, and prototypes are moved
to relevant headers.
This also adds checks for add_key() and request_key(), as one day
glibc may be going to add some of them separatedly.
The check for fspick in meson.build is dropped, as it is currently
unused in our code.
This also moves
- basic/missing_bpf.h -> include/override/linux/bpf.h,
- basic/missing_keyctl.h -> include/override/linux/keyctl.h.
This also moves syscall tables and generators to the same directory.
Note, inclusion of asm/sgidefs.h is dropped, as it is already included
by unistd.h and sys/syscall.h.
- pass our system include directories to make generators use our libc
wrappers and latest kernel headers,
- include relevant headers in generated gperf file,
- use files() rather than find_program(), as the result of
find_program() cannot be passed to 'input' of custom_target(),
- move generate-bpf-delegate-configs.py to src/core/, as it is only used
by libcore.
- This introduces ERRNO_IS_FS_WRITE_REFUSED(), and apply it where
usable.
- This makes unexpected errors in access_fd() called by binfmt_mounted()
propagated to the caller.
- Renames binfmt_mounted() to binfmt_mounted_and_writable(), as it also
checks the fs is writable.
- Voidifies one disable_binfmt() call in shutdown.c.
The recently added test case TEST-07-PID1.subgroup-kill.sh surfaced a
race: if we enumerate PIDs in a cgroup, and the cgroup is unlinked at
the very same time reading will result in ENODEV. We need to handle that
gracefully. Hence let's do so.
Noticed while looking at:
https://github.com/systemd/systemd/actions/runs/16143084441/job/45554929264?pr=38120
We put the name of the variable in the message, but it is a local variable
and the name does not have global meaning. We end up with pointless copies
of the error string:
$ strings build/libsystemd.so.0.40.0 | grep 'big enough'
xsprintf: p[] must be big enough
xsprintf: error[] must be big enough
xsprintf: prefix[] must be big enough
xsprintf: pty[] must be big enough
xsprintf: mode[] must be big enough
xsprintf: t[] must be big enough
xsprintf: s[] must be big enough
xsprintf: spid[] must be big enough
xsprintf: header_priority[] must be big enough
xsprintf: header_pid[] must be big enough
xsprintf: path[] must be big enough
xsprintf: buf[] must be big enough
The error message already shows the file, line, and function name, which
is enough to identify the problem:
Assertion 'xsprintf: buffer too small' failed at src/test/test-string-util.c:20, function test_xsprintf(). Aborting.
Suggested in
https://github.com/systemd/systemd/pull/35892#discussion_r2180322856.
This is a tiny amount of code and does not warrant having a separate file
and spawning a separate instance of the compiler during the build.
Note: it took me a while to confirm that the contents of that table and
function don't end up in libsystemd.so. The issue is that they _are_ present in
it, unless LTO is used. We actually use link_whole[libbasic_static] for
libsystemd, so we end up with all that code there. LTO is needed to clean
that up.
Christian made this possible in Linux 6.15 with a new system call
open_tree_attr() that combines open_tree() and mount_setattr(). Because
idmapped mounts are (rightfully) not nested, we have to do some extra
shenanigans to make source we're putting the right source uid in the
userns for any idmapped mounts that we do in nspawn.
Of course we also add the necessary boilerplate to make open_tree_attr()
available in our code and wrap open_tree_attr() and the corresponding
fallback in a new function which we then use everywhere else.
These source files uses symbols provided by sys/stat.h, e.g. struct stat,
S_IFREG, S_IFBLK, and so on. Let's explicitly include sys/stat.h where
necessary.
Glibc's fcntl.h includes bits/stat.h, which provides these symbols, so
these symbols can be used without explicitly including sys/stat.h. But,
based on the discussion in #37922, we should explicitly include relevant
headers, and should not rely on the indirect inclusion.
Similar to 4f18ff2e29, but for sys/stat.h.
If one of the header is included in a C++ source file, then using
_Static_assert() triggers compile error for some reasons.
Let's use static_assert(), which can be used by both C and C++ code.
These source files uses symbols provided by sched.h, e.g.
setns(), unshare(), CLONE_NEWNS, and friends, but they do not explicitly
include sched.h. Currently, it is included indirectly via missing_syscall.h,
which is included by e.g. pidfd-util.h.
Let's explicitly include headers that provides symbols used in the code.
This is similar to 4f18ff2e29, but for sched.h.
- use unsigned for the return value of read_nr_open(), as it does not
fail, and the kernel internally uses unsigned for the value,
- when bumping the value by PID1, let's start from the kernel's maximum
value defined in fs/file.c. The maximum value should be mostly an API
of the kernel, but may changed in a future, hence still try several
times if we fail to bump the value.
Co-authored-by: Jared Baur <jaredbaur@fastmail.com>
Co-authored-by: John Rinehart <johnrichardrinehart@gmail.com>
Follow-up for c5de7b14ae
chase() is arguably a hot path in our code, hence it deserves
some caching whether open_tree() is available. Moreover,
the manual set of r to -EPERM feels kinda ugly. Let's
instead extract this bit into its own function.