Hi! Maxim Cournoyer <[email protected]> skribis:
> Ludovic Courtès <[email protected]> writes: [...] >>> I reviewed how that works, and it'd be easy; I just didn't see the >>> incentive yet (there's no composition needed for the service, and it'd >>> make the definition slightly less readable). If you tell me >>> mark+forkexec-constructor/container is going the way of the Dodo though, >>> that's a good enough incentive :-). > > That turns out to be bit problematic; dbus-daemon must not run in its > own user namespace (CLONE_NEWUSER) as it wants to validate user/group > IDs. That's probably the reason it was working with > 'make-forkexec-constructor/container', as this was dropping the user and > net namespaces, contrary to least-authority, which uses them all. > > The problem then seems to be that since we need CAP_SYS_ADMIN when > dropping the user namespace, as CLONE_NEWUSER is what gives us > superpowers. Per 'man user_namespaces': > > The child process created by clone(2) with the CLONE_NEWUSER flag starts > out with a complete set of capabilities in the new user namespace. > > Which means that if we combine something like (untested): > > (make-forkexec-constructor > (least-authority > (list (file-append coreutils "/bin/true")) > (mappings (delq 'user %namespaces)) > #:user "nobody" > #:group "nobody")) > > the make-forkexec-constructor will switch to the non-privileged user > before the clone call is made, and it will fail with EPERM. > > When using 'make-forkexec-constructor/container', the clone(2) call > happens before switching user, thus as 'root' in Shepherd, which > explains why it works. Damnit, that’s right. For example the result of: (lower-object (least-authority-wrapper (file-append coreutils "/bin/uname") #:namespaces (delq 'user %namespaces))) won’t run as an unprivileged user: --8<---------------cut here---------------start------------->8--- $ $(guix build /gnu/store/hy8rd8p8pid67ac27dwm63svl5bqn0a1-pola-wrapper.drv) substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0% substitute: updating substitutes from 'https://bordeaux.guix.gnu.org'... 100.0% substitute: updating substitutes from 'https://guix.bordeaux.inria.fr'... 100.0% The following derivations will be built: /gnu/store/hy8rd8p8pid67ac27dwm63svl5bqn0a1-pola-wrapper.drv /gnu/store/bd63i07rvvsw7xgsig0cbdsw7fpznd1k-references.drv building /gnu/store/bd63i07rvvsw7xgsig0cbdsw7fpznd1k-references.drv... successfully built /gnu/store/bd63i07rvvsw7xgsig0cbdsw7fpznd1k-references.drv building /gnu/store/hy8rd8p8pid67ac27dwm63svl5bqn0a1-pola-wrapper.drv... successfully built /gnu/store/hy8rd8p8pid67ac27dwm63svl5bqn0a1-pola-wrapper.drv Backtrace: 5 (primitive-load "/gnu/store/ifsh87aifh2k8pqzhkjxncq3vskpwx3l-pola-wrapper") In ice-9/eval.scm: 191:35 4 (_ #f) In gnu/build/linux-container.scm: 300:8 3 (call-with-temporary-directory #<procedure 7f9aa3a674b0 at gnu/build/linux-container.scm:396:3 (root)>) 397:16 2 (_ "/tmp/guix-directory.K9gBNH") 239:7 1 (run-container "/tmp/guix-directory.K9gBNH" (#<<file-system> device: "/gnu/store/jkjs0inmzhj4vsvclbf08nmh0shm7lrf-attr-2.5…> …) …) In guix/build/syscalls.scm: 1099:12 0 (_ 1845624849) guix/build/syscalls.scm:1099:12: In procedure clone: 1845624849: Operation not permitted --8<---------------cut here---------------end--------------->8--- > I'm not sure how it could be fixed; it seems the user changing business > would need to be handled by the least-authority-wrapper code? And the > make-forkexec-constructor would probably need to detect that command is > a pola wrapper and then avoid changing the user/group itself to not > interfere. I think we would add #:user and #:group to ‘least-authority-wrapper’ and have it call setuid/setgid. ‘make-forkexec-constructor’ doesn’t need to be modified, but the user simply won’t pass #:user and #:group to it. Thanks, Ludo’.
