From b7058d0ce5e99cbc80b5f760a0b654d3ff03c094 Mon Sep 17 00:00:00 2001 From: privb0x23 Date: Tue, 3 Oct 2017 23:37:55 +0100 Subject: [PATCH] Add basic LUKS detached header support A LUKS root volume with a detached header on a device without partitioning will not have a UUID and will not have an attribute ENV{ID_FS_TYPE}=="crypto_LUKS". Therefore, several areas need to be addressed: identification of the LUKS device, inclusion of entries within crypttab, and provision of the detached header file. - Added support for an option (4th column: "force") in /etc/crypttab to force the inclusion of the entry in the initramfs version (avoiding the fs type test). - Added support for an option (4th column: "header=/path/to/file") in /etc/crypttab to provide a path to a detached header file embedded within the initramfs. - Added ID and PARTUUID support to the device (2nd column) in /etc/crypttab (complementing the existing UUID functionality). - Added cmdline support to indicate LUKS device ("rd.luks.serial=") that refers to the attribute ENV{ID_SERIAL_SHORT}. Tested successfully on Void Linux (x86_64 musl) (no systemd) with a LUKS root volume accessed with a keyfile and using a detached header. Not tested on systemd, or on a LUKS root volume with a passphrase rather than a keyfile. --- modules.d/90crypt/cryptroot-ask.sh | 20 ++++++++++++- modules.d/90crypt/module-setup.sh | 46 ++++++++++++++++++++++++------ modules.d/90crypt/parse-crypt.sh | 33 ++++++++++++++++++++- 3 files changed, 88 insertions(+), 11 deletions(-) diff --git a/modules.d/90crypt/cryptroot-ask.sh b/modules.d/90crypt/cryptroot-ask.sh index 5b513638d..9f635eb30 100755 --- a/modules.d/90crypt/cryptroot-ask.sh +++ b/modules.d/90crypt/cryptroot-ask.sh @@ -29,13 +29,27 @@ if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -d -n rd_NO_CRYPTTAB; t continue fi + # PARTUUID used in crypttab + if [ "${dev%%=*}" = "PARTUUID" ]; then + if [ "luks-${dev##PARTUUID=}" = "$luksname" ]; then + luksname="$name" + break + fi + # UUID used in crypttab - if [ "${dev%%=*}" = "UUID" ]; then + elif [ "${dev%%=*}" = "UUID" ]; then if [ "luks-${dev##UUID=}" = "$luksname" ]; then luksname="$name" break fi + # ID used in crypttab + elif [ "${dev%%=*}" = "ID" ]; then + if [ "luks-${dev##ID=}" = "$luksname" ]; then + luksname="$name" + break + fi + # path used in crypttab else cdev=$(readlink -f $dev) @@ -88,6 +102,10 @@ while [ $# -gt 0 ]; do ;; allow-discards) allowdiscards="--allow-discards" + ;; + header=*) + cryptsetupopts="${cryptsetupopts} --${1}" + ;; esac shift done diff --git a/modules.d/90crypt/module-setup.sh b/modules.d/90crypt/module-setup.sh index 9c1be9984..69aceaab9 100755 --- a/modules.d/90crypt/module-setup.sh +++ b/modules.d/90crypt/module-setup.sh @@ -68,22 +68,50 @@ install() { if [[ $hostonly ]] && [[ -f /etc/crypttab ]]; then # filter /etc/crypttab for the devices we need - while read _mapper _dev _rest || [ -n "$_mapper" ]; do + while read _mapper _dev _luksfile _luksoptions || [ -n "$_mapper" ]; do [[ $_mapper = \#* ]] && continue [[ $_dev ]] || continue + [[ $_dev == PARTUUID=* ]] && \ + _dev="/dev/disk/by-partuuid/${_dev#PARTUUID=}" + [[ $_dev == UUID=* ]] && \ _dev="/dev/disk/by-uuid/${_dev#UUID=}" - echo "$_dev $(blkid $_dev -s UUID -o value)" > /usr/lib/dracut/modules.d/90crypt/block_uuid.map - - for _hdev in "${!host_fs_types[@]}"; do - [[ ${host_fs_types[$_hdev]} == "crypto_LUKS" ]] || continue - if [[ $_hdev -ef $_dev ]] || [[ /dev/block/$_hdev -ef $_dev ]]; then - echo "$_mapper $_dev $_rest" - break - fi + [[ $_dev == ID=* ]] && \ + _dev="/dev/disk/by-id/${_dev#ID=}" + + echo "$_dev $(blkid $_dev -s UUID -o value)" >> /usr/lib/dracut/modules.d/90crypt/block_uuid.map + + # loop through the options to check for the force option + luksoptions=${_luksoptions} + OLD_IFS="${IFS}" + IFS=, + set -- ${luksoptions} + IFS="${OLD_IFS}" + + while [ $# -gt 0 ]; do + case $1 in + force) + forceentry="yes" + break + ;; + esac + shift done + + # include the entry regardless + if [ "${forceentry}" = "yes" ]; then + echo "$_mapper $_dev $_luksfile $_luksoptions" + else + for _hdev in "${!host_fs_types[@]}"; do + [[ ${host_fs_types[$_hdev]} == "crypto_LUKS" ]] || continue + if [[ $_hdev -ef $_dev ]] || [[ /dev/block/$_hdev -ef $_dev ]]; then + echo "$_mapper $_dev $_luksfile $_luksoptions" + break + fi + done + fi done < /etc/crypttab > $initdir/etc/crypttab mark_hostonly /etc/crypttab fi diff --git a/modules.d/90crypt/parse-crypt.sh b/modules.d/90crypt/parse-crypt.sh index 8a0db02b5..f0a4fba96 100755 --- a/modules.d/90crypt/parse-crypt.sh +++ b/modules.d/90crypt/parse-crypt.sh @@ -35,6 +35,7 @@ else echo 'ACTION!="add|change", GOTO="luks_end"' } > /etc/udev/rules.d/70-luks.rules.new + SERIAL=$(getargs rd.luks.serial -d rd_LUKS_SERIAL) LUKS=$(getargs rd.luks.uuid -d rd_LUKS_UUID) tout=$(getarg rd.luks.key.tout) @@ -44,7 +45,37 @@ else done < /etc/crypttab fi - if [ -n "$LUKS" ]; then + if [ -n "$SERIAL" ]; then + for serialid in $SERIAL; do + + serialid=${serialid##luks-} + if luksname=$(_cryptgetargsname "rd.luks.name=$serialid="); then + luksname="${luksname#$serialid=}" + else + luksname="luks-$serialid" + fi + + if [ -z "$DRACUT_SYSTEMD" ]; then + { + printf -- 'ENV{ID_SERIAL_SHORT}=="*%s*", ' "$serialid" + printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)" + printf -- '--name cryptroot-ask-%%k %s ' "$(command -v cryptroot-ask)" + printf -- '$env{DEVNAME} %s %s"\n' "$luksname" "$tout" + } >> /etc/udev/rules.d/70-luks.rules.new + else + luksname=$(dev_unit_name "$luksname") + if ! crypttab_contains "$serialid"; then + { + printf -- 'ENV{ID_SERIAL_SHORT}=="*%s*", ' "$serialid" + printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)" + printf -- '--name systemd-cryptsetup-%%k %s start ' "$(command -v systemctl)" + printf -- 'systemd-cryptsetup@%s.service"\n' "$luksname" + } >> /etc/udev/rules.d/70-luks.rules.new + fi + fi + done + + elif [ -n "$LUKS" ]; then for luksid in $LUKS; do luksid=${luksid##luks-} -- 2.47.2