activation: Lock /etc/.pwd.lock before accessing databases.

Suggested by Florian Pelz <pelzflorian@pelzflorian.de>
in <http://bugs.gnu.org/35996>.

* gnu/build/accounts.scm (%password-lock-file): New variable.
* gnu/build/activation.scm (activate-users+groups): Wrap calls to
'user+group-databases', 'write-group', etc. into 'with-file-lock'.
This commit is contained in:
Ludovic Courtès 2019-06-03 17:14:17 +02:00
parent 5f0cf1df71
commit d497b6ab39
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
2 changed files with 25 additions and 14 deletions

View file

@ -51,6 +51,7 @@ (define-module (gnu build accounts)
group-entry-gid
group-entry-members
%password-lock-file
write-group
write-passwd
write-shadow
@ -224,6 +225,11 @@ (define-database-entry <group-entry> ;<grp.h>
(serialization list->comma-separated comma-separated->list)
(default '())))
(define %password-lock-file
;; The password database lock file used by libc's 'lckpwdf'. Users should
;; grab this lock with 'with-file-lock' when they access the databases.
"/etc/.pwd.lock")
(define (database-writer file mode entry->string)
(lambda* (entries #:optional (file-or-port file))
"Write ENTRIES to FILE-OR-PORT. When FILE-OR-PORT is a file name, write

View file

@ -22,6 +22,7 @@ (define-module (gnu build activation)
#:use-module (gnu build accounts)
#:use-module (gnu build linux-boot)
#:use-module (guix build utils)
#:use-module ((guix build syscalls) #:select (with-file-lock))
#:use-module (ice-9 ftw)
#:use-module (ice-9 match)
#:use-module (ice-9 vlist)
@ -129,22 +130,26 @@ (define system-accounts
;; Allow home directories to be created under /var/lib.
(mkdir-p "/var/lib")
(let-values (((groups passwd shadow)
(user+group-databases users groups)))
(write-group groups)
(write-passwd passwd)
(write-shadow shadow)
;; Take same lock as libc's 'lckpwdf' (but without a timeout) while we read
;; and write the databases. This ensures there's no race condition with
;; other tools that might be accessing it at the same time.
(with-file-lock %password-lock-file
(let-values (((groups passwd shadow)
(user+group-databases users groups)))
(write-group groups)
(write-passwd passwd)
(write-shadow shadow)))
;; Home directories of non-system accounts are created by
;; 'activate-user-home'.
(for-each make-home-directory system-accounts)
;; Home directories of non-system accounts are created by
;; 'activate-user-home'.
(for-each make-home-directory system-accounts)
;; Turn shared home directories, such as /var/empty, into root-owned,
;; read-only places.
(for-each (lambda (directory)
(chown directory 0 0)
(chmod directory #o555))
(duplicates (map user-account-home-directory system-accounts)))))
;; Turn shared home directories, such as /var/empty, into root-owned,
;; read-only places.
(for-each (lambda (directory)
(chown directory 0 0)
(chmod directory #o555))
(duplicates (map user-account-home-directory system-accounts))))
(define (activate-user-home users)
"Create and populate the home directory of USERS, a list of tuples, unless