system: Add support for setuid binaries.

* gnu/system.scm (<operating-system>)[pam-services, setuid-programs]:
  New fields.
  (etc-directory)[bashrc]: Prepend /run/setuid-programs to $PATH.
  (operating-system-etc-directory): Honor
  'operating-system-pam-services'.
  (%setuid-programs): New variable.
  (operating-system-boot-script): Add (guix build utils) to the set of
  imported modules.  Call 'activate-setuid-programs' in boot script.
* gnu/system/linux.scm (base-pam-services): New procedure.
* guix/build/activation.scm (%setuid-directory): New variable.
  (activate-setuid-programs): New procedure.
* build-aux/hydra/demo-os.scm: Add 'pam-services' field.
This commit is contained in:
Ludovic Courtès 2014-04-30 22:17:56 +02:00
parent d8a7a5bfd5
commit 09e028f45f
4 changed files with 76 additions and 8 deletions

View File

@ -34,6 +34,7 @@
(gnu packages package-management) (gnu packages package-management)
(gnu system shadow) ; 'user-account' (gnu system shadow) ; 'user-account'
(gnu system linux) ; 'base-pam-services'
(gnu services base) (gnu services base)
(gnu services networking) (gnu services networking)
(gnu services xorg)) (gnu services xorg))
@ -56,6 +57,9 @@
#:gateway "10.0.2.2") #:gateway "10.0.2.2")
%base-services)) %base-services))
(pam-services
;; Explicitly allow for empty passwords.
(base-pam-services #:allow-empty-passwords? #t))
(packages (list bash coreutils findutils grep sed (packages (list bash coreutils findutils grep sed
procps psmisc less procps psmisc less
guile-2.0 dmd guix util-linux inetutils guile-2.0 dmd guix util-linux inetutils

View File

@ -106,7 +106,12 @@
(locale operating-system-locale) ; string (locale operating-system-locale) ; string
(services operating-system-services ; list of monadic services (services operating-system-services ; list of monadic services
(default %base-services))) (default %base-services))
(pam-services operating-system-pam-services ; list of PAM services
(default (base-pam-services)))
(setuid-programs operating-system-setuid-programs
(default %setuid-programs))) ; list of string-valued gexps
@ -191,6 +196,7 @@ export TZ=\"" timezone "\"
export TZDIR=\"" tzdata "/share/zoneinfo\" export TZDIR=\"" tzdata "/share/zoneinfo\"
export PATH=$HOME/.guix-profile/bin:" profile "/bin:" profile "/sbin export PATH=$HOME/.guix-profile/bin:" profile "/bin:" profile "/sbin
export PATH=/run/setuid-programs:$PATH
export CPATH=$HOME/.guix-profile/include:" profile "/include export CPATH=$HOME/.guix-profile/include:" profile "/include
export LIBRARY_PATH=$HOME/.guix-profile/lib:" profile "/lib export LIBRARY_PATH=$HOME/.guix-profile/lib:" profile "/lib
alias ls='ls -p --color' alias ls='ls -p --color'
@ -238,8 +244,8 @@ alias ll='ls -l'
(pam-services -> (pam-services ->
;; Services known to PAM. ;; Services known to PAM.
(delete-duplicates (delete-duplicates
(cons %pam-other-services (append (operating-system-pam-services os)
(append-map service-pam-services services)))) (append-map service-pam-services services))))
(accounts (operating-system-accounts os)) (accounts (operating-system-accounts os))
(profile-drv (operating-system-profile os)) (profile-drv (operating-system-profile os))
(groups -> (append (operating-system-groups os) (groups -> (append (operating-system-groups os)
@ -250,15 +256,29 @@ alias ll='ls -l'
#:timezone (operating-system-timezone os) #:timezone (operating-system-timezone os)
#:profile profile-drv))) #:profile profile-drv)))
(define %setuid-programs
;; Default set of setuid-root programs.
(let ((shadow (@ (gnu packages admin) shadow)))
(list #~(string-append #$shadow "/bin/passwd")
#~(string-append #$shadow "/bin/su")
#~(string-append #$inetutils "/bin/ping"))))
(define (operating-system-boot-script os) (define (operating-system-boot-script os)
"Return the boot script for OS---i.e., the code started by the initrd once "Return the boot script for OS---i.e., the code started by the initrd once
we're running in the final root." we're running in the final root."
(define %modules
'((guix build activation)
(guix build utils)))
(mlet* %store-monad (mlet* %store-monad
((services (sequence %store-monad (operating-system-services os))) ((services (sequence %store-monad (operating-system-services os)))
(etc (operating-system-etc-directory os)) (etc (operating-system-etc-directory os))
(modules (imported-modules '((guix build activation)))) (modules (imported-modules %modules))
(compiled (compiled-modules '((guix build activation)))) (compiled (compiled-modules %modules))
(dmd-conf (dmd-configuration-file services))) (dmd-conf (dmd-configuration-file services)))
(define setuid-progs
(operating-system-setuid-programs os))
(gexp->file "boot" (gexp->file "boot"
#~(begin #~(begin
(eval-when (expand load eval) (eval-when (expand load eval)
@ -272,6 +292,9 @@ we're running in the final root."
;; Populate /etc. ;; Populate /etc.
(activate-etc #$etc) (activate-etc #$etc)
;; Activate setuid programs.
(activate-setuid-programs (list #$@setuid-progs))
;; Start dmd. ;; Start dmd.
(execl (string-append #$dmd "/bin/dmd") (execl (string-append #$dmd "/bin/dmd")
"dmd" "--config" #$dmd-conf))))) "dmd" "--config" #$dmd-conf)))))

View File

@ -29,8 +29,8 @@
#:export (pam-service #:export (pam-service
pam-entry pam-entry
pam-services->directory pam-services->directory
%pam-other-services unix-pam-service
unix-pam-service)) base-pam-services))
;;; Commentary: ;;; Commentary:
;;; ;;;
@ -152,4 +152,11 @@ should be the name of a file used as the message-of-the-day."
(list #~(string-append "motd=" #$motd))))) (list #~(string-append "motd=" #$motd)))))
(list unix)))))))) (list unix))))))))
(define* (base-pam-services #:key allow-empty-passwords?)
"Return the list of basic PAM services everyone would want."
(list %pam-other-services
(unix-pam-service "su" #:allow-empty-passwords? allow-empty-passwords?)
(unix-pam-service "passwd"
#:allow-empty-passwords? allow-empty-passwords?)))
;;; linux.scm ends here ;;; linux.scm ends here

View File

@ -17,8 +17,10 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix build activation) (define-module (guix build activation)
#:use-module (guix build utils)
#:use-module (ice-9 ftw) #:use-module (ice-9 ftw)
#:export (activate-etc)) #:export (activate-etc
activate-setuid-programs))
;;; Commentary: ;;; Commentary:
;;; ;;;
@ -60,4 +62,36 @@
(rm-f "/var/guix/gcroots/etc-directory") (rm-f "/var/guix/gcroots/etc-directory")
(symlink etc "/var/guix/gcroots/etc-directory"))) (symlink etc "/var/guix/gcroots/etc-directory")))
(define %setuid-directory
;; Place where setuid programs are stored.
"/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)
(let ((target (string-append %setuid-directory
"/" (basename prog))))
(catch 'system-error
(lambda ()
(link prog target))
(lambda args
;; Perhaps PROG and TARGET live in a different file system, so copy
;; PROG.
(copy-file prog target)))
(chown target 0 0)
(chmod target #o6555)))
(format #t "setting up setuid programs in '~a'...~%"
%setuid-directory)
(if (file-exists? %setuid-directory)
(for-each delete-file
(scandir %setuid-directory
(lambda (file)
(not (member file '("." ".."))))
string<?))
(mkdir-p %setuid-directory))
(for-each make-setuid-program programs))
;;; activation.scm ends here ;;; activation.scm ends here