On Sun, Jan 14, 2024 at 06:36:29PM +0100, Francesco Poli wrote: > Of course, I have! ;-) > > For privacy reasons: I don't want other users to be able to enter my > home directory and to read any file within it that I might have > forgotten with world-readable permissions!
I agree that this is good practice. It's just that working with namespaces tends to make this annoying. We're still in search for a more satisfying solution. For now, I'm happy to have identified the cause of your failure. > the final touches to sid_amd64.img will be put with the file in its > intended destination directory, which is /home/${USER}/mysubdir, since > the command-line argument was "sid_amd64.img", a relative path to a > file directly within the current working directory (~/mysubdir). That command that fails is mkfs.ext4. This command is run inside the user namespace that mmdebstrap creates for constructing the chroot. The uids 0 to 65535 inside the user namespace correspond to your first subuid range that is large enough. The mkfs.ext4 operation is performed by the root user inside the user namespace. In the initial namespace that root user is your first subuid. In particular, it is not your user but a different user and this user has no permission to access your output image. > And these final touches require all parent directories (up to the root > directory) to be world-executable. Technically speaking, this is a sufficient but not strictly necessary precondition. What we actually needs is your first subuid to be able to open the output image for writing. This is difficult to achieve. The method implemented in mmdebstrap-autopkgtest-build-qemu is to temporarily change the ownership of the output image to the first subuid. While chown is normally a privileged operation, you can chown inside your namespace if both the original owner and the new owner are mapped inside your user namespace. This is not the case for the namespace that mmdebstrap creates, but before calling mmdebstrap, we construct another namespace suitable for performing this chown. What we don't do is adjust the permission of leading directory components. The ability for opening the output image depends on both the final component having a +w bit in an appropriate place (and since we care fully chose the owner this is u+w) and leading directory components being +x (and since these are neither owned by the first subuid nor the first subgid, it amounts to o+x). > In other words, the user would need: > > $ stat -c "%a %n" ~/mysubdir ~ /home / > 771 /home/${USER}/mysubdir > 701 /home/${USER} > 755 /home > 755 / > > rather than: > > $ stat -c "%a %n" ~/mysubdir ~ /home / > 770 /home/${USER}/mysubdir > 700 /home/${USER} > 755 /home > 755 / > > Is that correct? > Or am I completely off-track? This is one way to establish the actual precondition. Let me suggest some alternatives. One is storing the output image outside $HOME. If you put it into /tmp and the move it from /tmp into your home, that should work as well. Another is using ACLs. You might add an ACL that specifically grants your subuid range execute permission on your home but not every user. The available options to improve this are not super nice. A simple workaround is creating the output image as a temporary file inside the namespace and then copying it out. This will perform a 1GB copy operation that we'd like to avoid (and rather construct the filesystem in-place) for performance reasons, but maybe usability beats performance? I'm also not sure how mmdebstrap downloads sparse files. It might make them un-sparse and that'd be quite bad for this use case as you'd write 25GB of zeros. Another option could be using fuse. In principle, we could have a fuse driver running in the initial namespace that just serves the output image. Then inside the namespace we could mount this fuse filesystem (which becomes a regular file, not a directory) and write to it. Having the fuse driver run in one namespace and the fuse mount in a different namespace resolves the permission problem. This is all non-trivial to implement though. The plumbing isn't up to the task. Maybe there are other options that I don't see at this time? > It looks like it worked, but, unfortunately, it (again) fails to be > usable with autopkgtest: > > $ autopkgtest --output-dir ./${SRCPKG}_autopkgtest.out --summary > ./${SRCPKG}_autopkgtest.summary --apt-upgrade -B ./${SRCPKG}_amd64.changes -- > qemu --overlay-dir /dev/shm ~/Downloads/sid_amd64.img > autopkgtest [18:24:23]: starting date and time: 2024-01-14 18:24:23+0100 > autopkgtest [18:24:23]: version 5.32 > autopkgtest [18:24:23]: host ${HOST}; command line: /usr/bin/autopkgtest > --output-dir './${SRCPKG}_autopkgtest.out' --summary > './${SRCPKG}_autopkgtest.summary' --apt-upgrade -B > './${SRCPKG}_amd64.changes' -- qemu --overlay-dir /dev/shm > ${HOME}/Downloads/sid_amd64.img > qemu-system-x86_64: terminating on signal 15 from pid 115770 > (/usr/bin/python3) > <VirtSubproc>: failure: timed out waiting for 'login prompt on serial > console' > autopkgtest [18:25:24]: ERROR: testbed failure: unexpected eof from the > testbed > > > What did I fail to understand? The difficulty resides in making a bootable image with no root privileges. mmdebstrap-autopkgtest-build-qemu is not fully compatible with autopkgtest-build-qemu. It specifically required you to pass --boot=efi, right? On amd64, autopkgtest-virt-qemu defaults to bios boot. In order to use this image, you likewise have to pass --boot=efi to the virtualization backend. Helmut