GNU bug report logs - #75810
[PATCH 0/6] Rootless guix-daemon

Previous Next

Package: guix-patches;

Reported by: Ludovic Courtès <ludo <at> gnu.org>

Date: Fri, 24 Jan 2025 17:24:02 UTC

Severity: normal

Tags: patch

Done: Ludovic Courtès <ludo <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


Message #394 received at 75810 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: Reepca Russelstein <reepca <at> russelstein.xyz>
Cc: 75810 <at> debbugs.gnu.org
Subject: Re: [bug#75810] [PATCH v6 00/16] Rootless guix-daemon
Date: Thu, 20 Mar 2025 21:57:44 +0100
Hi,

Reepca Russelstein <reepca <at> russelstein.xyz> skribis:

>> The visible changes in the build environment are unfortunate; I’m hoping
>> they won’t have any practical impact, not any more than the other
>> parameters that may change currently (build UID, binfmt_misc, file
>> system, etc.)  We could test this hypothesis by rebuilding at least the
>> entire set of packages up to ‘hello’.  (I tried doing it just now in a
>> Debian VM but failed since the main partition cannot easily be extended;
>> it’ll be easier to do with Guix System.)
>>
>
> For what it's worth, the visible changes could be avoided with
> subordinate ids, as I wrote in
> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=75810#86.

Yes.  The newuidmap/newgidmap mechanism looks like a hack to me so I’m
reluctant, but if we have to, we could take that route.

> We could try it as-is and see how it goes, and if there are problems
> with reproducibility add on using subordinate ids.  I would expect it to
> be a much smaller change than the root->rootless transition.

Yes.

>>   1. If /proc/self/exe points to (say) /usr/bin/guix-daemon, outside the
>>      store, execve fails with ENOENT because that file is not mounted in
>>      the chroot.
>
> No, like I wrote, /proc/self/exe, despite being reported as a symlink by
> stat, does not follow the usual symlink semantics.  This is much like
> how the files in /proc/self/fd work, e.g.:

Oh right; apologies, and thanks for taking the time to (re)explain and
to come up with a reproducer.

> From 'man 2 execve':
>
>        ENOENT The file pathname or a script *or ELF interpreter* does not exist.
>
> (emphasis mine).  The dynamic linker registered in guix-daemon's binary
> is not likely to exist in the container in this test, but an attacker
> could easily make it so as long as it's in the store.

Yes.  And it wouldn’t be so hard when one is running guix-daemon from
the store (from the ‘guix’ package or from ‘guix pull’).

>> +	    drv.builder = canonPath(drv.builder, true);
>> +	    printMsg(lvlError, format("builder is `%1%'") % drv.builder);
>> +	    if (!isInStore(drv.builder))
>> +		throw Error(format("derivation builder '%1%' is outside the store") % drv.builder);
>>  	}
>>  
>>          /* Fill in the arguments. */
>
> Note that we should still supply the original name or basename as
> argv[0].

Right, noted!

> 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.

> One more consideration I noticed when looking at v6's patch 14/16 (the
> guix-daemon.service one): we don't do anything to set the gid.  I know
> on guix system we usually use both dedicated privilege separation users
> and groups for services.  Should we use a dedicated group for
> guix-daemon as well?  Note that currently the chroot directories have
> 0750 permissions, so it's very important that their group not be
> accessible to others.

Quoth
<https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#User=>:

  User=, Group=
    Set the UNIX user or group that the processes are executed as,
    respectively. […] If no group is set, the default group of the user
    is used.

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.

I’ve just sent v7 with the ‘canonPath’ change discussed above.

Thank you!

Ludo’.




This bug report was last modified 56 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.