GNU bug report logs -
#77862
guix-daemon run as non-root sets up /etc/group incorrectly in build container
Previous Next
Full log
Message #61 received at 77862 <at> debbugs.gnu.org (full text, mbox):
Hey Reepca,
Reepca Russelstein <reepca <at> russelstein.xyz> writes:
> Ludovic Courtès <ludo <at> gnu.org> writes:
[...]
>> The attached patch tries to do that, by calling out to ‘newuidmap’, and
>> under the assumption that /etc/subgid allows mapping the ‘kvm’ group.
>>
>> It does the job (a build process can chown to ‘kvm’), but I couldn’t get
>> the GID mapping preserved across the ‘unshare’ call (the call that is
>> made to “lock” mounts), hence the “#if 0” there.
>>
>> The problem is that when we call ‘unshare’, the ‘newgidmap’ setuid
>> binary is not longer accessible because we’re already in a chroot, so it
>> seems that we cannot preserve the GID map.
>
> ... and even if we had the setuid binary accessible (for example via a
> saved file descriptor that could be used with execveat, or a
> bind-mount), it wouldn't be of any use at this point because (man
> user_namespaces):
>
> "if either the user or the group ID of the file has no mapping inside
> the namespace, the set-user-ID (set-group- ID) bit is silently ignored:
> the new program is executed, but the process's effective user (group) ID
> is left unchanged."
>
> Naturally, uid 0 isn't going to be mapped! In fact, more generally,
> newuidmap and newgidmap can't ever be used from within an uninitialized
> user namespace, since by definition uid 0 isn't yet mapped in it.
>
> So it falls to the parent process to do the initialization - that is, it
> now has to do the initialization twice. Of course, it's going to need
> some way of knowing when the second user namespace has been created, and
> the child is going to need some way of knowing when it's been
> initialized, so we'll need to either use two pipes or switch to using a
> socketpair.
That makes sense, thanks for explaining!
However, I think part of the rules still don’t fit in my head. Here’s
what I have now (parent is 6929):
--8<---------------cut here---------------start------------->8---
6929 openat(AT_FDCWD, "/proc/6938/uid_map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 17
6929 write(17, "30001 1000 1", 12) = 12
6929 close(17) = 0
6929 openat(AT_FDCWD, "/proc/6938/setgroups", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 17
6929 write(17, "deny", 4) = 4
6929 close(17) = 0
6929 openat(AT_FDCWD, "/proc/6938/gid_map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 17
6929 write(17, "30000 998 1", 11) = 11
6929 close(17) = 0
[…]
6938 unshare(CLONE_NEWNS|CLONE_NEWUSER) = 0
6938 write(20, "reinit\n", 7) = 7
6929 <... read resumed>"reinit\n", 20) = 7
6938 read(17, <unfinished ...>
6929 write(4, "gmlo\0\0\0\0+\0\0\0\0\0\0\0| reinitializing UID/GID mapping of 6938\n\0\0\0\0\0", 64) = 64
6929 getgid() = 998
6929 getuid() = 1000
6929 openat(AT_FDCWD, "/proc/6938/uid_map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 17
6929 write(17, "30001 1000 1", 12) = -1 EPERM (Operation not permitted)
--8<---------------cut here---------------end--------------->8---
Why oh why would we get EPERM the second time?
These restrictions appear to be respected:
• The data written to uid_map (gid_map) must consist of a sin‐
gle line that maps the writing process's effective user ID
(group ID) in the parent user namespace to a user ID (group
ID) in the user namespace.
• The writing process must have the same effective user ID as
the process that created the user namespace.
Or is the user namespace of the parent (6929) not the same as “the
parent user namespace”?
Thanks for your patience. :-)
Ludo’.
PS: The more I use it, the less I can stand this user namespace soup
presented as an “API”.
This bug report was last modified 9 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.