Subject: Re: bug#54770: Non-root LUKS devices unusable after Shepherd upgrade

From: Ludovic Courtès <[email-masked]>
Date: Fri, 08 Apr 2022 15:34:12 +0200

A note on my debugging tricks, for posterity…

Initially, I tried to reproduce the issue (in a VM) with a Guile or Bash
process that would be invoked from shepherd before ‘user-processes’ and
that would try to read from stdin:

--8<---------------cut here---------------start------------->8---
(simple-service 'input
                shepherd-root-service-type
                (list (shepherd-service
                       (provision '(input))
                       (start #~(lambda ()
                                  (pk 'tty-before?
                                      (current-input-port)
                                      (isatty?
                                       (current-input-port)))

                                  (with-output-to-file
                                      "/dev/tty1"
                                    (lambda ()
                                     (system*
                                      #$(file-append
                                         coreutils "/bin/ls") "-l" "/proc/self/fd")
                                     (with-input-from-file
                                         "/dev/tty1"
                                       (lambda ()
                                         (pk 'tty?
                                             (isatty?
                                              (current-input-port)))
                                         (system*
                                          #$(file-append
                                             coreutils "/bin/ls") "-l"
                                          "/proc/self/fd")
                                         (system* "/bin/sh"
                                                  "-c"
                                                  "echo read; read x; echo got $x; read y"))))))))))
(simple-service 'wait-for-input user-processes-service-type
                '(input))
--8<---------------cut here---------------end--------------->8---

For some reason, that did not reproduce the issue; ‘isatty?’ would
return true.

So I though I’d arrange to run ‘cryptsetup open --type luks’.  To do
that, I copied the header of a real LUKS partition:

  sudo dd if=/dev/sda2 of=/tmp/luks.img bs=1024 count=1025

and then came up with an OS config that would try to open than fake LUKS
device:

(use-modules (gnu))
(use-service-modules networking ssh shepherd)
(use-package-modules base linux screen ssh)

(operating-system
  (host-name "komputilo")
  (timezone "Europe/Berlin")
  (locale "en_US.utf8")

  ;; Boot in "legacy" BIOS mode, assuming /dev/sdX is the
  ;; target hard disk, and "my-root" is the label of the target
  ;; root file system.
  (bootloader (bootloader-configuration
                (bootloader grub-bootloader)
                (targets '("/dev/sdX"))))
  (mapped-devices (list (mapped-device
                         (source "/dev/loop0")
                         (target "root")
                         (type luks-device-mapping))))
  (file-systems (cons (file-system
                        (device (file-system-label "my-root"))
                        (mount-point "/")
                        (type "ext4"))
                      %base-file-systems))

  ;; This is where user accounts are specified.  The "root"
  ;; account is implicit, and is initially created with the
  ;; empty password.
  (users (cons (user-account
                (name "alice")
                (comment "Bob's sister")
                (group "users")

                ;; Adding the account to the "wheel" group
                ;; makes it a sudoer.  Adding it to "audio"
                ;; and "video" allows the user to play sound
                ;; and access the webcam.
                (supplementary-groups '("wheel"
                                        "audio" "video")))
               %base-user-accounts))

  ;; Globally-installed packages.
  (packages (cons screen %base-packages))

  ;; Add services to the baseline: a DHCP client and
  ;; an SSH server.
  (services (append (list (service dhcp-client-service-type)
                          (simple-service 'losetup activation-service-type
                                          #~(system*
                                             #$(file-append util-linux
                                                            "/sbin/losetup")
                                             "/dev/loop0"
                                             #$(local-file "/tmp/luks.img")))
                          (service openssh-service-type
                                   (openssh-configuration
                                    (openssh openssh-sans-x)
                                    (port-number 2222))))
                    %base-services)))

That’s enough to see whether ‘cryptsetup open’ manages to read the
passphrase and all.

Eventually I confirmed by testing it on the bare metal, on a victim’s
laptop.

Currently we don’t have an installation test with cleartext root +
encrypted home; we should prolly do that.

Ludo’.