Allow "sudo kdumpctl" for LUKS dump target

Resolves: https://issues.redhat.com/browse/RHEL-124989
Conflict: Upstream has slightly different format

commit c08d151016ab4d62addc2ec8089a756c0d89d583
Author: Coiby Xu <coxu@redhat.com>
Date:   Wed Nov 5 10:14:28 2025 +0800

    Allow "sudo kdumpctl" for LUKS dump target

    Some users may run kdumcptl after "sudo su" or use "sudo kdumpctl". And
    kdump will fail,
        # sudo kdumcptl restart
        request_key: Required key not available
        keyctl_set_timeout: Invalid argument
        kexec_file_load failed: Required key not available
        kdump: kexec: failed to load kdump kernel

    This happens because the LUKS keys is can only be searched (keyctl request)
    by the process but not by the user and sudo process inherits the session
    keyring (@s) of the original user (test in the following example),

        [test@localhost ~]$ sudo keyctl add user testkey testdata @u
        711801750
        [test@localhost ~]$ sudo grep testkey /proc/keys
        2a6d3b96 I--Q---     1 perm 3f010000     0     0 user      testkey: 8
        [test@localhost ~]$ sudo keyctl show 711801750
        Keyring
        Unable to dump key: Permission denied

    The permission "3f010000" means the process has all the permissions but
    user only has the view permission i.e. "sudo keyctl show/list @u" will list
    all the keys but "sudo keyctl show KEY_ID" won't work.

    Automatically use "sudo -i" which will use the session keyring (@s) of
    the root to support "sudo kdumpctl". Note "sudo -i kexec" is also
    needed in order for the process to read the keys in the kernel space.

    Reported-by: Li Tian <litian@redhat.com>
    Signed-off-by: Coiby Xu <coxu@redhat.com>
This commit is contained in:
Coiby Xu 2025-11-07 13:51:36 +08:00
parent f7e92f8a6a
commit 228cf59003

View File

@ -655,6 +655,8 @@ function load_kdump_kernel_key()
return
fi
# %.ima keyring is writable to the user, no need to use
# "sudo -i keyctl"
keyctl padd asymmetric "" %:.ima < "/usr/share/doc/kernel-keys/$KDUMP_KERNELVER/kernel-signing-ppc.cer"
}
@ -683,6 +685,7 @@ load_kdump()
return 1
fi
[[ ${KEYCTL_CMD[0]} == sudo ]] && KEXEC="sudo -i $KEXEC"
ddebug "$KEXEC $KEXEC_ARGS $standard_kexec_args --command-line=$KDUMP_COMMANDLINE --initrd=$TARGET_INITRD $KDUMP_KERNEL"
# shellcheck disable=SC2086
@ -1062,6 +1065,9 @@ remove_luks_vol_keys()
local _key_line _key_id _key_desc _status=1
# Get all keys from @u keyring and process each line
# sudo process by default only has the permission to list the keys
# stored in user keyring i.e. "sudo keyctl list" can work not
# "sudo keyctl unlink/show"
while read -r _key_line; do
# Skip header lines and empty lines
[[ $_key_line =~ ^[0-9]+: ]] || continue
@ -1078,7 +1084,7 @@ remove_luks_vol_keys()
# Check if key description starts with LUKS_KEY_PRFIX
if [[ $_key_desc == "$LUKS_KEY_PRFIX"* ]]; then
keyctl unlink "$_key_id"
"${KEYCTL_CMD[@]}" unlink "$_key_id"
_status=0
fi
done < <(keyctl list @u 2> /dev/null || true)
@ -1120,11 +1126,22 @@ _get_luks_key_by_unlock()
return 1
}
# Some users may use "sudo kdumpctl". sudo process by default inherits the
# session keyring (@s) of the original user which means it can't read LUKS keys
# stored in root's user (@u) which is only linked to root's session keyring.
# So use "sudo -i keyctl" and "sudo kexec" automatically in order to be able to
# search and read the LUKS key(s).
KEYCTL_CMD=(keyctl)
prepare_luks()
{
local _key_id _key_des _luks_unlock_cmd
declare -a _luks_devs
# Use "sudo -i" to use the root's session keyring to access LUKS keys
if ! keyctl show @s | grep -qs "_uid.0$"; then
KEYCTL_CMD=(sudo -i keyctl)
fi
mapfile -t _luks_devs < <(get_all_kdump_crypt_dev)
if [[ ${#_luks_devs[@]} -lt 1 ]]; then
@ -1152,10 +1169,13 @@ prepare_luks()
for _devuuid in "${_luks_devs[@]}"; do
_key_dir=$LUKS_CONFIGFS/$_devuuid
_key_des=$LUKS_KEY_PRFIX$_devuuid
if _key_id=$(keyctl request logon "$_key_des" 2> /dev/null); then
if _key_id=$("${KEYCTL_CMD[@]}" request logon "$_key_des" 2> /dev/null); then
ddebug "Succesfully get @u::%logon:$_key_des"
elif _get_luks_key_by_unlock "$_devuuid" "$_key_des"; then
_key_id=$(keyctl request logon "$_key_des")
if ! _key_id=$("${KEYCTL_CMD[@]}" request logon "$_key_des"); then
derror "Probably you are using 'sudo kdumpctl' or 'sudo su', please retry with 'sudo -i kdumpctl'"
return 1
fi
ddebug "Succesfully get @u::%logon:$_key_des after cryptsetup"
else
derror "Failed to get logon key $_key_des. Run 'kdumpctl restart' manually to start kdump."
@ -1163,7 +1183,7 @@ prepare_luks()
fi
# Let the key expire after 300 seconds
keyctl timeout "$_key_id" 300
"${KEYCTL_CMD[@]}" timeout "$_key_id" 300
mkdir "$_key_dir"
printf "%s" "$_key_des" > "$_key_dir"/description
done