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)) e...@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))