GNU bug report logs - #63904
Can't setuid programs to anybody but root

Previous Next

Package: guix;

Reported by: edk <at> beaver-labs.com

Date: Mon, 5 Jun 2023 10:13:02 UTC

Severity: normal

To reply to this bug, email your comments to 63904 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guix <at> gnu.org:
bug#63904; Package guix. (Mon, 05 Jun 2023 10:13:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to edk <at> beaver-labs.com:
New bug report received and forwarded. Copy sent to bug-guix <at> gnu.org. (Mon, 05 Jun 2023 10:13:02 GMT) Full text and rfc822 format available.

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

From: edk <at> beaver-labs.com
To: bug-guix <bug-guix <at> gnu.org>
Subject: Can't setuid programs to anybody but root
Date: Mon, 05 Jun 2023 12:00:18 +0200
Dear Guix developers,

At the end of the email is the code for a minimal container, which tries
to setuid =true=, the simplest binary of all, to user suc.

When line 26 is commented, and the container is built and run with:
sudo $(guix system container  mwe.scm)

One can login to the container and run:
ls -l /run/setuid-programs/true

which yields:
-r-sr-xr-x 1 root root 39488 Jun  5 09:59 /run/setuid-programs/true
as it should.

Also, one can fire up guile and run (getpw "suc") and get in return:
$1 = #("suc" "x" 1000 998 "" "/home/suc" "/gnu/store/m6c5hgqg569mbcjjbp8l8m7q82ascpdl-bash-5.1.16/bin/bash")

However, when line 26 is uncommented, the container can be built, but
when run fails with the error below.
My hunch is that things are done out of order, with setuid binaries
being set up before user creation, but I have no way of checking that.

Please do not hesitate to ping me if I can be of help.

Cheers,

Edouard.

The error:
system container is running as PID 9825
WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
Run 'sudo guix container exec 9825 /run/current-system/profile/bin/bash --login'
or run 'sudo nsenter -a -t 9825' to get a shell into it.

WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
making '/gnu/store/mnc9lfpn01frmffqa31jy3c381dkgrwl-system' the current system...
WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
setting up setuid programs in '/run/setuid-programs'...
Backtrace:
          12 (primitive-load "/gnu/store/bygckv7p4091xqykjnkay4qnazn…")
In gnu/build/linux-container.scm:
    300:8 11 (call-with-temporary-directory #<procedure 7fb026898d70…>)
   397:16 10 (_ "/tmp/guix-directory.B9dmTN")
     62:6  9 (call-with-clean-exit #<procedure 7fb0268a5380 at gnu/b…>)
In unknown file:
           8 (primitive-load "/gnu/store/mnc9lfpn01frmffqa31jy3c381d…")
In ice-9/eval.scm:
    619:8  7 (_ #f)
In unknown file:
           6 (primitive-load "/gnu/store/dib6wfh2r52dfaydz78n33267qx…")
In srfi/srfi-1.scm:
    634:9  5 (for-each #<procedure primitive-load (_)> ("/gnu/sto…" …))
In unknown file:
           4 (primitive-load "/gnu/store/ypwqsx11k2qmxkscmzan6srq87q…")
In srfi/srfi-1.scm:
    634:9  3 (for-each #<procedure 7fb026380538 at gnu/build/activa…> …)
In ice-9/boot-9.scm:
  1747:15  2 (with-exception-handler #<procedure 7fb02683c6f0 at ic…> …)
In gnu/build/activation.scm:
   317:57  1 (_)
In unknown file:
           0 (getpw "suc")

ERROR: In procedure getpw:
In procedure getpw: entry not found



The code

(use-modules
 (guix gexp)
 (gnu system)
 (gnu bootloader)
 (gnu bootloader grub)
 (gnu system file-systems)
 (gnu services)
 (gnu services base)
 (gnu system setuid)
 (gnu packages base))

(operating-system
  (host-name "minimal-container")
  (timezone "UTC")
  (locale "en_US.utf8")
  (bootloader (bootloader-configuration
               (bootloader grub-bootloader)))
  (file-systems %base-file-systems)
  (users (cons
          (user-account
           (name "suc")
           (group "users"))
          %base-user-accounts))
  (setuid-programs
   (cons (setuid-program (program (file-append coreutils "/bin/true"))
                         (user "suc")
                         )
         %setuid-programs))
  (packages %base-packages)
  (services %base-services))




Information forwarded to bug-guix <at> gnu.org:
bug#63904; Package guix. (Tue, 06 Jun 2023 07:49:01 GMT) Full text and rfc822 format available.

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

From: Edouard Klein <edou <at> rdklein.fr>
To: 63904 <at> debbugs.gnu.org
Cc: dev <at> jpoiret.xyz, me <at> tobias.gr, zimon.toutoune <at> gmail.com, othacehe <at> gnu.org,
 ludo <at> gnu.org, mail <at> cbaines.net, rekado <at> elephly.net
Subject: Re: Can't setuid programs to anybody but root
Date: Tue, 06 Jun 2023 09:21:43 +0200
Dear Guix, CCing the core team,

I tried tracking down the bug.

The fatidic call to getpw was easy enough to find:
The make-setuid-program procedure is given a numeric uid argument. This
numeric uid is found from the user name string by
activate-setuid-program which calls getpwnam
(gnu/build/activation.scm:317).

Now this gave me an idea to sidestep the bug: See below the modified
part of the minimal reproductible example: I just force-assign a uid to
the user I want to setuid to, and give this uid instead of the username
to the setuid record.

This is cumbersome, but it does the job: the call to getpw is averted
and I get a system in which I can setuid to somebody other than root.

However, I'm lost as to how to solve the bug for good. I tried to
understand the call stack, but I can't figure out how in the folding
service machinery the services are ordered. My intuition is that I need
to make it so the folding of non-root setuids happen after the folding
of user and groups (I also have the intuition that root-setuids must
happen before, because folding users and group may require that root
setuid binaries are there, but I have not been able to verify that).

Here is what I was able to find.
getpw is called by activate-setuid-program
activate-setuid-program is called in setuid-program->activation-gexp
setuid-program->activation-gexp is the activation procedure for setuid-program-service-type
setuid-program-service-type is itself an extension of activation-service-type

I'm trying to follow how the service DAG is constructed, and then
walked, from there, but I don't think I have a very clear model of how
it works in my head.

I think the devil may be in:


(define (compute-boot-script _ gexps)
  ;; Reverse GEXPS so that extensions appear in the boot script in the right
  ;; order.  That is, user extensions would come first, and extensions added
  ;; by 'essential-services' (e.g., running shepherd) are guaranteed to come
  ;; last.
  (gexp->file "boot"
              ;; Clean up and activate the system, then spawn shepherd.
              #~(begin #$@(reverse gexps))))

Any help there would be greatly appreciated.

Thanks in advance,

Cheers,

Edouard.



(operating-system
  (host-name "minimal-container")
  (timezone "UTC")
  (locale "en_US.utf8")
  (bootloader (bootloader-configuration
               (bootloader grub-bootloader)))
  (file-systems %base-file-systems)
  (users (cons
          (user-account
           (name "suc")
           (group "users")
           (uid 1042))
          %base-user-accounts))
  (setuid-programs
   (cons (setuid-program (program (file-append coreutils "/bin/true"))
                         ;; (user "suc")
                         (user 1042)
                         )
         %setuid-programs))
  (packages %base-packages)
  (services %base-services))


edk <at> beaver-labs.com writes:

> Dear Guix developers,
>
> At the end of the email is the code for a minimal container, which tries
> to setuid =true=, the simplest binary of all, to user suc.
>
> When line 26 is commented, and the container is built and run with:
> sudo $(guix system container  mwe.scm)
>
> One can login to the container and run:
> ls -l /run/setuid-programs/true
>
> which yields:
> -r-sr-xr-x 1 root root 39488 Jun  5 09:59 /run/setuid-programs/true
> as it should.
>
> Also, one can fire up guile and run (getpw "suc") and get in return:
> $1 = #("suc" "x" 1000 998 "" "/home/suc" "/gnu/store/m6c5hgqg569mbcjjbp8l8m7q82ascpdl-bash-5.1.16/bin/bash")
>
> However, when line 26 is uncommented, the container can be built, but
> when run fails with the error below.
> My hunch is that things are done out of order, with setuid binaries
> being set up before user creation, but I have no way of checking that.
>
> Please do not hesitate to ping me if I can be of help.
>
> Cheers,
>
> Edouard.
>
> The error:
> system container is running as PID 9825
> WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
> Run 'sudo guix container exec 9825 /run/current-system/profile/bin/bash --login'
> or run 'sudo nsenter -a -t 9825' to get a shell into it.
>
> WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
> making '/gnu/store/mnc9lfpn01frmffqa31jy3c381dkgrwl-system' the current system...
> WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
> setting up setuid programs in '/run/setuid-programs'...
> Backtrace:
>           12 (primitive-load "/gnu/store/bygckv7p4091xqykjnkay4qnazn…")
> In gnu/build/linux-container.scm:
>     300:8 11 (call-with-temporary-directory #<procedure 7fb026898d70…>)
>    397:16 10 (_ "/tmp/guix-directory.B9dmTN")
>      62:6  9 (call-with-clean-exit #<procedure 7fb0268a5380 at gnu/b…>)
> In unknown file:
>            8 (primitive-load "/gnu/store/mnc9lfpn01frmffqa31jy3c381d…")
> In ice-9/eval.scm:
>     619:8  7 (_ #f)
> In unknown file:
>            6 (primitive-load "/gnu/store/dib6wfh2r52dfaydz78n33267qx…")
> In srfi/srfi-1.scm:
>     634:9  5 (for-each #<procedure primitive-load (_)> ("/gnu/sto…" …))
> In unknown file:
>            4 (primitive-load "/gnu/store/ypwqsx11k2qmxkscmzan6srq87q…")
> In srfi/srfi-1.scm:
>     634:9  3 (for-each #<procedure 7fb026380538 at gnu/build/activa…> …)
> In ice-9/boot-9.scm:
>   1747:15  2 (with-exception-handler #<procedure 7fb02683c6f0 at ic…> …)
> In gnu/build/activation.scm:
>    317:57  1 (_)
> In unknown file:
>            0 (getpw "suc")
>
> ERROR: In procedure getpw:
> In procedure getpw: entry not found
>
>
>
> The code
>
> (use-modules
>  (guix gexp)
>  (gnu system)
>  (gnu bootloader)
>  (gnu bootloader grub)
>  (gnu system file-systems)
>  (gnu services)
>  (gnu services base)
>  (gnu system setuid)
>  (gnu packages base))
>
> (operating-system
>   (host-name "minimal-container")
>   (timezone "UTC")
>   (locale "en_US.utf8")
>   (bootloader (bootloader-configuration
>                (bootloader grub-bootloader)))
>   (file-systems %base-file-systems)
>   (users (cons
>           (user-account
>            (name "suc")
>            (group "users"))
>           %base-user-accounts))
>   (setuid-programs
>    (cons (setuid-program (program (file-append coreutils "/bin/true"))
>                          (user "suc")
>                          )
>          %setuid-programs))
>   (packages %base-packages)
>   (services %base-services))




Information forwarded to bug-guix <at> gnu.org:
bug#63904; Package guix. (Thu, 08 Jun 2023 07:20:01 GMT) Full text and rfc822 format available.

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

From: Josselin Poiret <dev <at> jpoiret.xyz>
To: Edouard Klein <edou <at> rdklein.fr>, 63904 <at> debbugs.gnu.org
Cc: me <at> tobias.gr, zimon.toutoune <at> gmail.com, othacehe <at> gnu.org, ludo <at> gnu.org,
 mail <at> cbaines.net, rekado <at> elephly.net
Subject: Re: Can't setuid programs to anybody but root
Date: Thu, 08 Jun 2023 09:19:00 +0200
[Message part 1 (text/plain, inline)]
Hi everyone,

You might want to have a look at [1], which should resolve this.  I've
held off on reviewing it for quite a bit but have talked on IRC recently
with bjc about it.  With this approach, while cleaner, we'll need to
identify which services rely on the setuid binaries being present, as
well as ensure they're up before any interaction with the user is
possible.

[1] https://issues.guix.gnu.org/62726

HTH,
-- 
Josselin Poiret
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-guix <at> gnu.org:
bug#63904; Package guix. (Thu, 06 Jul 2023 12:09:02 GMT) Full text and rfc822 format available.

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

From: Edouard Klein <edou <at> rdklein.fr>
To: Josselin Poiret <dev <at> jpoiret.xyz>
Cc: 63904 <at> debbugs.gnu.org
Subject: Re: Can't setuid programs to anybody but root
Date: Thu, 06 Jul 2023 14:04:02 +0200
Thank you Josselin :)

I ended up basically reusing this code in my own system layer, while we
wait on 62726 to be merged.

Also, I needed a new keyword argument to change the name of the setuid
binary.

It works flawlessly, thanks !

Cheers,

Edouard.




Josselin Poiret <dev <at> jpoiret.xyz> writes:

> [[PGP Signed Part:Undecided]]
> Hi everyone,
>
> You might want to have a look at [1], which should resolve this.  I've
> held off on reviewing it for quite a bit but have talked on IRC recently
> with bjc about it.  With this approach, while cleaner, we'll need to
> identify which services rely on the setuid binaries being present, as
> well as ensure they're up before any interaction with the user is
> possible.
>
> [1] https://issues.guix.gnu.org/62726
>
> HTH,




This bug report was last modified 266 days ago.

Previous Next


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