Subject: Re: guix-daemon run as non-root sets up /etc/group incorrectly in build container

From: Ludovic Courtès <[email-masked]>
Date: Fri, 25 Apr 2025 20:39:29 +0200

Hi,

I committed the /etc/group fix in
0d3bc50b0cffeae05beb12d0c270c6599186c0d7 together with a test.

keinflue <[email-masked]> writes:

> I think this happens if the user running guix-daemon has supplementary
> groups. These are not mapped via /proc/gid_map in the build container
> and therefore are reported as the overflow gid (65534) by getgroups.
>
> The test cases assume that they can change ownership to this
> additional group but that is not permitted on the overflow gid.
>
> I think supplementary groups should be dropped in the user namespace
> for the build container to make the behavior
> reproducible. Unfortunately this may be impossible if the parent
> namespace has set /proc/[...]/setgroups to "deny".

I came up with this test:

--8<---------------cut here---------------start------------->8---
(use-modules (guix)
             (gcrypt hash)
             (gnu packages bootstrap))

(computed-file "kvm-access"
               #~(begin
                   (pk '#$(gettimeofday))
                   (let ((st (stat "/dev/kvm")))
                     (pk '/dev/kvm st)
                     (pk '/dev/kvm:owner (stat:uid st) (stat:gid st))
                     (pk 'getgroups (getgroups))
                     ;; XXX: When running the daemon as root, /dev/kvm is
                     ;; owned by UID 0, which has no entry in /etc/passwd.
                     ;; (pk 'kvm-user (getpwuid (stat:uid st)))
                     ;; xxx: /etc/group never contained an entry to the "kvm"
                     ;; group so the thing below always failed.
                     ;; (pk 'kvm-group (getgrgid (stat:gid st)))
                     )
                   (when (open-fdes "/dev/kvm" O_RDWR)
                     (mkdir #$output)))
               #:guile %bootstrap-guile)
--8<---------------cut here---------------end--------------->8---

Privileged:

--8<---------------cut here---------------start------------->8---
$ guix build -f ~/src/guix-debugging/dev-kvm-access.scm
substitute: looking for substitutes on 'http://192.168.1.48:8123'...   0.0%guix substitute: warning: 192.168.1.48: connection failed: Connection timed out
substitute: 
substitute: looking for substitutes on 'https://ci.guix.gnu.org'... 100.0%
substitute: looking for substitutes on 'https://bordeaux.guix.gnu.org'... 100.0%
substitute: looking for substitutes on 'https://guix.bordeaux.inria.fr'... 100.0%
The following derivation will be built:
  /gnu/store/vc5p6bfrzr7khgp9jha8h6kplixcl5h6-kvm-access.drv
substitute: looking for substitutes on 'http://192.168.1.48:8123'...   0.0%
building /gnu/store/vc5p6bfrzr7khgp9jha8h6kplixcl5h6-kvm-access.drv...

;;; ((1745606160 . 233876))

;;; (/dev/kvm #(6 483 8624 1 0 984 2792 0 1745359386 1745359386 1745359386 4096 0 char-special 432 382791307 382791307 1745359386))

;;; (/dev/kvm:owner 0 984)

;;; (getgroups #(984 30000))
successfully built /gnu/store/vc5p6bfrzr7khgp9jha8h6kplixcl5h6-kvm-access.drv
/gnu/store/36fin1iw2fh9066jg0y2fjd78j9wyjwp-kvm-access
--8<---------------cut here---------------end--------------->8---

Unprivileged:

--8<---------------cut here---------------start------------->8---
$ ./test-env guix build -f ~/src/guix-debugging/dev-kvm-access.scm
accepted connection from pid 2591, user ludo
accepted connection from pid 2601, user ludo
substitute: guix substitute: warning: ACL for archive imports seems to be uninitialized, substitutes may be unavailable
substitute: guix substitute: warning: authentication and authorization of substitutes disabled!
The following derivation will be built:
  /home/ludo/src/guix/test-tmp/store/5p4qn8d3bgnj60a2kwpliiwk81bvrcjp-kvm-access.drv
substitute: guix substitute: warning: authentication and authorization of substitutes disabled!
building /home/ludo/src/guix/test-tmp/store/5p4qn8d3bgnj60a2kwpliiwk81bvrcjp-kvm-access.drv...

;;; ((1745606200 . 636919))

;;; (/dev/kvm #(6 483 8624 1 65534 65534 2792 0 1745359386 1745359386 1745359386 4096 0 char-special 432 382791307 382791307 1745359386))

;;; (/dev/kvm:owner 65534 65534)

;;; (getgroups #(65534 65534 65534 65534 65534 65534 65534 30000 65534))
successfully built /home/ludo/src/guix/test-tmp/store/5p4qn8d3bgnj60a2kwpliiwk81bvrcjp-kvm-access.drv
/home/ludo/src/guix/test-tmp/store/ffh8zaw279dgdsh6q54mlldh4nikxiqp-kvm-access
--8<---------------cut here---------------end--------------->8---

In both cases, /dev/kvm is accessible.

In both cases, only the primary group has an entry in /etc/group;
supplementary groups are lacking.

So:

  1. I don’t think we need to map the “kvm” UID/GID into the user
     namespace;

  2. I’m confused as to what makes the Coreutils test suite fail.

It would still be good to drop any supplementary group other than “kvm”
though.

WDYT?

Thanks,
Ludo’.