Subject: [bug#54997] [PATCH 00/12] Add "least authority" program wrapper

From: Maxime Devos <[email-masked]>
Date: Fri, 22 Apr 2022 16:39:43 +0200

Ludovic Courtès schreef op wo 20-04-2022 om 00:02 [+0200]:
> > would become simpler as it wouldn't need to fork, exec, waitpid and
> > dynamic-wind.  Alternatively, if associating a user and group with
> > a
> > pola wrapper is problematic (*), what do you think of defining a
> > 'system*/with-capabilities' or 'invoke/with-capabilities' in a
> > central
> > location?
> 
> I’m not sure what these procedures would do.
> 
> I think we should build the house one brick at a time; this is the
> first brick but I’m sure there’ll be others as we gain more
> experience and clearer use cases.

This system*/with-capabilities brick would do the primitive-
fork+setuid+setgid+execl thing:

(define (system*/with-capabilities command #:key user group extra-
groups environment)
  ;; Exec the given command with the right authority.
  (let ((pid (primitive-fork)))
        (if (zero? pid)
           (dynamic-wind
              (const #t)
              (lambda ()
                (let ((pw (getpwnam "ipfs")))  ; TODO use 'user' and
'group', and don't change user/group when already this user/group
                  (setgroups '#())
                  (setgid (passwd:gid pw))
                  (setuid (passwd:uid pw))
                  (environ environment)
                  (apply execl command)))
              (lambda ()
                (primitive-exit 127)))
            (waitpid pid)))))

This would make this functionality available outside the ipfs service
as well.  Over time, it could be extended to support more kinds of
ambient authority, e.g. namespaces, POSIX ‘capabilities’, capability
masks to disallow gaining capabilities by runningsetuid binaries, the
file system hierarchy (with bind mounts), removing all users and groups
(on the Hurd), ...

Many of these are supported by 'least-authority-wrapper' but these POLA
wrappers require creating an additional process which seems a bit
unoptimal to me (memory- and latency-wise).

Also, having to do fork, waitpid and primitive-fork seems rather low-
level to me, so I prefer moving this code into somewhere like (gnu
build SOMEWHERE) or to keep the old make-forkexec-constructor/container
code.

Greetinsgs,
Maxime.