machined: make registration of unpriv user's VMs/containers work (#37855)

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.
This commit is contained in:
Lennart Poettering
2025-07-11 21:10:08 +02:00
committed by GitHub
38 changed files with 1492 additions and 336 deletions
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
# shellcheck disable=SC2016
set -eux
set -o pipefail
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
if [[ ! -f /usr/lib/systemd/system/systemd-mountfsd.socket ]] ||
[[ ! -f /usr/lib/systemd/system/systemd-nsresourced.socket ]] ||
! grep -q bpf /sys/kernel/security/lsm ||
! find /usr/lib* -name libbpf.so.1 2>/dev/null | grep . ||
systemd-analyze compare-versions "$(uname -r)" lt 6.5 ||
systemd-analyze compare-versions "$(pkcheck --version | awk '{print $3}')" lt 124; then
echo "Skipping unpriv nspawn test"
exit 0
fi
at_exit() {
rm -rf /home/testuser/.local/state/machines/zurps ||:
machinectl terminate zurps ||:
rm -f /usr/share/polkit-1/rules.d/registermachinetest.rules
}
trap at_exit EXIT
systemctl start systemd-mountfsd.socket systemd-nsresourced.socket
run0 -u testuser mkdir -p .local/state/machines
create_dummy_container /home/testuser/.local/state/machines/zurps
cat >/home/testuser/.local/state/machines/zurps/sbin/init <<EOF
#!/bin/sh
echo "I am living in a container"
exec sleep infinity
EOF
chmod +x /home/testuser/.local/state/machines/zurps/sbin/init
systemd-dissect --shift /home/testuser/.local/state/machines/zurps foreign
# Install a PK rule that allows 'testuser' user to register a machine even
# though they are not on an fg console, just for testing
cat >/usr/share/polkit-1/rules.d/registermachinetest.rules <<'EOF'
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.machine1.register-machine" &&
subject.user == "testuser") {
return polkit.Result.YES;
}
});
EOF
loginctl enable-linger testuser
run0 -u testuser systemctl start --user systemd-nspawn@zurps.service
machinectl status zurps
machinectl status zurps | grep "UID:" | grep "$(id -u testuser)"
machinectl status zurps | grep "Unit: user@" | grep "$(id -u testuser)"
machinectl status zurps | grep "Subgroup: machine.slice/systemd-nspawn@zurps.service/payload"
machinectl terminate zurps
(! run0 -u testuser systemctl is-active --user systemd-nspawn@zurps.service)
loginctl disable-linger testuser