From e1b8840da16fb531f6607892ebf08f2d5472b962 Mon Sep 17 00:00:00 2001 From: Maxim Cournoyer Date: Sun, 7 Jun 2020 23:01:49 -0400 Subject: [PATCH 1/3] services: Allow configuring the ownership of setuid programs. Fixes . * gnu/build/activation.scm (activate-setuid-programs): Update doc. Allow a program entry to be a list that may include a user and a group. [make-setuid-program] New USER and GROUP keyword parameters. Move the error handling inside the MAKE-SETUID-PROGRAM helper procedure. * gnu/services.scm (setuid-program-service-type): Update doc. * doc/guix.texi (Setuid Programs): Update doc. --- doc/guix.texi | 17 +++++++++++--- gnu/build/activation.scm | 48 +++++++++++++++++++++++++--------------- gnu/services.scm | 17 ++++++++++++-- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 056bf011f6..83d7344bd8 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -26429,14 +26429,25 @@ should be setuid root. The @code{setuid-programs} field of an @code{operating-system} declaration contains a list of G-expressions denoting the names of -programs to be setuid-root (@pxref{Using the Configuration System}). -For instance, the @command{passwd} program, which is part of the Shadow -package, can be designated by this G-expression (@pxref{G-Expressions}): +programs to be setuid (@pxref{Using the Configuration System}). The +user and group ownership of the setuid program default to @code{root}, +but can be specified by declaring them along the file name of the +program. For instance, the @command{passwd} program, which is part of +the Shadow package, can be designated as a setuid-root porgram by this +G-expression (@pxref{G-Expressions}): @example #~(string-append #$shadow "/bin/passwd") @end example +As a second example, the @command{smtpctl} program, which is part of the +OpenSMTPD package, requires to have its group set to @samp{smtpq}. +This can be specified using: + +@example +(list (file-append opensmtpd "/bin/smtpctl") "smtpq" "smtpq") +@end example + A default set of setuid programs is defined by the @code{%setuid-programs} variable of the @code{(gnu system)} module. diff --git a/gnu/build/activation.scm b/gnu/build/activation.scm index 30f5e87d5a..6be3664d44 100644 --- a/gnu/build/activation.scm +++ b/gnu/build/activation.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès ;;; Copyright © 2015 Mark H Weaver +;;; Copyright © 2020 Maxim Cournoyer ;;; ;;; This file is part of GNU Guix. ;;; @@ -227,14 +228,28 @@ they already exist." "/run/setuid-programs") (define (activate-setuid-programs programs) - "Turn PROGRAMS, a list of file names, into setuid programs stored under -%SETUID-DIRECTORY." - (define (make-setuid-program prog) + "Turn PROGRAMS, a list of file names and/or of nested lists composed of a +file name, a user and a group, into setuid programs stored under +%SETUID-DIRECTORY. The user and group default to \"root\" and affect the +ownership of the associated file name." + (define* (make-setuid-program prog #:key (user "root") (group user)) (let ((target (string-append %setuid-directory "/" (basename prog)))) - (copy-file prog target) - (chown target 0 0) - (chmod target #o6555))) + (catch 'system-error + (lambda () + (let ((uid (passwd:uid (getpwnam user))) + (gid (group:gid (getgrnam group)))) + (copy-file prog target) + (chown target uid gid) + (chmod target #o6555))) + (lambda args + ;; If we fail to create a setuid program, better keep going + ;; so that we don't leave %SETUID-DIRECTORY empty or + ;; half-populated. This can happen if PROGRAMS contains + ;; incorrect file names: . + (format (current-error-port) + "warning: failed to make '~a' setuid (~a:~a): ~a~%" + prog user group (strerror (system-error-errno args))))))) (format #t "setting up setuid programs in '~a'...~%" %setuid-directory) @@ -247,18 +262,15 @@ they already exist." string. - (format (current-error-port) - "warning: failed to make '~a' setuid-root: ~a~%" - program (strerror (system-error-errno args)))))) + (for-each (match-lambda + ((program user group) + (make-setuid-program program #:user user #:group group)) + ((program user) + (make-setuid-program program #:user user)) + ((program) + (make-setuid-program program)) + (program + (make-setuid-program program))) programs)) (define (activate-special-files special-files) diff --git a/gnu/services.scm b/gnu/services.scm index 2e4648bf78..19a1c38ceb 100644 --- a/gnu/services.scm +++ b/gnu/services.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès ;;; Copyright © 2016 Chris Marusich +;;; Copyright © 2020 Maxim Cournoyer ;;; ;;; This file is part of GNU Guix. ;;; @@ -681,12 +682,24 @@ FILES must be a list of name/file-like object pairs." (list (service-extension activation-service-type (lambda (programs) #~(activate-setuid-programs - (list #$@programs)))))) + (quote (#$@programs))))))) (compose concatenate) (extend append) (description "Populate @file{/run/setuid-programs} with the specified -executables, making them setuid-root."))) +executables, making them setuid. The PROGRAMS entries extending the +setuid-program-service-type is a list of file-like objects. Alternatively to +file-like objects, nested lists containing a file-like object, a user and a +group can be used to control the ownership of the associated file. + +Example: + +(list (file-append shadow \"/bin/passwd\") + (list (file-append opensmtpd \"/bin/smtpctl\") \"root\" \"smtpq\")) + +The @command{passwd} program has both its user and group set to the +default \"root\" while the @command{smtpctl} program has its user set to +\"root\" and its group set to \"smtpq\"."))) (define (packages->profile-entry packages) "Return a system entry for the profile containing PACKAGES." -- 2.26.2