systemd / systemd

The systemd System and Service Manager
https://systemd.io
GNU General Public License v2.0
13.3k stars 3.8k forks source link

MachineCtl Automatically Chowns Overlay UpperDir Merged Mount #30653

Open vindicatorr opened 10 months ago

vindicatorr commented 10 months ago

systemd version the issue has been seen with

255

Used distribution

Arch Linux

Linux kernel version used

6.5.0-dirty

CPU architectures issue was seen on

x86_64

Component

machinectl

Expected behaviour you didn't see

File and directory ownership remains as-it-was.

Unexpected behaviour you saw

File and directory ownership changed as if --private-users was being used.

Steps to reproduce the problem

Init:

$ sudo mkdir -pv ./deleteThis/test{Root{,/var/lib/pacman,/proc,/dev},Upper,Work,Mount}
$ sudo mount -v --bind /proc ./deleteThis/testRoot/proc
$ sudo touch ./deleteThis/testRoot/dev/null
$ sudo mount -v --bind /dev/null ./deleteThis/testRoot/dev/null
$ sudo cp -rv /var/lib/pacman/sync/ ./deleteThis/testRoot/var/lib/pacman/
$ sudo pacman --root "${PWD}"/deleteThis/testRoot -S systemd
$ sudo umount ./deleteThis/testRoot/proc ./deleteThis/testRoot/dev/null
$ sudo cp -rav ./deleteThis/testRoot{,.bak}

Scenarios: Fail - Overlay Mount - Machinectl:

$ sudo mount -v --types overlay overlay \
--options index=off,metacopy=off,lowerdir=./deleteThis/testRoot,upperdir=./deleteThis/testUpper,workdir=./deleteThis/testWork ./deleteThis/testMount
//Scenario also fails without "index=off,metacopy=off"
$ sudo ln -s "${PWD}"/deleteThis/testMount /var/lib/machines/
$ sudo ls -l ./deleteThis/testMount/var/lib
//Note the correct "root" ownerships
$ sudo machinectl start testMount
$ sudo machinectl stop testMount
$ sudo ls -l ./deleteThis/testMount/var/lib
//Note the INcorrect "<#>" ownerships, because it was chowned.
$ sudo umount ./deleteThis/testMount

Success - Overlay Mount - Systemd-Nspawn:

$ sudo rm -rf ./deleteThis/testUpper
$ sudo mkdir -v ./deleteThis/testUpper
$ sudo mount -v --types overlay overlay \
--options index=off,metacopy=off,lowerdir=./deleteThis/testRoot,upperdir=./deleteThis/testUpper,workdir=./deleteThis/testWork ./deleteThis/testMount
$ sudo ls -l ./deleteThis/testMount/var/lib
//Note the correct "root" ownerships
$ sudo systemd-nspawn --directory=./deleteThis/testMount --boot
$ sudo ls -l ./deleteThis/testMount/var/lib
//Note the correct "root" ownerships remains
$ sudo umount ./deleteThis/testMount

Success - Mount - Machinectl:

$ sudo mount -v --bind ./deleteThis/testRoot ./deleteThis/testMount
$ sudo ls -l ./deleteThis/testMount/var/lib
//Note the correct "root" ownerships
$ sudo machinectl start testMount
$ sudo ls -l ./deleteThis/testMount/var/lib
//Note the correct "root" ownerships remains
$ sudo umount ./deleteThis/testMount

Cleanup:

$ sudo rm -rf ./deleteThis

As awesome as the idea is, I've already been seeing how messy/problematic overlays can be (mainly with nspawn) which is why I opted to manually make them, in addition to idmapping simply not working with them for some reason (noted in other open issues here).

Additional program output to the terminal or log subsystem illustrating the issue

Bus n/a: changing state UNSET → OPENING
sd-bus: starting bus by connecting to /run/dbus/system_bus_socket...
Bus n/a: changing state OPENING → AUTHENTICATING
Successfully forked off '(sd-askpwagent)' as PID 1812532.
Bus n/a: changing state AUTHENTICATING → HELLO
Sent message type=method_call sender=n/a destination=org.freedesktop.DBus path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=Hello cookie=1 reply_cookie=0 signature=n/a error-name=n/a error-message=n/a
Sent message type=method_call sender=n/a destination=org.freedesktop.DBus path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=AddMatch cookie=2 reply_cookie=0 signature=s error-name=n/a error-message=n/a
Got message type=method_return sender=org.freedesktop.DBus destination=:1.6053 path=n/a interface=n/a member=n/a  cookie=1 reply_cookie=1 signature=s error-name=n/a error-message=n/a
Bus n/a: changing state HELLO → RUNNING
Sent message type=method_call sender=n/a destination=org.freedesktop.machine1 path=/org/freedesktop/machine1 interface=org.freedesktop.machine1.Manager member=GetImage cookie=3 reply_cookie=0 signature=s error-name=n/a error-message=n/a
Got message type=method_return sender=:1.1 destination=:1.6053 path=n/a interface=n/a member=n/a  cookie=12854 reply_cookie=3 signature=o error-name=n/a error-message=n/a
Sent message type=method_call sender=n/a destination=org.freedesktop.systemd1 path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=StartUnit cookie=4 reply_cookie=0 signature=ss error-name=n/a error-message=n/a
Got message type=method_return sender=:1.6 destination=:1.6053 path=n/a interface=n/a member=n/a  cookie=136490 reply_cookie=4 signature=o error-name=n/a error-message=n/a
Got message type=signal sender=org.freedesktop.DBus destination=:1.6053 path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=NameAcquired  cookie=2 reply_cookie=0 signature=s error-name=n/a error-message=n/a
Got message type=method_return sender=org.freedesktop.DBus destination=:1.6053 path=n/a interface=n/a member=n/a  cookie=3 reply_cookie=2 signature=n/a error-name=n/a error-message=n/a
Match type='signal',sender='org.freedesktop.systemd1',path='/org/freedesktop/systemd1',interface='org.freedesktop.systemd1.Manager',member='JobRemoved' successfully installed.
Got message type=signal sender=:1.6 destination=n/a path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=JobRemoved  cookie=136521 reply_cookie=0 signature=uoss error-name=n/a error-message=n/a
Got message type=signal sender=:1.6 destination=n/a path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=JobRemoved  cookie=136541 reply_cookie=0 signature=uoss error-name=n/a error-message=n/a
Got message type=signal sender=:1.6 destination=n/a path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=JobRemoved  cookie=136546 reply_cookie=0 signature=uoss error-name=n/a error-message=n/a
Got message type=signal sender=:1.6 destination=n/a path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=JobRemoved  cookie=136551 reply_cookie=0 signature=uoss error-name=n/a error-message=n/a
Got message type=signal sender=:1.6 destination=n/a path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=JobRemoved  cookie=136562 reply_cookie=0 signature=uoss error-name=n/a error-message=n/a
Got message type=signal sender=:1.6 destination=n/a path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=JobRemoved  cookie=136569 reply_cookie=0 signature=uoss error-name=n/a error-message=n/a
Got result done/Success for job systemd-nspawn@testMount.service
Sent message type=method_call sender=n/a destination=org.freedesktop.DBus path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=RemoveMatch cookie=5 reply_cookie=0 signature=s error-name=n/a error-message=n/a
Bus n/a: changing state RUNNING → CLOSED

EDIT0: I just noticed machinectl runs systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth -U --settings=override --machine=testMount, and I'm seeing the -U is apparently default (which would explain the chowning since it can't map an overlay).

poettering commented 10 months ago

it only does this if the root inode of your rootfs is not owned by root of the container. If the root fs is properly owned nspawn won't recursively chown. It also doesn't do it if if can use idmapped mounts (which is only available for overlayfs in very recent kernels).

hence: either fix your root fs, or live with the recursive chowning, or use a very recent kernel?

vindicatorr commented 10 months ago

Sorry, but I'm not quite following here as to what I need to be doing... Kernel: 6.5.0-dirty //should be available ("5.12"*https://lwn.net/Articles/896255/)? util-linux: 2.39.3

Root of the container should still be UID==0, and that would pair with my host root UID==0 as well. You're specifically mentioning "inode" which is making me think I'm missing something in my checks here...

$ ls -laid /
3 drwxr-xr-x 18 root root 4096 Dec 28 22:57 /

$ ls -laid ./deleteThis/testRoot
149607445 drwxr-xr-x 1 root root 122 Jan  2 10:32 ./deleteThis/testRoot

$ ls -laid ./deleteThis/testUpper
149607451 drwxr-xr-x 1 root root 0 Jan  2 10:31 ./deleteThis/testUpper

If it's a lack of understanding of the topic on my part, I'm open to being pointed to a man/link where I can learn more about it.