Skip to content

Commit d9677e1

Browse files
committed
Support dumping to a LUKS-encrypted target
Based on the new kernel feature that dm-crypt keys can persist for the kdump kernel [1][2], this patch which is adapted from [3] 1) ask the 1st kernel to save a copy of the LUKS volume keys 2) ask the kdump kernel to add the copy of the LUKS volume keys to specified keyring and then use --volume-key-keyring the unlock the LUKS device. Users need to set up the link-volume-key option in /etc/crypttab (man crypttab) so kdumpctl can read the key from @U::%logon:cryptsetup:UUID and instruct the kernel to save it to kdump-reserved memory. [1] https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/kdump/kdump.rst#write-the-dump-file-to-encrypted-disk-volume [2] torvalds/linux@180cf31 [3] https://lists.fedorahosted.org/archives/list/[email protected]/message/Y3KUSJQPN3JHUUC2FPIK7H4HTSX2TUCX/ Signed-off-by: Coiby Xu <[email protected]>
1 parent e5a47c6 commit d9677e1

File tree

6 files changed

+90
-15
lines changed

6 files changed

+90
-15
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
#
3+
echo true > /sys/kernel/config/crash_dm_crypt_keys/restore

dracut/99kdumpbase/module-setup.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,50 @@ ForwardToConsole=yes
10941094
EOF
10951095
}
10961096

1097+
kdump_check_crypt_targets() {
1098+
local _luks_dev _devuuid _key_desc
1099+
declare -a _luks_devs
1100+
1101+
mapfile -t _luks_devs < <(get_all_kdump_crypt_dev)
1102+
1103+
if [[ ${#_luks_devs[@]} -lt 1 ]]; then
1104+
return
1105+
fi
1106+
1107+
if [[ ! -d $LUKS_CONFIGFS ]]; then
1108+
dwarn "$LUKS_CONFIGFS not available"
1109+
return 1
1110+
fi
1111+
1112+
# This overrides behaviour of 90crypt
1113+
inst cryptsetup
1114+
instmods dm_crypt
1115+
1116+
echo > "$initdir/etc/cmdline.d/90crypt.conf"
1117+
echo > "$initdir/etc/crypttab"
1118+
echo > "${initdir}/sbin/crypt-run-generator"
1119+
1120+
# configfs is mounted after dracut pre-udev hook
1121+
# shellcheck disable=SC2154
1122+
inst_hook initqueue 20 "$moddir/kexec-crypt-setup.sh"
1123+
1124+
# shellcheck disable=SC2154
1125+
mkdir -p "$hookdir/initqueue/finished"
1126+
CRYPTSETUP_PATH=$(command -v cryptsetup)
1127+
for _luks_dev in "${_luks_devs[@]}"; do
1128+
_devuuid=$(maj_min_to_uuid "$_luks_dev")
1129+
_key_desc=$LUKS_KEY_PRFIX$_devuuid
1130+
cat << EOF >> "${initdir}/etc/udev/rules.d/70-luks-kdump.rules"
1131+
ENV{ID_FS_UUID}=="$_devuuid", \
1132+
RUN+="/sbin/initqueue --settled --unique --onetime --name kdump-crypt-target-%k \
1133+
$CRYPTSETUP_PATH luksOpen --volume-key-keyring \
1134+
%%user:$_key_desc \$env{DEVNAME} luks-$_devuuid"
1135+
EOF
1136+
done
1137+
1138+
dracut_need_initqueue
1139+
}
1140+
10971141
install() {
10981142
declare -A unique_netifs ovs_unique_netifs ipv4_usage ipv6_usage
10991143
local is_nvmf
@@ -1146,6 +1190,8 @@ install() {
11461190

11471191
kdump_check_nvmf_target
11481192

1193+
kdump_check_crypt_targets
1194+
11491195
kdump_install_systemd_conf
11501196

11511197
# nfs/ssh dump will need to get host ip in second kernel and need to call 'ip' tool, see get_host_ip for more detail

kdump-lib-initramfs.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ KDUMP_CONFIG_FILE="/etc/kdump.conf"
1111
FENCE_KDUMP_SEND="/usr/libexec/fence_kdump_send"
1212
# shellcheck disable=SC2034
1313
LVM_CONF="/etc/lvm/lvm.conf"
14+
# shellcheck disable=SC2034
15+
LUKS_CONFIGFS=/sys/kernel/config/crash_dm_crypt_keys
16+
# shellcheck disable=SC2034
17+
LUKS_KEY_PRFIX="systemd-cryptsetup:vk-"
1418

1519
# Read kdump config in well formated style
1620
kdump_read_conf()

kdumpctl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ trap '
5252
ret=$?;
5353
is_mounted $TMPMNT && umount -f $TMPMNT;
5454
rm -rf "$KDUMP_TMPDIR"
55+
[[ -d $LUKS_CONFIGFS ]] && find $LUKS_CONFIGFS/ -mindepth 1 -type d -delete
5556
exit $ret;
5657
' EXIT
5758

@@ -731,6 +732,11 @@ load_kdump()
731732
args+=("--initrd=$TARGET_INITRD")
732733
args+=("$KDUMP_KERNEL")
733734

735+
if ! prepare_luks; then
736+
derror "kexec: failed to prepare for a LUKS target"
737+
return 1
738+
fi
739+
734740
ddebug "$KEXEC ${args[*]}"
735741
if $KEXEC "${args[@]}"; then
736742
dinfo "kexec: loaded kdump kernel"
@@ -1050,6 +1056,36 @@ check_final_action_config()
10501056
esac
10511057
}
10521058

1059+
prepare_luks()
1060+
{
1061+
local _luks_dev _key_id _key_des
1062+
declare -a _luks_devs
1063+
1064+
mapfile -t _luks_devs < <(get_all_kdump_crypt_dev)
1065+
1066+
if [[ ${#_luks_devs[@]} -lt 1 ]]; then
1067+
return
1068+
fi
1069+
1070+
if [[ ! -d $LUKS_CONFIGFS ]]; then
1071+
dwarn "$LUKS_CONFIGFS not available, please use a newer kernel."
1072+
return 1
1073+
fi
1074+
1075+
for _luks_dev in "${_luks_devs[@]}"; do
1076+
_devuuid=$(maj_min_to_uuid "$_luks_dev")
1077+
_key_dir=$LUKS_CONFIGFS/$_devuuid
1078+
_key_des=$LUKS_KEY_PRFIX$_devuuid
1079+
if _key_id=$(keyctl request logon "$_key_des" 2> /dev/null); then
1080+
mkdir "$_key_dir"
1081+
printf "%s" "$_key_des" > "$_key_dir"/description
1082+
else
1083+
derror "Failed to get logon key $_key_des. Ensure the link-volume-key option is correctly set up in /etc/crypttab (see man crypttab) and that the key is available."
1084+
return 1
1085+
fi
1086+
done
1087+
}
1088+
10531089
start()
10541090
{
10551091
check_dump_feasibility || return

mkdumprd

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -318,21 +318,6 @@ handle_default_dump_target()
318318
check_size fs "$_target"
319319
}
320320

321-
check_crypt()
322-
{
323-
local _dev
324-
325-
for _dev in $(get_kdump_targets); do
326-
if [[ -n $(get_luks_crypt_dev "$(get_maj_min "$_dev")") ]]; then
327-
derror "Device $_dev is encrypted." && return 1
328-
fi
329-
done
330-
}
331-
332-
if ! check_crypt; then
333-
dwarn "Warning: Encrypted device is in dump path, which is not recommended, see kexec-kdump-howto.txt for more details."
334-
fi
335-
336321
# firstly get right SSH_KEY_LOCATION
337322
keyfile=$(kdump_get_conf_val sshkey)
338323
if [[ -f $keyfile ]]; then

supported-kdump-targets.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ storage:
4949
NVMe-FC (qla2xxx, lpfc)
5050
NVMe/TCP configured by NVMe Boot Firmware Table (users may need to
5151
increase the crashkernel value)
52+
LUKS-encrypted volume
5253

5354
network:
5455
Hardware using kernel modules: (igb, ixgbe, ice, i40e, e1000e, igc,

0 commit comments

Comments
 (0)