Add new tests to verify kexec of blacklisted and non blacklisted kernel based on ima policy and secureboot state. Signed-off-by: Nageswara R Sastry <rnsastry@xxxxxxxxxxxxx> --- tools/testing/selftests/kexec/Makefile | 3 +- .../selftests/kexec/kexec_common_lib.sh | 71 +++++++++++++++ .../selftests/kexec/test_kexec_dbx_bk.sh | 90 +++++++++++++++++++ .../selftests/kexec/test_kexec_dbx_nbk.sh | 62 +++++++++++++ 4 files changed, 225 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/kexec/test_kexec_dbx_bk.sh create mode 100755 tools/testing/selftests/kexec/test_kexec_dbx_nbk.sh diff --git a/tools/testing/selftests/kexec/Makefile b/tools/testing/selftests/kexec/Makefile index 806a150648c3..ac1e998e0158 100644 --- a/tools/testing/selftests/kexec/Makefile +++ b/tools/testing/selftests/kexec/Makefile @@ -5,7 +5,8 @@ uname_M := $(shell uname -m 2>/dev/null || echo not) ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) ifeq ($(ARCH),$(filter $(ARCH),x86 ppc64le)) -TEST_PROGS := test_kexec_load.sh test_kexec_file_load.sh +TEST_PROGS := test_kexec_load.sh test_kexec_file_load.sh test_kexec_dbx_bk.sh\ + test_kexec_dbx_nbk.sh TEST_FILES := kexec_common_lib.sh include ../lib.mk diff --git a/tools/testing/selftests/kexec/kexec_common_lib.sh b/tools/testing/selftests/kexec/kexec_common_lib.sh index e907c3030eb3..9f9383940a93 100755 --- a/tools/testing/selftests/kexec/kexec_common_lib.sh +++ b/tools/testing/selftests/kexec/kexec_common_lib.sh @@ -7,6 +7,7 @@ VERBOSE="${VERBOSE:-1}" IKCONFIG="/tmp/config-`uname -r`" KERNEL_IMAGE="/boot/vmlinuz-`uname -r`" SECURITYFS=$(grep "securityfs" /proc/mounts | awk '{print $2}') +BLACKLIST_BIN_HASH="" log_info() { @@ -244,3 +245,73 @@ check_ima_policy() [ $? -eq 0 ] && ret=1 return $ret } + +# Look for check_blacklist in IMA Policy +# Return 1 for found and 0 for not found. +check_for_ima_policy_blacklist() +{ + local ret=0 + + check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ + "appraise_flag=check_blacklist" + ret=$? + [ $ret -eq 1 ] && log_info "Found IMA blacklist policy rule" + + return $ret +} + +# Look for blacklist_binary from blacklist keyring +# Return 1 for found and 0 for not found. +check_for_dbx_bin() +{ + local ret=0 + + which keyctl > /dev/null 2>&1 || log_skip "keyctl not found" + cmd=$(keyctl show %keyring:.blacklist | grep "blacklist: bin" | wc -l) + if [ $cmd -ge 1 ]; then + BLACKLIST_BIN_HASH=$(keyctl show %keyring:.blacklist | grep \ + "blacklist: bin" | cut -d":" -f3) + log_info "Found DBX blacklist binary from keyring" + ret=1 + fi + return $ret +} + +common_steps_for_dbx() +{ + ima_policy=0 + dbx=0 + secureboot=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 + + kconfig_enabled "CONFIG_SYSTEM_BLACKLIST_KEYRING=y" \ + "Kernel config blacklist_keyring is enabled" + if [ $? -eq 0 ]; then + log_skip "Kernel config blacklist_keyring is not enabled" + fi + + check_for_ima_policy_blacklist + ima_policy=$? + if [ $ima_policy -eq 0 ];then + log_skip "Not found IMA blacklist policy rule" + fi + + check_for_dbx_bin + dbx=$? + if [ $dbx -eq 0 ]; then + log_skip "Not found blacklisted kernel" + fi + + get_secureboot_mode + secureboot=$? +} diff --git a/tools/testing/selftests/kexec/test_kexec_dbx_bk.sh b/tools/testing/selftests/kexec/test_kexec_dbx_bk.sh new file mode 100755 index 000000000000..212a86be290d --- /dev/null +++ b/tools/testing/selftests/kexec/test_kexec_dbx_bk.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Loading a dbx black listed kernel image via the kexec_file_load syscall + +. ./kexec_common_lib.sh + +TEST="KEXEC_FILE_LOAD_DBX" + +# Read KERNEL_DBX_IMAGE from the environment variable +KERNEL_DBX_IMAGE=$(printenv | grep KERNEL_DBX_IMAGE | cut -d"=" -f2) +if [ -z $KERNEL_DBX_IMAGE ]; then + env_var="KERNEL_DBX_IMAGE" + log_skip "$env_var not found, set using 'export $env_var=value'" +# KERNEL_DBX_IMAGE=$KERNEL_IMAGE +# log_info "Continuing with booted kernel" +fi + +# Look for kernel matching with blacklisted binary hash +check_for_blacklist_kernel() +{ + local module_sig_string="~Module signature appended~" + local ret=0 + + tail --bytes $((${#module_sig_string} + 1)) $KERNEL_DBX_IMAGE | \ + grep -q "$module_sig_string" + if [ $? -eq 0 ]; then + log_info "Found $KERNEL_DBX_IMAGE with Module signature" + # Remove the signature + local hash=$(../../../../scripts/extract-module-sig.pl -0\ + ${KERNEL_DBX_IMAGE} 2> /dev/null | sha256sum -\ + |awk -F" " '{print $1}') + for b_hash in $BLACKLIST_BIN_HASH + do + # Make sure test is not going to run on booted kernel + if [ "$hash" == "$b_hash" -a \ + "$KERNEL_IMAGE" != "$KERNEL_DBX_IMAGE" ]; then + KERNEL_IMAGE=$KERNEL_DBX_IMAGE + ret=1 + fi + done + fi + return $ret +} + +kexec_file_load_dbx_test() +{ + local succeed_msg=$1 + local failed_msg=$2 + + 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 dbx blacklist exists + if [ $secureboot -eq 1 ] && [ $dbx -eq 1 ]; then + log_fail "$succeed_msg (secureboot and dbx enabled)" + # secureboot mode disabled, and dbx blacklist exists + elif [ $dbx -eq 1 ]; then + log_fail "$succeed_msg (dbx enabled)" + fi + fi + + # Check the reason for the kexec_file_load failure + if (echo $line | grep -q "Permission denied"); then + if [ $dbx -eq 1 ]; then + log_pass "$failed_msg (Permission denied)" + else + log_fail "$succeed_msg" + fi + fi + + return 0 +} + +common_steps_for_dbx + +check_for_blacklist_kernel +bk=$? + +if [ $bk -eq 0 ]; then + log_skip "Not found blacklisted hash matching kernel" +fi + +# Loading the black listed kernel image via kexec_file_load syscall should fail +succeed_msg="kexec blacklisted kernel image succeeded" +failed_msg="kexec blacklisted kernel image failed" +kexec_file_load_dbx_test "$succeed_msg" "$failed_msg" diff --git a/tools/testing/selftests/kexec/test_kexec_dbx_nbk.sh b/tools/testing/selftests/kexec/test_kexec_dbx_nbk.sh new file mode 100755 index 000000000000..8cd09dd79d01 --- /dev/null +++ b/tools/testing/selftests/kexec/test_kexec_dbx_nbk.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Loading a dbx black listed kernel image via the kexec_file_load syscall + +. ./kexec_common_lib.sh + +TEST="KEXEC_FILE_LOAD_DBX_NB" + +# Look for kernel matching with blacklisted binary hash +check_for_non_blacklist_kernel() +{ + local module_sig_string="~Module signature appended~" + local ret=0 + + tail --bytes $((${#module_sig_string} + 1)) $KERNEL_IMAGE | \ + grep -q "$module_sig_string" + if [ $? -eq 0 ]; then + log_info "Found $KERNEL_IMAGE with Module signature" + # Remove the signature + local hash=$(../../../../scripts/extract-module-sig.pl -0\ + ${KERNEL_IMAGE} 2> /dev/null | sha256sum -\ + |awk -F" " '{print $1}') + for b_hash in $BLACKLIST_BIN_HASH + do + if ! [ "$hash" == "$b_hash" ]; then + ret=1 + fi + done + fi + return $ret +} + +kexec_file_load_nbk_test() +{ + local succeed_msg=$1 + local failed_msg=$2 + + line=$(kexec --load --kexec-file-syscall $KERNEL_IMAGE 2>&1) + + if [ $? -eq 0 -a $secureboot -eq 1 ]; then + kexec --unload --kexec-file-syscall + log_pass "$succeed_msg (secureboot enabled)" + elif (echo $line | grep -q "Permission denied"); then + log_fail "$failed_msg (Permission denied)" + fi + +} + +common_steps_for_dbx + +check_for_non_blacklist_kernel +bk=$? + +if [ $bk -eq 0 ]; then + log_skip "Found blacklisted hash matching kernel" +fi + +# Loading the black listed kernel image via kexec_file_load syscall should fail +succeed_msg="kexec non blacklisted kernel image succeeded" +failed_msg="kexec non blacklisted kernel image failed" +kexec_file_load_nbk_test "$succeed_msg" "$failed_msg" -- 2.23.0