90crypt: probe for keydev asynchronously; changed kernel arg
New kernel argument syntax for LUKS-keydev is introduced: rd.luks.key=<key_path>[:<key_dev>[:<luks_dev>]] Unfolding <key_dev> in BNF: <key_dev> ::= "UUID=" <uuid> | "LABEL=" <label> | <kname> Where <kname> matches following regular expression: ^/dev/.* <kname> need to be a character device and not a symlink for now. For every rd.luks.key argument udev rule is created. That rule runs test to check whether matching device contains <key_path>. If it does it's applied to matching <luks_dev>.master
parent
ccb0ab7348
commit
8844cd6b6c
|
|
@ -0,0 +1,119 @@
|
|||
#!/bin/sh
|
||||
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||
|
||||
. /lib/dracut-lib.sh
|
||||
|
||||
# Try to mount specified device (by path, by UUID or by label) and check
|
||||
# the path with 'test'.
|
||||
#
|
||||
# example:
|
||||
# test_dev -f LABEL="nice label" /some/file1
|
||||
test_dev() {
|
||||
local test_op=$1; local dev="$2"; local f="$3"
|
||||
local ret=1; local mount_point=$(mkuniqdir /mnt testdev)
|
||||
local path
|
||||
|
||||
[ -n "$dev" -a -n "$*" ] || return 1
|
||||
[ -d "$mount_point" ] || die 'Mount point does not exist!'
|
||||
|
||||
if mount -r "$dev" "$mount_point" >/dev/null 2>&1; then
|
||||
test $test_op "${mount_point}/${f}"
|
||||
ret=$?
|
||||
umount "$mount_point"
|
||||
fi
|
||||
|
||||
rmdir "$mount_point"
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
# Get kernel name for given device. Device may be the name too (then the same
|
||||
# is returned), a symlink (full path), UUID (prefixed with "UUID=") or label
|
||||
# (prefixed with "LABEL="). If just a beginning of the UUID is specified or
|
||||
# even an empty, function prints all device names which UUIDs match - every in
|
||||
# single line.
|
||||
#
|
||||
# NOTICE: The name starts with "/dev/".
|
||||
#
|
||||
# Example:
|
||||
# devnames UUID=123
|
||||
# May print:
|
||||
# /dev/dm-1
|
||||
# /dev/sdb1
|
||||
# /dev/sdf3
|
||||
devnames() {
|
||||
local dev="$1"; local d; local names
|
||||
|
||||
case "$dev" in
|
||||
UUID=*)
|
||||
dev="$(foreach_uuid_until '! blkid -U $___' "${dev#UUID=}")" \
|
||||
&& return 255
|
||||
[ -z "$dev" ] && return 255
|
||||
;;
|
||||
LABEL=*) dev="$(blkid -L "${dev#LABEL=}")" || return 255 ;;
|
||||
/dev/?*) ;;
|
||||
*) return 255 ;;
|
||||
esac
|
||||
|
||||
for d in $dev; do
|
||||
names="$names
|
||||
$(readlink -e -q "$d")" || return 255
|
||||
done
|
||||
|
||||
echo "${names#
|
||||
}"
|
||||
}
|
||||
|
||||
# match_dev devpattern dev
|
||||
#
|
||||
# Returns true if 'dev' matches 'devpattern'. Both 'devpattern' and 'dev' are
|
||||
# expanded to kernel names and then compared. If name of 'dev' is on list of
|
||||
# names of devices matching 'devpattern', the test is positive. 'dev' and
|
||||
# 'devpattern' may be anything which function 'devnames' recognizes.
|
||||
#
|
||||
# If 'devpattern' is empty or '*' then function just returns true.
|
||||
#
|
||||
# Example:
|
||||
# match_dev UUID=123 /dev/dm-1
|
||||
# Returns true if /dev/dm-1 UUID starts with "123".
|
||||
match_dev() {
|
||||
[ -z "$1" -o "$1" = '*' ] && return 0
|
||||
local devlist; local dev
|
||||
|
||||
devlist="$(devnames "$1")" || return 255
|
||||
dev="$(devnames "$2")" || return 255
|
||||
|
||||
strstr "
|
||||
$devlist
|
||||
" "
|
||||
$dev
|
||||
"
|
||||
}
|
||||
|
||||
# getkey keysfile for_dev
|
||||
#
|
||||
# Reads file <keysfile> produced by probe-keydev and looks for first line to
|
||||
# which device <for_dev> matches. The successful result is printed in format
|
||||
# "<keydev>|<keypath>". When nothing found, just false is returned.
|
||||
#
|
||||
# Example:
|
||||
# getkey /tmp/luks.keys /dev/sdb1
|
||||
# May print:
|
||||
# /dev/sdc1|/keys/some.key
|
||||
getkey() {
|
||||
local keys_file="$1"; local for_dev="$2"
|
||||
local luks_dev; local key_dev; local key_path
|
||||
|
||||
[ -z "$keys_file" -o -z "$for_dev" ] && die 'getkey: wrong usage!'
|
||||
[ -f "$keys_file" ] || return 1
|
||||
|
||||
while IFS='|' read luks_dev key_dev key_path; do
|
||||
if match_dev "$luks_dev" "$for_dev"; then
|
||||
echo "${key_dev}|${key_path}"
|
||||
return 0
|
||||
fi
|
||||
done < "$keys_file"
|
||||
|
||||
return 1
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
# load dm_crypt if it is not already loaded
|
||||
[ -d /sys/module/dm_crypt ] || modprobe dm_crypt
|
||||
|
||||
. /lib/dracut-lib.sh
|
||||
. /lib/dracut-crypt-lib.sh
|
||||
|
||||
# default luksname - luks-UUID
|
||||
luksname=$2
|
||||
|
|
@ -26,6 +26,7 @@ else
|
|||
device="$1"
|
||||
fi
|
||||
|
||||
# TODO: improve to support what cmdline does
|
||||
if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -n rd_NO_CRYPTTAB; then
|
||||
while read name dev rest; do
|
||||
# ignore blank lines and comments
|
||||
|
|
@ -53,73 +54,31 @@ if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -n rd_NO_CRYPTTAB; then
|
|||
unset name dev rest
|
||||
fi
|
||||
|
||||
#
|
||||
# Search key on external devices
|
||||
#
|
||||
|
||||
# Try to mount device specified by UUID and probe for existence of any of
|
||||
# the paths. On success return 0 and print "<uuid> <first-existing-path>",
|
||||
# otherwise return 1.
|
||||
# Function leaves mount point created.
|
||||
probe_keydev() {
|
||||
local uuid="$1"; shift; local keypaths="$*"
|
||||
local ret=1; local mount_point=/mnt/keydev
|
||||
local path
|
||||
|
||||
[ -n "${uuid}" -a -n "${keypaths}" ] || return 1
|
||||
[ -d ${mount_point} ] || mkdir -p "${mount_point}" || return 1
|
||||
|
||||
if mount -r -U "${uuid}" "${mount_point}" 2>/dev/null >/dev/null; then
|
||||
for path in ${keypaths}; do
|
||||
if [ -f "${mount_point}/${path}" ]; then
|
||||
echo "${uuid} ${path}"
|
||||
ret=0
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
umount "${mount_point}" 2>/dev/null >/dev/null
|
||||
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
keypaths="$(getargs rd.luks.keypath rd_LUKS_KEYPATH)"
|
||||
unset keydev_uuid keypath
|
||||
|
||||
if [ -n "$keypaths" ]; then
|
||||
keydev_uuids="$(getargs rd.luks.keydev.uuid rd_LUKS_KEYDEV_UUID)"
|
||||
[ -n "$keydev_uuids" ] || {
|
||||
warn 'No UUID of device storing LUKS key specified.'
|
||||
warn 'It is recommended to set rd_LUKS_KEYDEV_UUID.'
|
||||
warn 'Performing scan of *all* devices accessible by UUID...'
|
||||
}
|
||||
tmp=$(foreach_uuid_until "probe_keydev \$full_uuid $keypaths" \
|
||||
$keydev_uuids) && {
|
||||
keydev_uuid="${tmp%% *}"
|
||||
keypath="${tmp#* }"
|
||||
} || {
|
||||
warn "Key for $device not found."
|
||||
}
|
||||
unset tmp keydev_uuids
|
||||
fi
|
||||
|
||||
unset keypaths
|
||||
|
||||
#
|
||||
# Open LUKS device
|
||||
#
|
||||
|
||||
info "luksOpen $device $luksname"
|
||||
|
||||
if [ -n "$keydev_uuid" ]; then
|
||||
mntp=/mnt/keydev
|
||||
mkdir -p "$mntp"
|
||||
mount -r -U "$keydev_uuid" "$mntp"
|
||||
if [ -n "$(getarg rd.luks.key)" ]; then
|
||||
if tmp=$(getkey /tmp/luks.keys $device); then
|
||||
keydev="${tmp%%|*}"
|
||||
keypath="${tmp#*|}"
|
||||
else
|
||||
info "No key found for $device. Will try later."
|
||||
/sbin/initqueue --unique --onetime --settled \
|
||||
--name cryptroot-ask-$luksname \
|
||||
/sbin/cryptroot-ask "$@"
|
||||
exit 0
|
||||
fi
|
||||
unset tmp
|
||||
|
||||
mntp=$(mkuniqdir /mnt keydev)
|
||||
mount -r "$keydev" "$mntp" || die 'Mounting rem. dev. failed!'
|
||||
cryptsetup -d "$mntp/$keypath" luksOpen "$device" "$luksname"
|
||||
umount "$mntp"
|
||||
rmdir -p "$mntp" 2>/dev/null
|
||||
unset mntp keypath keydev_uuid
|
||||
rmdir "$mntp"
|
||||
unset mntp keypath keydev
|
||||
else
|
||||
# Prompt for password with plymouth, if installed.
|
||||
# Should we check if plymouthd is running?
|
||||
|
|
|
|||
|
|
@ -2,7 +2,12 @@
|
|||
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||
inst cryptsetup
|
||||
inst rmdir
|
||||
inst readlink
|
||||
inst "$moddir"/cryptroot-ask.sh /sbin/cryptroot-ask
|
||||
inst "$moddir"/probe-keydev.sh /sbin/probe-keydev
|
||||
inst_hook cmdline 10 "$moddir/parse-keydev.sh"
|
||||
inst_hook cmdline 30 "$moddir/parse-crypt.sh"
|
||||
inst_hook pre-pivot 30 "$moddir/crypt-cleanup.sh"
|
||||
inst /etc/crypttab
|
||||
inst "$moddir/crypt-lib.sh" "/lib/dracut-crypt-lib.sh"
|
||||
|
|
|
|||
|
|
@ -11,10 +11,6 @@ else
|
|||
} > /etc/udev/rules.d/70-luks.rules
|
||||
|
||||
LUKS=$(getargs rd.luks.uuid rd_LUKS_UUID)
|
||||
unset settled
|
||||
[ -n "$(getargs rd.luks.keypath rd_LUKS_KEYPATH)" ] && \
|
||||
[ -z "$(getargs rd.luks.keydev.uuid rd_LUKS_KEYDEV_UUID)" ] && \
|
||||
settled='--settled'
|
||||
|
||||
if [ -n "$LUKS" ]; then
|
||||
for luksid in $LUKS; do
|
||||
|
|
@ -22,7 +18,7 @@ else
|
|||
{
|
||||
printf 'ENV{ID_FS_TYPE}=="crypto_LUKS", '
|
||||
printf 'ENV{ID_FS_UUID}=="*%s*", ' $luksid
|
||||
printf 'RUN+="/sbin/initqueue --unique --onetime %s ' "$settled"
|
||||
printf 'RUN+="/sbin/initqueue --unique --onetime '
|
||||
printf -- '--name cryptroot-ask-%%k /sbin/cryptroot-ask '
|
||||
printf '$env{DEVNAME} luks-$env{ID_FS_UUID}"\n'
|
||||
} >> /etc/udev/rules.d/70-luks.rules
|
||||
|
|
@ -35,7 +31,7 @@ else
|
|||
} >> /emergency/00-crypt.sh
|
||||
done
|
||||
else
|
||||
echo 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue' $settled \
|
||||
echo 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="/sbin/initqueue' \
|
||||
'--unique --onetime --name cryptroot-ask-%k' \
|
||||
'/sbin/cryptroot-ask $env{DEVNAME} luks-$env{ID_FS_UUID}"' \
|
||||
>> /etc/udev/rules.d/70-luks.rules
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/sh
|
||||
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||
|
||||
if getargbool 1 rd.luks -n rd_NO_LUKS && \
|
||||
[ -n "$(getarg rd.luks.key)" ]; then
|
||||
exec 7>/etc/udev/rules.d/65-luks-keydev.rules
|
||||
echo 'SUBSYSTEM!="block", GOTO="luks_keydev_end"' >&7
|
||||
echo 'ACTION!="add|change", GOTO="luks_keydev_end"' >&7
|
||||
|
||||
for arg in $(getargs rd.luks.key); do
|
||||
unset keypath keydev luksdev
|
||||
splitsep : "$arg" keypath keydev luksdev
|
||||
|
||||
info "rd.luks.key: keypath='$keypath' keydev='$keydev' luksdev='$luksdev'"
|
||||
|
||||
if [ -z "$keypath" ]; then
|
||||
warn 'keypath required!'
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -n "$keydev" ]; then
|
||||
udevmatch "$keydev" >&7 || {
|
||||
warn 'keydev incorrect!'
|
||||
continue
|
||||
}
|
||||
printf ', ' >&7
|
||||
fi
|
||||
|
||||
{
|
||||
printf 'RUN+="/sbin/initqueue --unique --onetime '
|
||||
printf -- '--name probe-keydev-%%k '
|
||||
printf '/sbin/probe-keydev /dev/%%k %s %s"\n' \
|
||||
"${keypath}" "${luksdev}"
|
||||
} >&7
|
||||
done
|
||||
unset arg keypath keydev luksdev
|
||||
|
||||
echo 'LABEL="luks_keydev_end"' >&7
|
||||
exec 7>&-
|
||||
fi
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
|
||||
. /lib/dracut-crypt-lib.sh
|
||||
|
||||
|
||||
real_keydev="$1"; keypath="$2"; luksdev="$3"
|
||||
|
||||
[ -z "$real_keydev" -o -z "$keypath" ] && die 'probe-keydev: wrong usage!'
|
||||
[ -z "$luksdev" ] && luksdev='*'
|
||||
|
||||
info "Probing $real_keydev for $keypath..."
|
||||
test_dev -f "$real_keydev" "$keypath" || exit 1
|
||||
|
||||
info "Found $keypath on $real_keydev"
|
||||
echo "$luksdev|$real_keydev|$keypath" >> /tmp/luks.keys
|
||||
Loading…
Reference in New Issue