summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2022-04-08 11:53:02 +0200
committerLudovic Courtès <ludo@gnu.org>2022-04-08 18:14:35 +0200
commit931f13840bad7bd3cb98b7806f09ca2b3cf7cd10 (patch)
tree9724772c119ceb742e34efee26ebdefdd77cfa69
parentdf473496edefbb88eaf2fbff7dda2665eb21b4d1 (diff)
downloadguix-patches-931f13840bad7bd3cb98b7806f09ca2b3cf7cd10.tar
guix-patches-931f13840bad7bd3cb98b7806f09ca2b3cf7cd10.tar.gz
mapped-devices: Ensure 'cryptsetup open' gets a tty.
Fixes <https://issues.guix.gnu.org/54770>. Regression introduced in 400c9ed3d779308e56038305d40cd93acb496180. Previously, for an encrypted /home (say), "cryptsetup open" would be invoked by shepherd, with /dev/null as its standard input. It would thus run in non-interactive mode and, instead of asking for a passphrase, fail with: Nothing to read on input. This change ensures it runs in interactive mode. * gnu/build/file-systems.scm (system*/console, system*/tty): New procedures. * gnu/system/mapped-devices.scm (open-luks-device): Use 'system*/tty' instead of 'system*'.
-rw-r--r--gnu/build/file-systems.scm30
-rw-r--r--gnu/system/mapped-devices.scm53
2 files changed, 58 insertions, 25 deletions
diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm
index d95340df83..d5f38c6774 100644
--- a/gnu/build/file-systems.scm
+++ b/gnu/build/file-systems.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014-2018, 2020-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016, 2017 David Craven <david@craven.ch>
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;; Copyright © 2019 Guillaume Le Vaillant <glv@posteo.net>
@@ -54,6 +54,7 @@
bind-mount
+ system*/tty
mount-flags->bit-mask
check-file-system
mount-file-system
@@ -67,6 +68,33 @@
;;;
;;; Code:
+(define (system*/console program . args)
+ "Run PROGRAM with ARGS in a tty on top of /dev/console. The return value is
+as for 'system*'."
+ (match (primitive-fork)
+ (0
+ (dynamic-wind
+ (const #t)
+ (lambda ()
+ (login-tty (open-fdes "/dev/console" O_RDWR))
+ (apply execlp program program args))
+ (lambda ()
+ (primitive-_exit 127))))
+ (pid
+ (cdr (waitpid pid)))))
+
+(define (system*/tty program . args)
+ "Run PROGRAM with ARGS, creating a tty if its standard input isn't one.
+The return value is as for 'system*'.
+
+This is necessary for commands such as 'cryptsetup open' or 'fsck' that may
+need to interact with the user but might be invoked from shepherd, where
+standard input is /dev/null."
+ (apply (if (isatty? (current-input-port))
+ system*
+ system*/console)
+ program args))
+
(define (bind-mount source target)
"Bind-mount SOURCE at TARGET."
(mount source target "" MS_BIND))
diff --git a/gnu/system/mapped-devices.scm b/gnu/system/mapped-devices.scm
index 96a381d5fe..e6b8970c12 100644
--- a/gnu/system/mapped-devices.scm
+++ b/gnu/system/mapped-devices.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014-2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2016 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2017, 2018 Mark H Weaver <mhw@netris.org>
;;;
@@ -202,7 +202,8 @@ option of @command{guix system}.\n")
;; XXX: 'use-modules' should be at the top level.
(use-modules (rnrs bytevectors) ;bytevector?
((gnu build file-systems)
- #:select (find-partition-by-luks-uuid))
+ #:select (find-partition-by-luks-uuid
+ system*/tty))
((guix build utils) #:select (mkdir-p)))
;; Create '/run/cryptsetup/' if it does not exist, as device locking
@@ -211,28 +212,32 @@ option of @command{guix system}.\n")
;; Use 'cryptsetup-static', not 'cryptsetup', to avoid pulling the
;; whole world inside the initrd (for when we're in an initrd).
- (zero? (system* #$(file-append cryptsetup-static "/sbin/cryptsetup")
- "open" "--type" "luks"
-
- ;; Note: We cannot use the "UUID=source" syntax here
- ;; because 'cryptsetup' implements it by searching the
- ;; udev-populated /dev/disk/by-id directory but udev may
- ;; be unavailable at the time we run this.
- (if (bytevector? source)
- (or (let loop ((tries-left 10))
- (and (positive? tries-left)
- (or (find-partition-by-luks-uuid source)
- ;; If the underlying partition is
- ;; not found, try again after
- ;; waiting a second, up to ten
- ;; times. FIXME: This should be
- ;; dealt with in a more robust way.
- (begin (sleep 1)
- (loop (- tries-left 1))))))
- (error "LUKS partition not found" source))
- source)
-
- #$target)))))))
+ ;; 'cryptsetup open' requires standard input to be a tty to allow
+ ;; for interaction but shepherd sets standard input to /dev/null;
+ ;; thus, explicitly request a tty.
+ (zero? (system*/tty
+ #$(file-append cryptsetup-static "/sbin/cryptsetup")
+ "open" "--type" "luks"
+
+ ;; Note: We cannot use the "UUID=source" syntax here
+ ;; because 'cryptsetup' implements it by searching the
+ ;; udev-populated /dev/disk/by-id directory but udev may
+ ;; be unavailable at the time we run this.
+ (if (bytevector? source)
+ (or (let loop ((tries-left 10))
+ (and (positive? tries-left)
+ (or (find-partition-by-luks-uuid source)
+ ;; If the underlying partition is
+ ;; not found, try again after
+ ;; waiting a second, up to ten
+ ;; times. FIXME: This should be
+ ;; dealt with in a more robust way.
+ (begin (sleep 1)
+ (loop (- tries-left 1))))))
+ (error "LUKS partition not found" source))
+ source)
+
+ #$target)))))))
(define (close-luks-device source targets)
"Return a gexp that closes TARGET, a LUKS device."