diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-06 20:29:45 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-06 20:29:45 -0700 |
| commit | 71ae5fc87c34ecbdca293c2a5c563d6be2576558 (patch) | |
| tree | 10e90a938f38158470937b3d13c9c8a6f46b24c4 /tools | |
| parent | 81ff5d2cba4f86cd850b9ee4a530cd221ee45aa3 (diff) | |
| parent | d917fb876f6eaeeea8a2b620d2a266ce26372f4d (diff) | |
| download | linux-71ae5fc87c34ecbdca293c2a5c563d6be2576558.tar.gz linux-71ae5fc87c34ecbdca293c2a5c563d6be2576558.tar.bz2 linux-71ae5fc87c34ecbdca293c2a5c563d6be2576558.zip | |
Merge tag 'linux-kselftest-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull Kselftest updates from Shuah Khan:
- fixes to seccomp test, and kselftest framework
- cleanups to remove duplicate header defines
- fixes to efivarfs "make clean" target
- cgroup cleanup path
- Moving the IMA kexec_load selftest to selftests/kexec work from Mimi
Johar and Petr Vorel
- A framework to kselftest for writing kernel test modules addition
from Tobin C. Harding
* tag 'linux-kselftest-5.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (29 commits)
selftests: build and run gpio when output directory is the src dir
selftests/ipc: Fix msgque compiler warnings
selftests/efivarfs: clean up test files from test_create*()
selftests: fix headers_install circular dependency
selftests/kexec: update get_secureboot_mode
selftests/kexec: make kexec_load test independent of IMA being enabled
selftests/kexec: check kexec_load and kexec_file_load are enabled
selftests/kexec: Add missing '=y' to config options
selftests/kexec: kexec_file_load syscall test
selftests/kexec: define "require_root_privileges"
selftests/kexec: define common logging functions
selftests/kexec: define a set of common functions
selftests/kexec: cleanup the kexec selftest
selftests/kexec: move the IMA kexec_load selftest to selftests/kexec
selftests/harness: Add 30 second timeout per test
selftests/seccomp: Handle namespace failures gracefully
selftests: cgroup: fix cleanup path in test_memcg_subtree_control()
selftests: efivarfs: remove the test_create_read file if it was exist
rseq/selftests: Adapt number of threads to the number of detected cpus
lib: Add test module for strscpy_pad
...
Diffstat (limited to 'tools')
27 files changed, 782 insertions, 186 deletions
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 971fc8428117..f2ebf8cf4686 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -15,11 +15,11 @@ TARGETS += firmware TARGETS += ftrace TARGETS += futex TARGETS += gpio -TARGETS += ima TARGETS += intel_pstate TARGETS += ipc TARGETS += ir TARGETS += kcmp +TARGETS += kexec TARGETS += kvm TARGETS += lib TARGETS += livepatch @@ -75,12 +75,15 @@ ifneq ($(KBUILD_SRC),) override LDFLAGS = endif -BUILD := $(O) -ifndef BUILD - BUILD := $(KBUILD_OUTPUT) -endif -ifndef BUILD - BUILD := $(shell pwd) +ifneq ($(O),) + BUILD := $(O) +else + ifneq ($(KBUILD_OUTPUT),) + BUILD := $(KBUILD_OUTPUT) + else + BUILD := $(shell pwd) + DEFAULT_INSTALL_HDR_PATH := 1 + endif endif # KSFT_TAP_LEVEL is used from KSFT framework to prevent nested TAP header @@ -89,8 +92,50 @@ endif # with system() call. Export it here to cover override RUN_TESTS defines. export KSFT_TAP_LEVEL=`echo 1` +# Prepare for headers install +top_srcdir ?= ../../.. +include $(top_srcdir)/scripts/subarch.include +ARCH ?= $(SUBARCH) +export KSFT_KHDR_INSTALL_DONE := 1 export BUILD -all: + +# build and run gpio when output directory is the src dir. +# gpio has dependency on tools/gpio and builds tools/gpio +# objects in the src directory in all cases making the src +# repo dirty even when objects are relocated. +ifneq (1,$(DEFAULT_INSTALL_HDR_PATH)) + TMP := $(filter-out gpio, $(TARGETS)) + TARGETS := $(TMP) +endif + +# set default goal to all, so make without a target runs all, even when +# all isn't the first target in the file. +.DEFAULT_GOAL := all + +# Install headers here once for all tests. KSFT_KHDR_INSTALL_DONE +# is used to avoid running headers_install from lib.mk. +# Invoke headers install with --no-builtin-rules to avoid circular +# dependency in "make kselftest" case. In this case, second level +# make inherits builtin-rules which will use the rule generate +# Makefile.o and runs into +# "Circular Makefile.o <- prepare dependency dropped." +# and headers_install fails and test compile fails. +# +# O= KBUILD_OUTPUT cases don't run into this error, since main Makefile +# invokes them as sub-makes and --no-builtin-rules is not necessary, +# but doesn't cause any failures. Keep it simple and use the same +# flags in both cases. +# Local build cases: "make kselftest", "make -C" - headers are installed +# in the default INSTALL_HDR_PATH usr/include. +khdr: +ifeq (1,$(DEFAULT_INSTALL_HDR_PATH)) + make --no-builtin-rules ARCH=$(ARCH) -C $(top_srcdir) headers_install +else + make --no-builtin-rules INSTALL_HDR_PATH=$$BUILD/usr \ + ARCH=$(ARCH) -C $(top_srcdir) headers_install +endif + +all: khdr @for TARGET in $(TARGETS); do \ BUILD_TARGET=$$BUILD/$$TARGET; \ mkdir $$BUILD_TARGET -p; \ @@ -173,4 +218,4 @@ clean: make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\ done; -.PHONY: all run_tests hotplug run_hotplug clean_hotplug run_pstore_crash install clean +.PHONY: khdr all run_tests hotplug run_hotplug clean_hotplug run_pstore_crash install clean diff --git a/tools/testing/selftests/cgroup/test_memcontrol.c b/tools/testing/selftests/cgroup/test_memcontrol.c index 28d321ba311b..6f339882a6ca 100644 --- a/tools/testing/selftests/cgroup/test_memcontrol.c +++ b/tools/testing/selftests/cgroup/test_memcontrol.c @@ -26,7 +26,7 @@ */ static int test_memcg_subtree_control(const char *root) { - char *parent, *child, *parent2, *child2; + char *parent, *child, *parent2 = NULL, *child2 = NULL; int ret = KSFT_FAIL; char buf[PAGE_SIZE]; @@ -34,50 +34,54 @@ static int test_memcg_subtree_control(const char *root) parent = cg_name(root, "memcg_test_0"); child = cg_name(root, "memcg_test_0/memcg_test_1"); if (!parent || !child) - goto cleanup; + goto cleanup_free; if (cg_create(parent)) - goto cleanup; + goto cleanup_free; if (cg_write(parent, "cgroup.subtree_control", "+memory")) - goto cleanup; + goto cleanup_parent; if (cg_create(child)) - goto cleanup; + goto cleanup_parent; if (cg_read_strstr(child, "cgroup.controllers", "memory")) - goto cleanup; + goto cleanup_child; /* Create two nested cgroups without enabling memory controller */ parent2 = cg_name(root, "memcg_test_1"); child2 = cg_name(root, "memcg_test_1/memcg_test_1"); if (!parent2 || !child2) - goto cleanup; + goto cleanup_free2; if (cg_create(parent2)) - goto cleanup; + goto cleanup_free2; if (cg_create(child2)) - goto cleanup; + goto cleanup_parent2; if (cg_read(child2, "cgroup.controllers", buf, sizeof(buf))) - goto cleanup; + goto cleanup_all; if (!cg_read_strstr(child2, "cgroup.controllers", "memory")) - goto cleanup; + goto cleanup_all; ret = KSFT_PASS; -cleanup: - cg_destroy(child); - cg_destroy(parent); - free(parent); - free(child); - +cleanup_all: cg_destroy(child2); +cleanup_parent2: cg_destroy(parent2); +cleanup_free2: free(parent2); free(child2); +cleanup_child: + cg_destroy(child); +cleanup_parent: + cg_destroy(parent); +cleanup_free: + free(parent); + free(child); return ret; } diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh index a47029a799d2..a90f394f9aa9 100755 --- a/tools/testing/selftests/efivarfs/efivarfs.sh +++ b/tools/testing/selftests/efivarfs/efivarfs.sh @@ -7,6 +7,12 @@ test_guid=210be57c-9849-4fc7-a635-e6382d1aec27 # Kselftest framework requirement - SKIP code is 4. ksft_skip=4 +file_cleanup() +{ + chattr -i $1 + rm -f $1 +} + check_prereqs() { local msg="skip all tests:" @@ -58,8 +64,10 @@ test_create() if [ $(stat -c %s $file) -ne 5 ]; then echo "$file has invalid size" >&2 + file_cleanup $file exit 1 fi + file_cleanup $file } test_create_empty() @@ -72,12 +80,14 @@ test_create_empty() echo "$file can not be created without writing" >&2 exit 1 fi + file_cleanup $file } test_create_read() { local file=$efivarfs_mount/$FUNCNAME-$test_guid ./create-read $file + file_cleanup $file } test_delete() @@ -92,11 +102,7 @@ test_delete() exit 1 fi - rm $file 2>/dev/null - if [ $? -ne 0 ]; then - chattr -i $file - rm $file - fi + file_cleanup $file if [ -e $file ]; then echo "$file couldn't be deleted" >&2 @@ -150,11 +156,7 @@ test_valid_filenames() echo "$file could not be created" >&2 ret=1 else - rm $file 2>/dev/null - if [ $? -ne 0 ]; then - chattr -i $file - rm $file - fi + file_cleanup $file fi done @@ -187,11 +189,7 @@ test_invalid_filenames() if [ -e $file ]; then echo "Creating $file should have failed" >&2 - rm $file 2>/dev/null - if [ $? -ne 0 ]; then - chattr -i $file - rm $file - fi + file_cleanup $file ret=1 fi done diff --git a/tools/testing/selftests/gpio/gpio-mockup-chardev.c b/tools/testing/selftests/gpio/gpio-mockup-chardev.c index aaa1e9f083c3..d587c814a9ca 100644 --- a/tools/testing/selftests/gpio/gpio-mockup-chardev.c +++ b/tools/testing/selftests/gpio/gpio-mockup-chardev.c @@ -12,7 +12,6 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> -#include <stdio.h> #include <errno.h> #include <string.h> #include <fcntl.h> diff --git a/tools/testing/selftests/ima/config b/tools/testing/selftests/ima/config deleted file mode 100644 index 6bc86d4d9bb4..000000000000 --- a/tools/testing/selftests/ima/config +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_IMA_APPRAISE -CONFIG_IMA_ARCH_POLICY -CONFIG_SECURITYFS -CONFIG_KEXEC_VERIFY_SIG diff --git a/tools/testing/selftests/ima/test_kexec_load.sh b/tools/testing/selftests/ima/test_kexec_load.sh deleted file mode 100755 index 1c10093fb526..000000000000 --- a/tools/testing/selftests/ima/test_kexec_load.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0+ -# Loading a kernel image via the kexec_load syscall should fail -# when the kerne is CONFIG_KEXEC_VERIFY_SIG enabled and the system -# is booted in secureboot mode. - -TEST="$0" -EFIVARFS="/sys/firmware/efi/efivars" -rc=0 - -# Kselftest framework requirement - SKIP code is 4. -ksft_skip=4 - -# kexec requires root privileges -if [ $UID != 0 ]; then - echo "$TEST: must be run as root" >&2 - exit $ksft_skip -fi - -# Make sure that efivars is mounted in the normal location -if ! grep -q "^\S\+ $EFIVARFS efivarfs" /proc/mounts; then - echo "$TEST: efivars is not mounted on $EFIVARFS" >&2 - exit $ksft_skip -fi - -# Get secureboot mode -file="$EFIVARFS/SecureBoot-*" -if [ ! -e $file ]; then - echo "$TEST: unknown secureboot mode" >&2 - exit $ksft_skip -fi -secureboot=`hexdump $file | awk '{print substr($4,length($4),1)}'` - -# kexec_load should fail in secure boot mode -KERNEL_IMAGE="/boot/vmlinuz-`uname -r`" -kexec -l $KERNEL_IMAGE &>> /dev/null -if [ $? == 0 ]; then - kexec -u - if [ "$secureboot" == "1" ]; then - echo "$TEST: kexec_load succeeded [FAIL]" - rc=1 - else - echo "$TEST: kexec_load succeeded [PASS]" - fi -else - if [ "$secureboot" == "1" ]; then - echo "$TEST: kexec_load failed [PASS]" - else - echo "$TEST: kexec_load failed [FAIL]" - rc=1 - fi -fi - -exit $rc diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c index dac927e82336..4c156aeab6b8 100644 --- a/tools/testing/selftests/ipc/msgque.c +++ b/tools/testing/selftests/ipc/msgque.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> -#include <linux/msg.h> +#include <sys/msg.h> #include <fcntl.h> #include "../kselftest.h" @@ -73,7 +74,7 @@ int restore_queue(struct msgque_data *msgque) return 0; destroy: - if (msgctl(id, IPC_RMID, 0)) + if (msgctl(id, IPC_RMID, NULL)) printf("Failed to destroy queue: %d\n", -errno); return ret; } @@ -120,7 +121,7 @@ int check_and_destroy_queue(struct msgque_data *msgque) ret = 0; err: - if (msgctl(msgque->msq_id, IPC_RMID, 0)) { + if (msgctl(msgque->msq_id, IPC_RMID, NULL)) { printf("Failed to destroy queue: %d\n", -errno); return -errno; } @@ -129,7 +130,7 @@ err: int dump_queue(struct msgque_data *msgque) { - struct msqid64_ds ds; + struct msqid_ds ds; int kern_id; int i, ret; @@ -245,7 +246,7 @@ int main(int argc, char **argv) return ksft_exit_pass(); err_destroy: - if (msgctl(msgque.msq_id, IPC_RMID, 0)) { + if (msgctl(msgque.msq_id, IPC_RMID, NULL)) { printf("Failed to destroy queue: %d\n", -errno); return ksft_exit_fail(); } diff --git a/tools/testing/selftests/ima/Makefile b/tools/testing/selftests/kexec/Makefile index 0b3adf5444b6..8e9b27a7452f 100644 --- a/tools/testing/selftests/ima/Makefile +++ b/tools/testing/selftests/kexec/Makefile @@ -1,10 +1,11 @@ -# Makefile for kexec_load +# Makefile for kexec tests 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),x86) -TEST_PROGS := test_kexec_load.sh +TEST_PROGS := test_kexec_load.sh test_kexec_file_load.sh +TEST_FILES := kexec_common_lib.sh include ../lib.mk diff --git a/tools/testing/selftests/kexec/config b/tools/testing/selftests/kexec/config new file mode 100644 index 000000000000..8962e862b2b8 --- /dev/null +++ b/tools/testing/selftests/kexec/config @@ -0,0 +1,3 @@ +CONFIG_IMA_APPRAISE=y +CONFIG_IMA_ARCH_POLICY=y +CONFIG_SECURITYFS=y diff --git a/tools/testing/selftests/kexec/kexec_common_lib.sh b/tools/testing/selftests/kexec/kexec_common_lib.sh new file mode 100755 index 000000000000..43017cfe88f7 --- /dev/null +++ b/tools/testing/selftests/kexec/kexec_common_lib.sh @@ -0,0 +1,220 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Kselftest framework defines: ksft_pass=0, ksft_fail=1, ksft_skip=4 + +VERBOSE="${VERBOSE:-1}" +IKCONFIG="/tmp/config-`uname -r`" +KERNEL_IMAGE="/boot/vmlinuz-`uname -r`" +SECURITYFS=$(grep "securityfs" /proc/mounts | awk '{print $2}') + +log_info() +{ + [ $VERBOSE -ne 0 ] && echo "[INFO] $1" +} + +# The ksefltest framework requirement returns 0 for PASS. +log_pass() +{ + [ $VERBOSE -ne 0 ] && echo "$1 [PASS]" + exit 0 +} + +# The ksefltest framework requirement returns 1 for FAIL. +log_fail() +{ + [ $VERBOSE -ne 0 ] && echo "$1 [FAIL]" + exit 1 +} + +# The ksefltest framework requirement returns 4 for SKIP. +log_skip() +{ + [ $VERBOSE -ne 0 ] && echo "$1" + exit 4 +} + +# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID). +# (Based on kdump-lib.sh) +get_efivarfs_secureboot_mode() +{ + local efivarfs="/sys/firmware/efi/efivars" + local secure_boot_file="" + local setup_mode_file="" + local secureboot_mode=0 + local setup_mode=0 + + # Make sure that efivar_fs is mounted in the normal location + if ! grep -q "^\S\+ $efivarfs efivarfs" /proc/mounts; then + log_info "efivars is not mounted on $efivarfs" + return 0; + fi + secure_boot_file=$(find "$efivarfs" -name SecureBoot-* 2>/dev/null) + setup_mode_file=$(find "$efivarfs" -name SetupMode-* 2>/dev/null) + if [ -f "$secure_boot_file" ] && [ -f "$setup_mode_file" ]; then + secureboot_mode=$(hexdump -v -e '/1 "%d\ "' \ + "$secure_boot_file"|cut -d' ' -f 5) + setup_mode=$(hexdump -v -e '/1 "%d\ "' \ + "$setup_mode_file"|cut -d' ' -f 5) + + if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then + log_info "secure boot mode enabled (CONFIG_EFIVAR_FS)" + return 1; + fi + fi + return 0; +} + +get_efi_var_secureboot_mode() +{ + local efi_vars + local secure_boot_file + local setup_mode_file + local secureboot_mode + local setup_mode + + if [ ! -d "$efi_vars" ]; then + log_skip "efi_vars is not enabled\n" + fi + secure_boot_file=$(find "$efi_vars" -name SecureBoot-* 2>/dev/null) + setup_mode_file=$(find "$efi_vars" -name SetupMode-* 2>/dev/null) + if [ -f "$secure_boot_file/data" ] && \ + [ -f "$setup_mode_file/data" ]; then + secureboot_mode=`od -An -t u1 "$secure_boot_file/data"` + setup_mode=`od -An -t u1 "$setup_mode_file/data"` + + if [ $secureboot_mode -eq 1 ] && [ $setup_mode -eq 0 ]; then + log_info "secure boot mode enabled (CONFIG_EFI_VARS)" + return 1; + fi + fi + return 0; +} + +# Check efivar SecureBoot-$(the UUID) and SetupMode-$(the UUID). +# The secure boot mode can be accessed either as the last integer +# of "od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-*" or from +# "od -An -t u1 /sys/firmware/efi/vars/SecureBoot-*/data". The efi +# SetupMode can be similarly accessed. +# Return 1 for SecureBoot mode enabled and SetupMode mode disabled. +get_secureboot_mode() +{ + local secureboot_mode=0 + + get_efivarfs_secureboot_mode + secureboot_mode=$? + + # fallback to using the efi_var files + if [ $secureboot_mode -eq 0 ]; then + get_efi_var_secureboot_mode + secureboot_mode=$? + fi + + if [ $secureboot_mode -eq 0 ]; then + log_info "secure boot mode not enabled" + fi + return $secureboot_mode; +} + +require_root_privileges() +{ + if [ $(id -ru) -ne 0 ]; then + log_skip "requires root privileges" + fi +} + +# Look for config option in Kconfig file. +# Return 1 for found and 0 for not found. +kconfig_enabled() +{ + local config="$1" + local msg="$2" + + grep -E -q $config $IKCONFIG + if [ $? -eq 0 ]; then + log_info "$msg" + return 1 + fi + return 0 +} + +# Attempt to get the kernel config first via proc, and then by +# extracting it from the kernel image or the configs.ko using +# scripts/extract-ikconfig. +# Return 1 for found. +get_kconfig() +{ + local proc_config="/proc/config.gz" + local module_dir="/lib/modules/`uname -r`" + local configs_module="$module_dir/kernel/kernel/configs.ko" + + if [ ! -f $proc_config ]; then + modprobe configs > /dev/null 2>&1 + fi + if [ -f $proc_config ]; then + cat $proc_config | gunzip > $IKCONFIG 2>/dev/null + if [ $? -eq 0 ]; then + return 1 + fi + fi + + local extract_ikconfig="$module_dir/source/scripts/extract-ikconfig" + if [ ! -f $extract_ikconfig ]; then + log_skip "extract-ikconfig not found" + fi + + $extract_ikconfig $KERNEL_IMAGE > $IKCONFIG 2>/dev/null + if [ $? -eq 1 ]; then + if [ ! -f $configs_module ]; then + log_skip "CONFIG_IKCONFIG not enabled" + fi + $extract_ikconfig $configs_module > $IKCONFIG + if [ $? -eq 1 ]; then + log_skip "CONFIG_IKCONFIG not enabled" + fi + fi + return 1 +} + +# Make sure that securityfs is mounted +mount_securityfs() +{ + if [ -z $SECURITYFS ]; then + SECURITYFS=/sys/kernel/security + mount -t securityfs security $SECURITYFS + fi + + if [ ! -d "$SECURITYFS" ]; then + log_fail "$SECURITYFS :securityfs is not mounted" + fi +} + +# The policy rule format is an "action" followed by key-value pairs. This +# function supports up to two key-value pairs, in any order. +# For example: action func=<keyword> [appraise_type=<type>] +# Return 1 for found and 0 for not found. +check_ima_policy() +{ + local action="$1" + local keypair1="$2" + local keypair2="$3" + local ret=0 + + mount_securityfs + + local ima_policy=$SECURITYFS/ima/policy + if [ ! -e $ima_policy ]; then + log_fail "$ima_policy not found" + fi + + if [ -n $keypair2 ]; then + grep -e "^$action.*$keypair1" "$ima_policy" | \ + grep -q -e "$keypair2" + else + grep -q -e "^$action.*$keypair1" "$ima_policy" + fi + + # invert "grep -q" result, returning 1 for found. + [ $? -eq 0 ] && ret=1 + return $ret +} diff --git a/tools/testing/selftests/kexec/test_kexec_file_load.sh b/tools/testing/selftests/kexec/test_kexec_file_load.sh new file mode 100755 index 000000000000..fa7c24e8eefb --- /dev/null +++ b/tools/testing/selftests/kexec/test_kexec_file_load.sh @@ -0,0 +1,208 @@ +#!/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. + if [ $ima_read_policy -eq 1 ]; then + check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ + "appraise_type=imasig" + ret=$? + [ $ret -eq 1 ] && log_info "IMA signature required"; + 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 +} + +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 ]; 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 ]; 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=$? + |
