diff mbox series

[3/3] Add tests to verify kexec of blacklist and non blacklist kernel

Message ID 20211124070802.1765-3-rnsastry@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series [1/3] selftest/kexec: fix "ignored null byte in input" warning | expand

Commit Message

R Nageswara Sastry Nov. 24, 2021, 7:08 a.m. UTC
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@linux.ibm.com>
---
 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 mbox series

Patch

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"