Subject: Re: [bug#75810] [PATCH v6 00/16] Rootless guix-daemon

From: Reepca Russelstein <[email-masked]>
Date: Fri, 21 Mar 2025 14:21:06 -0500

Ludovic Courtès <[email-masked]> writes:

>> While ensuring that what actually gets execve'd is in the store suffices
>> to eliminate the vulnerability, it may be "conceptually purer" to
>> require that the links pointing to it are all in the store as well.  For
>> example, while a builder that is a symlink pointing to /proc/self/exe
>> wouldn't be able to modify the daemon binary, it's still a piece of
>> basically "undefined behavior" as far as the build environment is
>> concerned, which could be closed up.  But that can come later just as
>> well.
>
> Yes.  But in practice, “normal” symlinks (i.e., not /proc/self/exe) will
> lead ‘canonPath’ to throw if one component is outside the store, since
> ‘canonPath’ operates within the chroot.

Unless the component actually exists and is outside of the store.  If we
just rely on canonPath throwing an exception to be safe, then if there
ever arose a situation where a non-symlink executable existed outside of
the store, it would still be possible to convince the daemon to execute
it.

For example, suppose Linus Torvalds wakes up one day and decides "you
know what, it really is wrong that we're lying about /proc/self/exe
being a symlink" and changes it so that lstat reports a regular file (or
a special file, really anything other than a symlink) that happens to be
a valid argument to readlink.  Or suppose in the interest of
backwards-compatibility he instead adds /proc/self/exe-hardlink.
canonPath won't throw if a symlink points to these hypothetical files,
and the daemon would execute them.  A similar situation could also
happen if an executable showed up in /dev somehow.

I mention this because I see that patch 07/16 of v7 has left out the
isInStore check, and I think it should remain.

> Since we don’t have ‘Group=’ in the .service file, the daemon runs as
> the group of ‘guix-daemon’, also called ‘guix-daemon’ (created by
> ‘guix-install.sh’).
>
> I confirmed in a VM that the process is indeed running as
> guix-daemon:guix-daemon.

Great.

While researching container escape vulnerabilities, I recently came
across CAP_DAC_READ_SEARCH and open_by_handle_at, which is a system call
so insanely powerful it is outright banned in all but the root user
namespace.  Or at least, it was.  10 months ago, in commit
620c266f394932e5decc4b34683a75dfc59dc2f4 of
https://github.com/torvalds/linux, the requirements were relaxed so
that, in certain cases, processes in non-root user namespaces could use
open_by_handle_at.

The consequences of this for same-user containers are not clear to me
yet, as I haven't studied the kernel source enough to know what exactly
that commit message means by "privileges over the filesystem" or
"privileges over a subtree".  I also haven't been able to test this
behavior yet, because my kernel is actually too old (I do my rebases and
upgrades rather less regularly than is recommended).  I'll try to look
into this more once I update my system (and man-pages!), but figured I
should mention it, because aside from that, and the aforementioned
isInStore check, I can't think of any remaining concerns.

- reepca