Non-root LUKS devices unusable after Shepherd upgrade

  • Done
  • quality assurance status badge
Details
2 participants
  • Ludovic Courtès
  • Christoph Weiss
Owner
unassigned
Submitted by
Ludovic Courtès
Severity
important
L
L
Ludovic Courtès wrote on 7 Apr 2022 18:33
(address . bug-guix@gnu.org)
87r168etvd.fsf@inria.fr
Hi!

Following the Shepherd upgrade in commit
400c9ed3d779308e56038305d40cd93acb496180, attempts to open non-root LUKS
devices from a Shepherd service fail with this cryptsetup message:

Nothing to read on input.

This is because standard input is now /dev/null so it cannot read the
passphrase.

This is because “shepherd.conf” now does:

(start-in-the-background …)

(redirect-port (open-input-file "/dev/null")
(current-input-port))

… meaning that ‘redirect-port’ is now called before services are
started.

‘fsck’ invocations for non-root file systems (started from Shepherd
services) would have the same problem.

I’ll try and come up with a solution…

Ludo’.
L
L
Ludovic Courtès wrote on 7 Apr 2022 18:40
control message for bug #54770
(address . control@debbugs.gnu.org)
87lewgetiq.fsf@gnu.org
severity 54770 important
quit
L
L
Ludovic Courtès wrote on 8 Apr 2022 11:32
Re: bug#54770: Non-root LUKS devices unusable after Shepherd upgrade
(address . 54770@debbugs.gnu.org)
87mtgvdiou.fsf@gnu.org
Hi,

Ludovic Courtès <ludo@gnu.org> skribis:

Toggle quote (9 lines)
> Following the Shepherd upgrade in commit
> 400c9ed3d779308e56038305d40cd93acb496180, attempts to open non-root LUKS
> devices from a Shepherd service fail with this cryptsetup message:
>
> Nothing to read on input.
>
> This is because standard input is now /dev/null so it cannot read the
> passphrase.

In Cryptsetup, the ‘tools_get_key’ function reads this:

Toggle snippet (24 lines)
if (tools_is_stdin(key_file)) {
if (isatty(STDIN_FILENO)) {
if (keyfile_offset) {
log_err(_("Cannot use offset with terminal input."));
} else {
if (!prompt && !crypt_get_device_name(cd))
snprintf(tmp, sizeof(tmp), _("Enter passphrase: "));
else if (!prompt) {
backing_file = crypt_loop_backing_file(crypt_get_device_name(cd));
snprintf(tmp, sizeof(tmp), _("Enter passphrase for %s: "), backing_file ?: crypt_get_device_name(cd));
free(backing_file);
}
r = crypt_get_key_tty(prompt ?: tmp, key, key_size, timeout, verify, cd);
}
} else {
log_dbg("STDIN descriptor passphrase entry requested.");
/* No keyfile means STDIN with EOL handling (\n will end input)). */
r = crypt_keyfile_device_read(cd, NULL, key, key_size,
keyfile_offset, keyfile_size_max,
key_file ? 0 : CRYPT_KEYFILE_STOP_EOL);
}
}

isatty(3) would return 0 when stdin is /dev/null; simply binding stdin
to /dev/console:

(with-input-from-file "/dev/console"
(lambda ()
(system* "cryptsetup" …)))

wouldn’t help, for reasons that are less clear to me¹.

The attached patch solves the ‘cryptsetup open’ problem for the case
when ‘cryptsetup’ is invoked from shepherd—e.g., for an encrypted /home.
I’m now running the “encrypted-root-os” test.

I’m not sure how to test fsck interactivity though; ideas welcome. If
you’re reading this and would like to test it on the bare metal (worst
case is it fails to boot and you have to reboot into the older
generation), that’s also much appreciated.

Feedback welcome!

Thanks,
Ludo’.

¹ This returns true:
sudo strace -f -o ,,s guile -c '(with-input-from-file "/dev/console" (lambda () (system* "guile" "-c" "(pk (isatty? (current-input-port)))")))'
Attachment: file
L
L
Ludovic Courtès wrote on 8 Apr 2022 15:34
(address . 54770@debbugs.gnu.org)
878rsfd7hn.fsf@gnu.org
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:

Toggle snippet (33 lines)
(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))

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’.
L
L
Ludovic Courtès wrote on 8 Apr 2022 18:18
(address . 54770-done@debbugs.gnu.org)
87zgkvblc0.fsf@gnu.org
Ludovic Courtès <ludo@gnu.org> skribis:

Toggle quote (9 lines)
> Following the Shepherd upgrade in commit
> 400c9ed3d779308e56038305d40cd93acb496180, attempts to open non-root LUKS
> devices from a Shepherd service fail with this cryptsetup message:
>
> Nothing to read on input.
>
> This is because standard input is now /dev/null so it cannot read the
> passphrase.

Fixed with these commits:

f239b9d788 tests: Add "encrypted-home-os" installation test.
dcb0e54a4f file-systems: Invoke fsck tools with 'system*/tty'.
931f13840b mapped-devices: Ensure 'cryptsetup open' gets a tty.

Ludo’.
Closed
C
C
Christoph Weiss wrote on 9 Apr 2022 16:51
Non-root LUKS devices unusable after Shepherd upgrade
(address . 54770@debbugs.gnu.org)
7bc7e9a1-6bd4-2350-4389-d08ec072b3e3@wsoptics.de
I ran into the same issue (no prompt but instead about 32 times the
message "Nothing to read on input.")

I bisected this issue myself (starting before the fix was pushed) and
arrived at 400c9ed3d779308e56038305d40cd93acb496180 as the culprit.

However, even with the current master
(aa5716703fd4603dd89ce9b55f555b7aa85f4c9b), the issue has not been fixed
for me.

Please let me know if I should provide any specific info.

Thank you.
L
L
Ludovic Courtès wrote on 11 Apr 2022 14:39
(name . Christoph Weiss)(address . weiss@wsoptics.de)(address . 54770@debbugs.gnu.org)
874k2zkd5h.fsf@gnu.org
Hi Christoph,

Christoph Weiss <weiss@wsoptics.de> skribis:

Toggle quote (10 lines)
> I ran into the same issue (no prompt but instead about 32 times the
> message "Nothing to read on input.")
>
> I bisected this issue myself (starting before the fix was pushed) and
> arrived at 400c9ed3d779308e56038305d40cd93acb496180 as the culprit.
>
> However, even with the current master
> (aa5716703fd4603dd89ce9b55f555b7aa85f4c9b), the issue has not been
> fixed for me.

It’s definitely fixed for me and the new ‘separate-home-os’ system test
agrees¹.

Did you reconfigure after pulling? What does ‘guix system describe’
report?

Thanks,
Ludo’.

C
C
Christoph Weiss wrote on 11 Apr 2022 19:07
(no subject)
(address . 54770@debbugs.gnu.org)
e8f0e131-5d3d-c6eb-aead-481e694826ab@wsoptics.de
Hi Ludo,

Thanks for your reply. Just to double check, I ran another `sudo guix
pull` and `sudo guix system reconfigure /etc/config.scm`. I still
cannot boot that installation.

This is `guix system describe`'s output for my working revision:

Generation 40 Apr 08 2022 19:52:13
file name: /var/guix/profiles/system-40-link
canonical file name: /gnu/store/sp41bjidi9qrl0k1gqpxivrdign7f7d6-system
label: GNU with Linux-Libre 5.16.14
bootloader: grub
root device: UUID: b63f8b65-48f2-41a7-9652-9a0cb1759048
kernel:
/gnu/store/1shy73077i3im91i4lv9bamifm4w29q1-linux-libre-5.16.14/bzImage
channels:
guix:
commit: f077fa0fd0519f0e04f458192a87854094aa36eb
configuration file:
/gnu/store/18hd645wcz8l5bvhp4lsy49cadq0d655-configuration.scm

I'm not quite sure how to print the describe for the failing revision...

Christoph
L
L
Ludovic Courtès wrote on 12 Apr 2022 10:41
Re: bug#54770: Non-root LUKS devices unusable after Shepherd upgrade
(name . Christoph Weiss)(address . weiss@wsoptics.de)(address . 54770@debbugs.gnu.org)
87sfqiem6v.fsf_-_@gnu.org
Hi,

Christoph Weiss <weiss@wsoptics.de> skribis:

Toggle quote (21 lines)
> Thanks for your reply. Just to double check, I ran another `sudo guix
> pull` and `sudo guix system reconfigure /etc/config.scm`. I still
> cannot boot that installation.
>
> This is `guix system describe`'s output for my working revision:
>
> Generation 40 Apr 08 2022 19:52:13
> file name: /var/guix/profiles/system-40-link
> canonical file name: /gnu/store/sp41bjidi9qrl0k1gqpxivrdign7f7d6-system
> label: GNU with Linux-Libre 5.16.14
> bootloader: grub
> root device: UUID: b63f8b65-48f2-41a7-9652-9a0cb1759048
> kernel:
> /gnu/store/1shy73077i3im91i4lv9bamifm4w29q1-linux-libre-5.16.14/bzImage
> channels:
> guix:
> repository URL: https://git.savannah.gnu.org/git/guix.git
> commit: f077fa0fd0519f0e04f458192a87854094aa36eb
> configuration file:
> /gnu/store/18hd645wcz8l5bvhp4lsy49cadq0d655-configuration.scm

This commit is older than the fix:


Probably this comes from a confusion: ‘sudo guix pull’ updates
~root/.config/guix/bin, but ‘sudo guix system reconfigure’ runs your
user’s ~/.config/guix/bin.

If you use sudo, what you need to do is:

guix pull # without sudo!
sudo guix system reconfigure …

Let me know if that helps!

Ludo’.
C
C
Christoph Weiss wrote on 12 Apr 2022 19:00
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 54770@debbugs.gnu.org)
0f3528a4-41dc-5cb6-3b4c-1434d9cf8126@wsoptics.de
Hi Ludo,

Oh, I had no idea that's how it worked... sorry about that. Indeed this
has fixed the issue. Thank you for your time!

Christoph
?