~ruther/guix-local

71f0676a295841e2cc662eec0d3e9b7e69726035 — Tobias Geerinckx-Rice 2 years ago 4e58dfe
privilege: Add POSIX capabilities(7) support.

* gnu/system/privilege.scm (<privileged-program>): Add a field
representing the program's POSIX capabilities.
(privileged-program-capabilities): New public procedure.
* doc/guix.texi (Privileged Programs): Document it.
* gnu/build/activation.scm (activate-privileged-programs): Take a LIBCAP
package argument providing setcap(8) to apply said capabilities.
* gnu/services.scm (privileged-program->activation-gexp): Pass said
package argument where supported.  Include privileged-program-capabilities
in the compatibility hack.
4 files changed, 34 insertions(+), 11 deletions(-)

M doc/guix.texi
M gnu/build/activation.scm
M gnu/services.scm
M gnu/system/privilege.scm
M doc/guix.texi => doc/guix.texi +7 -0
@@ 41655,6 41655,8 @@ invokation.
@cindex privileged programs
@cindex setuid programs
@cindex setgid programs
@cindex capabilities, POSIX
@cindex setcap
Some programs need to run with elevated privileges, even when they are
launched by unprivileged users.  A notorious example is the
@command{passwd} program, which users can run to change their


@@ 41720,6 41722,11 @@ defaults to root.
GID (integer) group name (string) for the group owner of the program,
defaults to root.

@item @code{capabilities} (default: @code{#f})
A string representing the program's POSIX capabilities, as described by
the @code{cap_to_text(3)} man page from the libcap package, or @code{#f}
to make no changes.

@end table
@end deftp


M gnu/build/activation.scm => gnu/build/activation.scm +12 -5
@@ 288,9 288,10 @@ they already exist."
  ;; Place where privileged copies of programs are stored.
  "/run/privileged/bin")

(define (activate-privileged-programs programs)
(define (activate-privileged-programs programs libcap)
  "Turn PROGRAMS, a list of file privileged-programs records, into privileged
copies stored under %PRIVILEGED-PROGRAM-DIRECTORY."
copies stored under %PRIVILEGED-PROGRAM-DIRECTORY, using LIBCAP's setcap(8)
binary if needed."
  (define (ensure-empty-directory directory)
    (if (file-exists? directory)
        (for-each (compose delete-file


@@ 301,7 302,7 @@ copies stored under %PRIVILEGED-PROGRAM-DIRECTORY."
                           string<?))
        (mkdir-p directory))    )

  (define (make-privileged-program program setuid? setgid? uid gid)
  (define (make-privileged-program program setuid? setgid? uid gid capabilities)
    (let ((target (string-append %privileged-program-directory
                                 "/" (basename program)))
          (mode (+ #o0555                   ; base permissions


@@ 309,7 310,10 @@ copies stored under %PRIVILEGED-PROGRAM-DIRECTORY."
                   (if setgid? #o2000 0)))) ; setgid bit
      (copy-file program target)
      (chown target uid gid)
      (chmod target mode)))
      (chmod target mode)
      (when (and capabilities libcap)
        (system* (string-append libcap "/sbin/setcap")
                 "-q" capabilities target))))

  (define (make-deprecated-wrapper program)
    ;; This will eventually become a script that warns on usage, then vanish.


@@ 331,13 335,16 @@ copies stored under %PRIVILEGED-PROGRAM-DIRECTORY."
                         (setgid?      (privileged-program-setgid? program))
                         (user         (privileged-program-user program))
                         (group        (privileged-program-group program))
                         (capabilities (privileged-program-capabilities program))
                         (uid (match user
                                ((? string?) (passwd:uid (getpwnam user)))
                                ((? integer?) user)))
                         (gid (match group
                                ((? string?) (group:gid (getgrnam group)))
                                ((? integer?) group))))
                    (make-privileged-program program-name setuid? setgid? uid gid)
                    (make-privileged-program program-name
                                             setuid? setgid? uid gid
                                             capabilities)
                    (make-deprecated-wrapper program-name)))
                (lambda args
                  ;; If we fail to create a privileged program, better keep going

M gnu/services.scm => gnu/services.scm +7 -2
@@ 46,6 46,7 @@
  #:use-module (gnu packages base)
  #:use-module (gnu packages bash)
  #:use-module (gnu packages hurd)
  #:use-module (gnu packages linux)
  #:use-module (gnu system privilege)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-9)


@@ 899,12 900,14 @@ FILES must be a list of name/file-like object pairs."
                               (setuid?      (privileged-program-setuid? program))
                               (setgid?      (privileged-program-setgid? program))
                               (user         (privileged-program-user program))
                               (group        (privileged-program-group program)) )
                               (group        (privileged-program-group program))
                               (capabilities (privileged-program-capabilities program)))
                           #~(privileged-program
                              (setuid? #$setuid?)
                              (setgid? #$setgid?)
                              (user    #$user)
                              (group   #$group)
                              (capabilities #$capabilities)
                              (program #$program-name))))
                       programs)))
    (with-imported-modules (source-module-closure


@@ 912,7 915,9 @@ FILES must be a list of name/file-like object pairs."
      #~(begin
          (use-modules (gnu system privilege))

          (activate-privileged-programs (list #$@programs))))))
          (activate-privileged-programs (list #$@programs)
                                        #$(and (supported-package? libcap)
                                               libcap))))))

(define privileged-program-service-type
  (service-type (name 'privileged-program)

M gnu/system/privilege.scm => gnu/system/privilege.scm +8 -4
@@ 25,13 25,14 @@
            privileged-program-setuid?
            privileged-program-setgid?
            privileged-program-user
            privileged-program-group))
            privileged-program-group
            privileged-program-capabilities))

;;; Commentary:
;;;
;;; Data structures representing privileged programs: binaries with additional
;;; permissions such as setuid/setgid.  This is meant to be used both on the
;;; host side and at run time--e.g., in activation snippets.
;;; permissions such as setuid/setgid, or POSIX capabilities.  This is meant to
;;; be used both on the host side and at run time--e.g., in activation snippets.
;;;
;;; Code:



@@ 51,4 52,7 @@
                 (default 0))
  ;; The group name or ID we want to set this to (defaults to root's).
  (group         privileged-program-group ;integer or string
                 (default 0)))
                 (default 0))
  ;; POSIX capabilities in cap_from_text(3) form (defaults to #f: none).
  (capabilities  privileged-program-capabilities ;string or #f
                 (default #f)))