If the LUKS key is loaded in userspace memory, just get it with dmsetup.
Else ask password and get is using cryptsetup.
Signed-off-by: Kairui Song <kasong(a)redhat.com>
---
kdump-lib.sh | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/kdump-lib.sh b/kdump-lib.sh
index 5a37f4c..03129c5 100755
--- a/kdump-lib.sh
+++ b/kdump-lib.sh
@@ -114,6 +114,13 @@ to_dev_name() {
echo $dev
}
+# get uuid from block device
+# $1: block device
+get_block_uuid() {
+ [[ -b /dev/block/$1 ]] || return 1
+ echo $(eval "$(blkid -o export -- /dev/block/$1); echo \$UUID")
+}
+
is_user_configured_dump_target()
{
grep -E -q "^ext[234]|^xfs|^btrfs|^minix|^raw|^nfs|^ssh" /etc/kdump.conf ||
is_mount_in_dracut_args;
@@ -914,6 +921,17 @@ kdump_get_arch_recommend_size()
return 0
}
+# get_maj_min <device>
+# Prints the major and minor of a device node.
+# Example:
+# $ get_maj_min /dev/sda2
+# 8:2
+kdump_get_maj_min() {
+ local _majmin
+ _majmin="$(stat -L -c '%t:%T' "$1" 2> /dev/null)"
+ printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))"
+}
+
# Append files to an existing initramfs
# $1: initramfs to be appended to
# $2: root directory of files to be appended
@@ -950,3 +968,71 @@ get_luks_crypt_dev()
get_luks_crypt_dev "$(< "$_x/dev")"
done
}
+
+# Get the master key of a luks device and dump to a file
+# May prompt for password.
+# $1: the crypted block device in maj:min format
+# $2: file to dump into
+# $3: if non-empty, password prompt is allowed
+# Return 1 if failed to get the key, else return 0
+get_luks_dev_master_key()
+{
+ local _dev=$1 _file=$2 _askpass=$3 _mapper _info _key _x
+
+ [[ -b /dev/block/$1 ]] || return 1
+
+ for _x in /sys/dev/block/$1/holders/*; do
+ if [[ -z "$_mapper" ]]; then
+ _mapper=$_x
+ else
+ dwarn "Can't handle LUKS device having multiple holders"
+ return 1
+ fi
+ done
+
+ if [[ -n "$_mapper" ]]; then
+ (set +x;
+ _mapper=$(< $_mapper/dev)
+ _info=$(dmsetup --showkeys table --major ${_mapper%:*} --minor
${_mapper#*:})
+ _key=$(echo $_info | cut -d ' ' -f 5)
+ # If it's in kernel keyring, it's not useable in userspace
+ [[ $_key == :* ]] && _key=""
+
+ if [[ -n "$_key" ]]; then
+ echo $_key | xxd -ps -g1 -r > $_file
+ exit 0
+ fi
+ exit 1
+ ) && return 0
+ fi
+
+ if [[ "$_askpass" ]]; then
+ (set +x;
+ echo -n "Enter passphrase for $(readlink -f /dev/block/$_dev): "
+ read -s _key && echo ""
+
+ _key=$(echo "$_key" | cryptsetup luksDump --dump-master-key
/dev/block/$_dev)
+ _key=${_key#*MK dump:}
+ _key=${_key//[[:space:]]/}
+
+ if [[ -n "$_key" ]]; then
+ echo $_key | xxd -ps -g1 -r > $_file
+ exit 0
+ fi
+ exit 1
+ ) && return 0
+ fi
+
+ dwarn "Can't get key of LUKS device $(readlink -f /dev/block/$_dev)"
+ return 1
+}
+
+get_all_kdump_crypt_dev()
+{
+ local _dev _crypt
+
+ for _dev in $(get_kdump_targets); do
+ _crypt=$(get_luks_crypt_dev $(kdump_get_maj_min "$_dev"))
+ [[ -n "$_crypt" ]] && echo $_crypt
+ done
+}
--
2.30.2