diff options
author | Tobias Geerinckx-Rice <me@tobias.gr> | 2023-07-23 02:00:00 +0200 |
---|---|---|
committer | Tobias Geerinckx-Rice <me@tobias.gr> | 2024-08-11 02:00:00 +0200 |
commit | 71f0676a295841e2cc662eec0d3e9b7e69726035 (patch) | |
tree | a39d569981af5fbe9b19634a935c536709698915 | |
parent | 4e58dfee6c7456d1e662f66041b8a157efe8710a (diff) | |
download | guix-71f0676a295841e2cc662eec0d3e9b7e69726035.tar guix-71f0676a295841e2cc662eec0d3e9b7e69726035.tar.gz |
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.
-rw-r--r-- | doc/guix.texi | 7 | ||||
-rw-r--r-- | gnu/build/activation.scm | 17 | ||||
-rw-r--r-- | gnu/services.scm | 9 | ||||
-rw-r--r-- | gnu/system/privilege.scm | 12 |
4 files changed, 34 insertions, 11 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index f882eb70e4..0e1e253b02 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -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 diff --git a/gnu/build/activation.scm b/gnu/build/activation.scm index 77eb150477..a57ca78a86 100644 --- a/gnu/build/activation.scm +++ b/gnu/build/activation.scm @@ -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 diff --git a/gnu/services.scm b/gnu/services.scm index 553ec93a6c..610a2df395 100644 --- a/gnu/services.scm +++ b/gnu/services.scm @@ -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) diff --git a/gnu/system/privilege.scm b/gnu/system/privilege.scm index 455a659a12..d89d5d5d1c 100644 --- a/gnu/system/privilege.scm +++ b/gnu/system/privilege.scm @@ -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))) |