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
41	# First check for appended signature (modsig), then xattr
42	if [ $ima_read_policy -eq 1 ]; then
43		check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \
44			"appraise_type=imasig|modsig"
45		ret=$?
46		if [ $ret -eq 1 ]; then
47			log_info "IMA or appended(modsig) signature required"
48		else
49			check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \
50				"appraise_type=imasig"
51			ret=$?
52			[ $ret -eq 1 ] && log_info "IMA signature required";
53		fi
54	fi
55	return $ret
56}
57
58# The kexec_file_load_test() is complicated enough, require pesign.
59# Return 1 for PE signature found and 0 for not found.
60check_for_pesig()
61{
62	which pesign > /dev/null 2>&1 || log_skip "pesign not found"
63
64	pesign -i $KERNEL_IMAGE --show-signature | grep -q "No signatures"
65	local ret=$?
66	if [ $ret -eq 1 ]; then
67		log_info "kexec kernel image PE signed"
68	else
69		log_info "kexec kernel image not PE signed"
70	fi
71	return $ret
72}
73
74# The kexec_file_load_test() is complicated enough, require getfattr.
75# Return 1 for IMA signature found and 0 for not found.
76check_for_imasig()
77{
78	local ret=0
79
80	which getfattr > /dev/null 2>&1
81	if [ $?	-eq 1 ]; then
82		log_skip "getfattr not found"
83	fi
84
85	line=$(getfattr -n security.ima -e hex --absolute-names $KERNEL_IMAGE 2>&1)
86	echo $line | grep -q "security.ima=0x03"
87	if [ $? -eq 0 ]; then
88		ret=1
89		log_info "kexec kernel image IMA signed"
90	else
91		log_info "kexec kernel image not IMA signed"
92	fi
93	return $ret
94}
95
96# Return 1 for appended signature (modsig) found and 0 for not found.
97check_for_modsig()
98{
99	local module_sig_string="~Module signature appended~"
100	local sig="$(tail --bytes $((${#module_sig_string} + 1)) $KERNEL_IMAGE)"
101	local ret=0
102
103	if [ "$sig" == "$module_sig_string" ]; then
104		ret=1
105		log_info "kexec kernel image modsig signed"
106	else
107		log_info "kexec kernel image not modsig signed"
108	fi
109	return $ret
110}
111
112kexec_file_load_test()
113{
114	local succeed_msg="kexec_file_load succeeded"
115	local failed_msg="kexec_file_load failed"
116	local key_msg="try enabling the CONFIG_INTEGRITY_PLATFORM_KEYRING"
117
118	line=$(kexec --load --kexec-file-syscall $KERNEL_IMAGE 2>&1)
119
120	if [ $? -eq 0 ]; then
121		kexec --unload --kexec-file-syscall
122
123		# In secureboot mode with an architecture  specific
124		# policy, make sure either an IMA or PE signature exists.
125		if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \
126			[ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ] \
127			  && [ $ima_modsig -eq 0 ]; then
128			log_fail "$succeed_msg (missing sig)"
129		fi
130
131		if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \
132		     && [ $pe_signed -eq 0 ]; then
133			log_fail "$succeed_msg (missing PE sig)"
134		fi
135
136		if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ] \
137		     && [ $ima_modsig -eq 0 ]; then
138			log_fail "$succeed_msg (missing IMA sig)"
139		fi
140
141		if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
142		    && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \
143	            && [ $ima_read_policy -eq 0 ]; then
144			log_fail "$succeed_msg (possibly missing IMA sig)"
145		fi
146
147		if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 0 ]; then
148			log_info "No signature verification required"
149		elif [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
150		    && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \
151	            && [ $ima_read_policy -eq 1 ]; then
152			log_info "No signature verification required"
153		fi
154
155		log_pass "$succeed_msg"
156	fi
157
158	# Check the reason for the kexec_file_load failure
159	echo $line | grep -q "Required key not available"
160	if [ $? -eq 0 ]; then
161		if [ $platform_keyring -eq 0 ]; then
162			log_pass "$failed_msg (-ENOKEY), $key_msg"
163		else
164			log_pass "$failed_msg (-ENOKEY)"
165		fi
166	fi
167
168	if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \
169	     && [ $pe_signed -eq 0 ]; then
170		log_pass "$failed_msg (missing PE sig)"
171	fi
172
173	if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then
174		log_pass "$failed_msg (missing IMA sig)"
175	fi
176
177	if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \
178	    && [ $ima_sig_required -eq 0 ] && [ $ima_read_policy -eq 0 ] \
179	    && [ $ima_signed -eq 0 ]; then
180		log_pass "$failed_msg (possibly missing IMA sig)"
181	fi
182
183	log_pass "$failed_msg"
184	return 0
185}
186
187# kexec requires root privileges
188require_root_privileges
189
190# get the kernel config
191get_kconfig
192
193kconfig_enabled "CONFIG_KEXEC_FILE=y" "kexec_file_load is enabled"
194if [ $? -eq 0 ]; then
195	log_skip "kexec_file_load is not enabled"
196fi
197
198# Determine which kernel config options are enabled
199kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled"
200ima_appraise=$?
201
202kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \
203	"architecture specific policy enabled"
204arch_policy=$?
205
206kconfig_enabled "CONFIG_INTEGRITY_PLATFORM_KEYRING=y" \
207	"platform keyring enabled"
208platform_keyring=$?
209
210kconfig_enabled "CONFIG_IMA_READ_POLICY=y" "reading IMA policy permitted"
211ima_read_policy=$?
212
213kconfig_enabled "CONFIG_KEXEC_SIG_FORCE=y" \
214	"kexec signed kernel image required"
215kexec_sig_required=$?
216
217kconfig_enabled "CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y" \
218	"PE signed kernel image required"
219pe_sig_required=$?
220
221is_ima_sig_required
222ima_sig_required=$?
223
224get_secureboot_mode
225secureboot=$?
226
227# Are there pe and ima signatures
228check_for_pesig
229pe_signed=$?
230
231check_for_imasig
232ima_signed=$?
233
234check_for_modsig
235ima_modsig=$?
236
237# Test loading the kernel image via kexec_file_load syscall
238kexec_file_load_test
239