Package: cryptsetup-initramfs
Version: 2:2.3.7-1+deb11u1
Severity: minor
Tags: patch

Dear Maintainer,

when using the `decrypt_derived` keyscript, the `cryptroot` initramfs hook expects the 
`key file` in `/etc/crypttab` to be the `target name` of another crypttab entry. Beside 
the runtime-use as argument to the keyscript, the `key file` is in this case also used 
during initramfs creation to make sure the "parent" is unlocked beforehand. And 
this all works fine. One thing I noticed thought is that systemd throws a few messages 
with such a setup. These appear after the initrd, so with the real root already mounted. 
(I slightly reordered the messages to increase readability)

```
ERROR systemd[1]: 
/run/systemd/generator/systemd-cryptsetup@luks\x2dtwo.service:14: 
RequiresMountsFor= path is not absolute, ignoring: luks-one
[...]
INFO systemd[1]: Starting Cryptography Setup for luks-one...
WARN systemd-cryptsetup[944]: Encountered unknown /etc/crypttab option 
'initramfs', ignoring.
INFO systemd-cryptsetup[944]: Volume luks-one already active.
INFO systemd[1]: Finished Cryptography Setup for luks-one.
INFO systemd[1]: Starting Cryptography Setup for luks-two...
WARN systemd-cryptsetup[910]: Password file path 'luks-one' is not absolute. 
Ignoring.
WARN systemd-cryptsetup[910]: Encountered unknown /etc/crypttab option 
'initramfs', ignoring.
WARN systemd-cryptsetup[910]: Encountered unknown /etc/crypttab option 
'keyscript=/lib/cryptsetup/scripts/decrypt_derived', ignoring.
INFO systemd-cryptsetup[910]: Volume luks-two already active.
INFO systemd[1]: Finished Cryptography Setup for luks-two.
```

I am not worried about the three `Encountered unknown /etc/crypttab option` 
warnings, because they are valid; these options are specific to Debian's 
cryptroot hook. But the other two regarding the non-absolute key file bothered 
me a bit, especially because one is an error. Out of pure curiosity, I changed 
the key file in my crypttab from the target name `luks-one` to the absolute 
block device path `/dev/mapper/luks-one` to see what happens. To my surprise 
does the keyscript not *require* a target name as argument, it also works fine 
with a absolute device path. You get the same result when calling 
`./decrypt_derived luks-one` and `./decrypt_derived /dev/mapper/luks-one` (also 
works with `dev/disk/by-id/...` and others). And the error/warning from systemd 
are gone, plus it now actually adds `dev-mapper-luks\x2done.device` as a proper 
dependency to `systemd-cryptsetup@luks\x2dtwo.service`. The only thing that 
breaks when using a absolute device path is the recursive unlocking, which the 
hook will warn about during initramfs creation:

```
update-initramfs: Generating /boot/initrd.img-5.10.0-13-amd64
cryptsetup: WARNING: target '/dev/mapper/luks-one' not found in /etc/crypttab
```

This can be functionally worked around by not relying on the recursion and 
explicitly setting the initramfs option for all needed entries. But being 
annoyed by that warning, I took a dive into the cryptroot hook sourcecode and 
created the attached patch, which detects a absolute key file and runs it 
through `dmsetup` to resolve it to a target name. With that, both the 
`cryptroot` hook and `systemd-cryptsetup` work.

I saw a few comments in the scripts to not trust `/dev/mapper/` so I am not 
sure if this breaks anything with regards to name-mangling, but I am sure you 
subject experts will be able to easily assess that.


I also acknowledge that one could partially or completely disable the 
systemd-cryptsetup-generator using kernel command line parameters, but that 
would prevent using the generated device/service units directly or as 
dependencies for other units. Unfortunately there is no 
systemd-cryptsetup-generator specific crypttab option to only disable unit 
generation for specific entries. I haven't tried to mask the generated services 
for the hook-handled devices, that would probably also work; the services are 
effectively no-ops in that case anyway.


-- Package-specific info:
-- /proc/cmdline
root=/dev/vgmain/lvroot ro noresume quiet

-- /etc/crypttab
# <target name>   <source device>    <key file>              <options>
#these two are the pvs of vgmain
luks-one          UUID=xxxxxx        none                    luks,initramfs
luks-two          UUID=yyyyyy        /dev/mapper/luks-one    
luks,initramfs,keyscript=/lib/cryptsetup/scripts/decrypt_derived

-- /etc/fstab
# <file system>               <mount point>     <type>    <options>       <dump>  
<pass>
/dev/vgmain/lvroot            /                 xfs       defaults        0     
  1
/dev/disk/by-partlabel/esp    /boot/efi         vfat      umask=0077      0     
  2


-- System Information:
Debian Release: 11.3
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 5.10.0-13-amd64 (SMP w/8 CPU threads)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_GB:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages cryptsetup-initramfs depends on:
ii  busybox-static [busybox]                1:1.30.1-6+b3
ii  cryptsetup                              2:2.3.7-1+deb11u1
ii  debconf [debconf-2.0]                   1.5.77
ii  initramfs-tools [linux-initramfs-tool]  0.140

Versions of packages cryptsetup-initramfs recommends:
ii  console-setup  1.205
ii  kbd            2.3.0-3

cryptsetup-initramfs suggests no packages.

-- debconf information:
  cryptsetup-initramfs/prerm_active_mappings: true
From d1229f61dffaeb516f3f652648fbaa1c3de570cb Mon Sep 17 00:00:00 2001
From: corubba <coru...@gmx.de>
Date: Mon, 28 Mar 2022 01:01:39 +0200
Subject: [PATCH] cryptroot hook: handle absolute keyfile path for decrypt_derived

---
 debian/initramfs/hooks/cryptroot | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/debian/initramfs/hooks/cryptroot b/debian/initramfs/hooks/cryptroot
index 81f65869..d9f01ea3 100644
--- a/debian/initramfs/hooks/cryptroot
+++ b/debian/initramfs/hooks/cryptroot
@@ -113,6 +113,9 @@ crypttab_print_entry() {
         # the boot scripts unlock it first); since _CRYPTTAB_* are local
         # to crypttab_find_and_print_entry() the new value won't
         # override the new ones
+        if [ "${CRYPTTAB_KEY#/}" != "$CRYPTTAB_KEY" ] && [ -b "$CRYPTTAB_KEY" ]; then
+            CRYPTTAB_KEY="$(dmsetup info -c --noheadings -o name -- "$CRYPTTAB_KEY")"
+        fi
         crypttab_find_and_print_entry "$CRYPTTAB_KEY"
     fi
     printf '%s %s %s %s\n' \
-- 
2.35.1

Reply via email to