From 557335e8a1e820ba131985e90109e43240c56274 Mon Sep 17 00:00:00 2001 From: Coiby Xu Date: Thu, 9 Oct 2025 16:49:53 +0800 Subject: [PATCH] Use cryptsetup --link-vk-to-keyring to save volume keys Resolves: https://issues.redhat.com/browse/RHEL-104940 Conflict: None commit 0d39f4fd626fea070d9b8af624feacd89938e7db Author: Coiby Xu Date: Wed Jun 18 09:16:26 2025 +0800 Use cryptsetup --link-vk-to-keyring to save volume keys cryptsetup open --link-vk-to-keyring (man cryptsetup-open) will link volume key to specified keyring after successfully unlocking the volume. Use this feature to save key to @u::%logon:cryptsetup:$UUID to support the following cases - volume is unlocked automatically say using TPM-sealed key - ask user to input passphrase to unlock the volume Signed-off-by: Coiby Xu Signed-off-by: Coiby Xu --- kdumpctl | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/kdumpctl b/kdumpctl index c572954..860ca57 100755 --- a/kdumpctl +++ b/kdumpctl @@ -1057,9 +1057,42 @@ check_final_action_config() fi } +_get_luks_key_by_unlock() +{ + local _devuuid=$1 _key_des=$2 + local _max_retries + local _attempt=1 + + local _luks_unlock_cmd="" + + # Check if stdin is a terminal. + if [ -t 0 ]; then + _max_retries=5 + ddebug "Attempting to unlock LUKS device. You have $_max_retries attempts." + else + # Not a terminal (e.g., running as system service), so only try once + # for cases where volume key is sealed to TPM which doesn't need user + # interaction. + _max_retries=1 + ddebug "Attempting to unlock LUKS device (non-interactive mode)..." + fi + + while [ "$_attempt" -le "$_max_retries" ]; do + if cryptsetup open "UUID=$_devuuid" DUMMY "--link-vk-to-keyring=@u::%logon:$_key_des" --test-passphrase; then + ddebug "Success: LUKS device unlocked." + dwarn "To avoid manually running kdumpctl, ensure the link-volume-key=@u::%logon:$_key_des option is correctly set up in /etc/crypttab (see man crypttab)." + return 0 + fi + _attempt=$((_attempt + 1)) + done + + derror "Error: Could not unlock the LUKS device." + return 1 +} + prepare_luks() { - local _luks_dev _key_id _key_des + local _luks_dev _key_id _key_des _luks_unlock_cmd declare -a _luks_devs mapfile -t _luks_devs < <(get_all_kdump_crypt_dev) @@ -1078,12 +1111,19 @@ prepare_luks() _key_dir=$LUKS_CONFIGFS/$_devuuid _key_des=$LUKS_KEY_PRFIX$_devuuid if _key_id=$(keyctl request logon "$_key_des" 2> /dev/null); then - mkdir "$_key_dir" - printf "%s" "$_key_des" > "$_key_dir"/description + ddebug "Succesfully get @u::%logon:$_key_des" + elif _get_luks_key_by_unlock "$_devuuid" "$_key_des"; then + _key_id=$(keyctl request logon "$_key_des") + ddebug "Succesfully get @u::%logon:$_key_des after cryptsetup" else - 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." + derror "Failed to get logon key $_key_des. Run 'kdumpctl restart' manually to start kdump." return 1 fi + + # Let the key expire after 300 seconds + keyctl timeout "$_key_id" 300 + mkdir "$_key_dir" + printf "%s" "$_key_des" > "$_key_dir"/description done }