forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
6.6 KiB
238 lines
6.6 KiB
#!/bin/sh |
|
# SPDX-License-Identifier: GPL-2.0 |
|
# |
|
# Loading a kernel image via the kexec_file_load syscall can verify either |
|
# the IMA signature stored in the security.ima xattr or the PE signature, |
|
# both signatures depending on the IMA policy, or none. |
|
# |
|
# To determine whether the kernel image is signed, this test depends |
|
# on pesign and getfattr. This test also requires the kernel to be |
|
# built with CONFIG_IKCONFIG enabled and either CONFIG_IKCONFIG_PROC |
|
# enabled or access to the extract-ikconfig script. |
|
|
|
TEST="KEXEC_FILE_LOAD" |
|
. ./kexec_common_lib.sh |
|
|
|
trap "{ rm -f $IKCONFIG ; }" EXIT |
|
|
|
# Some of the IMA builtin policies may require the kexec kernel image to |
|
# be signed, but these policy rules may be replaced with a custom |
|
# policy. Only CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS persists after |
|
# loading a custom policy. Check if it is enabled, before reading the |
|
# IMA runtime sysfs policy file. |
|
# Return 1 for IMA signature required and 0 for not required. |
|
is_ima_sig_required() |
|
{ |
|
local ret=0 |
|
|
|
kconfig_enabled "CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS=y" \ |
|
"IMA kernel image signature required" |
|
if [ $? -eq 1 ]; then |
|
log_info "IMA signature required" |
|
return 1 |
|
fi |
|
|
|
# The architecture specific or a custom policy may require the |
|
# kexec kernel image be signed. Policy rules are walked |
|
# sequentially. As a result, a policy rule may be defined, but |
|
# might not necessarily be used. This test assumes if a policy |
|
# rule is specified, that is the intent. |
|
|
|
# First check for appended signature (modsig), then xattr |
|
if [ $ima_read_policy -eq 1 ]; then |
|
check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ |
|
"appraise_type=imasig|modsig" |
|
ret=$? |
|
if [ $ret -eq 1 ]; then |
|
log_info "IMA or appended(modsig) signature required" |
|
else |
|
check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ |
|
"appraise_type=imasig" |
|
ret=$? |
|
[ $ret -eq 1 ] && log_info "IMA signature required"; |
|
fi |
|
fi |
|
return $ret |
|
} |
|
|
|
# The kexec_file_load_test() is complicated enough, require pesign. |
|
# Return 1 for PE signature found and 0 for not found. |
|
check_for_pesig() |
|
{ |
|
which pesign > /dev/null 2>&1 || log_skip "pesign not found" |
|
|
|
pesign -i $KERNEL_IMAGE --show-signature | grep -q "No signatures" |
|
local ret=$? |
|
if [ $ret -eq 1 ]; then |
|
log_info "kexec kernel image PE signed" |
|
else |
|
log_info "kexec kernel image not PE signed" |
|
fi |
|
return $ret |
|
} |
|
|
|
# The kexec_file_load_test() is complicated enough, require getfattr. |
|
# Return 1 for IMA signature found and 0 for not found. |
|
check_for_imasig() |
|
{ |
|
local ret=0 |
|
|
|
which getfattr > /dev/null 2>&1 |
|
if [ $? -eq 1 ]; then |
|
log_skip "getfattr not found" |
|
fi |
|
|
|
line=$(getfattr -n security.ima -e hex --absolute-names $KERNEL_IMAGE 2>&1) |
|
echo $line | grep -q "security.ima=0x03" |
|
if [ $? -eq 0 ]; then |
|
ret=1 |
|
log_info "kexec kernel image IMA signed" |
|
else |
|
log_info "kexec kernel image not IMA signed" |
|
fi |
|
return $ret |
|
} |
|
|
|
# Return 1 for appended signature (modsig) found and 0 for not found. |
|
check_for_modsig() |
|
{ |
|
local module_sig_string="~Module signature appended~" |
|
local sig="$(tail --bytes $((${#module_sig_string} + 1)) $KERNEL_IMAGE)" |
|
local ret=0 |
|
|
|
if [ "$sig" == "$module_sig_string" ]; then |
|
ret=1 |
|
log_info "kexec kernel image modsig signed" |
|
else |
|
log_info "kexec kernel image not modsig signed" |
|
fi |
|
return $ret |
|
} |
|
|
|
kexec_file_load_test() |
|
{ |
|
local succeed_msg="kexec_file_load succeeded" |
|
local failed_msg="kexec_file_load failed" |
|
local key_msg="try enabling the CONFIG_INTEGRITY_PLATFORM_KEYRING" |
|
|
|
line=$(kexec --load --kexec-file-syscall $KERNEL_IMAGE 2>&1) |
|
|
|
if [ $? -eq 0 ]; then |
|
kexec --unload --kexec-file-syscall |
|
|
|
# In secureboot mode with an architecture specific |
|
# policy, make sure either an IMA or PE signature exists. |
|
if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \ |
|
[ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ] \ |
|
&& [ $ima_modsig -eq 0 ]; then |
|
log_fail "$succeed_msg (missing sig)" |
|
fi |
|
|
|
if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \ |
|
&& [ $pe_signed -eq 0 ]; then |
|
log_fail "$succeed_msg (missing PE sig)" |
|
fi |
|
|
|
if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ] \ |
|
&& [ $ima_modsig -eq 0 ]; then |
|
log_fail "$succeed_msg (missing IMA sig)" |
|
fi |
|
|
|
if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ |
|
&& [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \ |
|
&& [ $ima_read_policy -eq 0 ]; then |
|
log_fail "$succeed_msg (possibly missing IMA sig)" |
|
fi |
|
|
|
if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 0 ]; then |
|
log_info "No signature verification required" |
|
elif [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ |
|
&& [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \ |
|
&& [ $ima_read_policy -eq 1 ]; then |
|
log_info "No signature verification required" |
|
fi |
|
|
|
log_pass "$succeed_msg" |
|
fi |
|
|
|
# Check the reason for the kexec_file_load failure |
|
echo $line | grep -q "Required key not available" |
|
if [ $? -eq 0 ]; then |
|
if [ $platform_keyring -eq 0 ]; then |
|
log_pass "$failed_msg (-ENOKEY), $key_msg" |
|
else |
|
log_pass "$failed_msg (-ENOKEY)" |
|
fi |
|
fi |
|
|
|
if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \ |
|
&& [ $pe_signed -eq 0 ]; then |
|
log_pass "$failed_msg (missing PE sig)" |
|
fi |
|
|
|
if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then |
|
log_pass "$failed_msg (missing IMA sig)" |
|
fi |
|
|
|
if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ |
|
&& [ $ima_sig_required -eq 0 ] && [ $ima_read_policy -eq 0 ] \ |
|
&& [ $ima_signed -eq 0 ]; then |
|
log_pass "$failed_msg (possibly missing IMA sig)" |
|
fi |
|
|
|
log_pass "$failed_msg" |
|
return 0 |
|
} |
|
|
|
# kexec requires root privileges |
|
require_root_privileges |
|
|
|
# get the kernel config |
|
get_kconfig |
|
|
|
kconfig_enabled "CONFIG_KEXEC_FILE=y" "kexec_file_load is enabled" |
|
if [ $? -eq 0 ]; then |
|
log_skip "kexec_file_load is not enabled" |
|
fi |
|
|
|
# Determine which kernel config options are enabled |
|
kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled" |
|
ima_appraise=$? |
|
|
|
kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \ |
|
"architecture specific policy enabled" |
|
arch_policy=$? |
|
|
|
kconfig_enabled "CONFIG_INTEGRITY_PLATFORM_KEYRING=y" \ |
|
"platform keyring enabled" |
|
platform_keyring=$? |
|
|
|
kconfig_enabled "CONFIG_IMA_READ_POLICY=y" "reading IMA policy permitted" |
|
ima_read_policy=$? |
|
|
|
kconfig_enabled "CONFIG_KEXEC_SIG_FORCE=y" \ |
|
"kexec signed kernel image required" |
|
kexec_sig_required=$? |
|
|
|
kconfig_enabled "CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y" \ |
|
"PE signed kernel image required" |
|
pe_sig_required=$? |
|
|
|
is_ima_sig_required |
|
ima_sig_required=$? |
|
|
|
get_secureboot_mode |
|
secureboot=$? |
|
|
|
# Are there pe and ima signatures |
|
check_for_pesig |
|
pe_signed=$? |
|
|
|
check_for_imasig |
|
ima_signed=$? |
|
|
|
check_for_modsig |
|
ima_modsig=$? |
|
|
|
# Test loading the kernel image via kexec_file_load syscall |
|
kexec_file_load_test
|
|
|