1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3#
4# Loading a kernel image via the kexec_file_load syscall can verify either
5# the IMA signature stored in the security.ima xattr or the PE signature,
6# both signatures depending on the IMA policy, or none.
7#
8# To determine whether the kernel image is signed, this test depends
9# on pesign and getfattr.  This test also requires the kernel to be
10# built with CONFIG_IKCONFIG enabled and either CONFIG_IKCONFIG_PROC
11# enabled or access to the extract-ikconfig script.
12
13TEST="KEXEC_FILE_LOAD"
14. ./kexec_common_lib.sh
15
16trap "{ rm -f $IKCONFIG ; }" EXIT
17
18# Some of the IMA builtin policies may require the kexec kernel image to
19# be signed, but these policy rules may be replaced with a custom
20# policy.  Only CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS persists after
21# loading a custom policy.  Check if it is enabled, before reading the
22# IMA runtime sysfs policy file.
23# Return 1 for IMA signature required and 0 for not required.
24is_ima_sig_required()
25{
26	local ret=0
27
28	kconfig_enabled "CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS=y" \
29		"IMA kernel image signature required"
30	if [ $? -eq 1 ]; then
31		log_info "IMA signature required"
32		return 1
33	fi
34
35	# The architecture specific or a custom policy may require the
36	# kexec kernel image be signed.  Policy rules are walked
37	# sequentially.  As a result, a policy rule may be defined, but
38	# might not necessarily be used.  This test assumes if a policy
39	# rule is specified, that is the intent.
40	if [ $ima_read_policy -eq 1 ]; then
41		check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \
42			"appraise_type=imasig"
43		ret=$?
44		[ $ret -eq 1 ] && log_info "IMA signature required";
45	fi
46	return $ret
47}
48
49# The kexec_file_load_test() is complicated enough, require pesign.
50# Return 1 for PE signature found and 0 for not found.
51check_for_pesig()
52{
53	which pesign > /dev/null 2>&1 || log_skip "pesign not found"
54
55	pesign -i $KERNEL_IMAGE --show-signature | grep -q "No signatures"
56	local ret=$?
57	if [ $ret -eq 1 ]; then
58		log_info "kexec kernel image PE signed"
59	else
60		log_info "kexec kernel image not PE signed"
61	fi
62	return $ret
63}
64
65# The kexec_file_load_test() is complicated enough, require getfattr.
66# Return 1 for IMA signature found and 0 for not found.
67check_for_imasig()
68{
69	local ret=0
70
71	which getfattr > /dev/null 2>&1
72	if [ $?	-eq 1 ]; then
73		log_skip "getfattr not found"
74	fi
75
76	line=$(getfattr -n security.ima -e hex --absolute-names $KERNEL_IMAGE 2>&1)
77	echo $line | grep -q "security.ima=0x03"
78	if [ $? -eq 0 ]; then
79		ret=1
80		log_info "kexec kernel image IMA signed"
81	else
82		log_info "kexec kernel image not IMA signed"
83	fi
84	return $ret
85}
86
87kexec_file_load_test()
88{
89	local succeed_msg="kexec_file_load succeeded"
90	local failed_msg="kexec_file_load failed"
91	local key_msg="try enabling the CONFIG_INTEGRITY_PLATFORM_KEYRING"
92
93	line=$(kexec --load --kexec-file-syscall $KERNEL_IMAGE 2>&1)
94
95	if [ $? -eq 0 ]; then
96		kexec --unload --kexec-file-syscall
97
98		# In secureboot mode with an architecture  specific
99		# policy, make sure either an IMA or PE signature exists.
100		if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \
101			[ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ]; then
102			log_fail "$succeed_msg (missing sig)"
103		fi
104
105		if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \
106		     && [ $pe_signed -eq 0 ]; then
107			log_fail "$succeed_msg (missing PE sig)"
108		fi
109
110		if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then
111			log_fail "$succeed_msg (missing IMA sig)"
112		fi
113
114		if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
115		    && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \
116	            && [ $ima_read_policy -eq 0 ]; then
117			log_fail "$succeed_msg (possibly missing IMA sig)"
118		fi
119
120		if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 0 ]; then
121			log_info "No signature verification required"
122		elif [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
123		    && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \
124	            && [ $ima_read_policy -eq 1 ]; then
125			log_info "No signature verification required"
126		fi
127
128		log_pass "$succeed_msg"
129	fi
130
131	# Check the reason for the kexec_file_load failure
132	echo $line | grep -q "Required key not available"
133	if [ $? -eq 0 ]; then
134		if [ $platform_keyring -eq 0 ]; then
135			log_pass "$failed_msg (-ENOKEY), $key_msg"
136		else
137			log_pass "$failed_msg (-ENOKEY)"
138		fi
139	fi
140
141	if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \
142	     && [ $pe_signed -eq 0 ]; then
143		log_pass "$failed_msg (missing PE sig)"
144	fi
145
146	if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then
147		log_pass "$failed_msg (missing IMA sig)"
148	fi
149
150	if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
151	    && [ $ima_sig_required -eq 0 ] && [ $ima_read_policy -eq 0 ] \
152	    && [ $ima_signed -eq 0 ]; then
153		log_pass "$failed_msg (possibly missing IMA sig)"
154	fi
155
156	log_pass "$failed_msg"
157	return 0
158}
159
160# kexec requires root privileges
161require_root_privileges
162
163# get the kernel config
164get_kconfig
165
166# Determine which kernel config options are enabled
167kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled"
168ima_appraise=$?
169
170kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \
171	"architecture specific policy enabled"
172arch_policy=$?
173
174kconfig_enabled "CONFIG_INTEGRITY_PLATFORM_KEYRING=y" \
175	"platform keyring enabled"
176platform_keyring=$?
177
178kconfig_enabled "CONFIG_IMA_READ_POLICY=y" "reading IMA policy permitted"
179ima_read_policy=$?
180
181kconfig_enabled "CONFIG_KEXEC_SIG_FORCE=y" \
182	"kexec signed kernel image required"
183kexec_sig_required=$?
184
185kconfig_enabled "CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y" \
186	"PE signed kernel image required"
187pe_sig_required=$?
188
189is_ima_sig_required
190ima_sig_required=$?
191
192get_secureboot_mode
193secureboot=$?
194
195# Are there pe and ima signatures
196check_for_pesig
197pe_signed=$?
198
199check_for_imasig
200ima_signed=$?
201
202# Test loading the kernel image via kexec_file_load syscall
203kexec_file_load_test
204