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.
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)
;;
allow-discards)
allowdiscards="--allow-discards"
+ ;;
+ header=*)
+ cryptsetupopts="${cryptsetupopts} --${1}"
+ ;;
esac
shift
done
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
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)
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-}