Commit | Line | Data |
---|---|---|
973b71c6 MZ |
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 | ||
13 | TEST="KEXEC_FILE_LOAD" | |
14 | . ./kexec_common_lib.sh | |
15 | ||
16 | trap "{ 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. | |
24 | is_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. | |
cbc0425d MZ |
40 | |
41 | # First check for appended signature (modsig), then xattr | |
973b71c6 MZ |
42 | if [ $ima_read_policy -eq 1 ]; then |
43 | check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ | |
cbc0425d | 44 | "appraise_type=imasig|modsig" |
973b71c6 | 45 | ret=$? |
cbc0425d MZ |
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 | |
973b71c6 MZ |
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. | |
60 | check_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. | |
76 | check_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 | ||
cbc0425d MZ |
96 | # Return 1 for appended signature (modsig) found and 0 for not found. |
97 | check_for_modsig() | |
98 | { | |
99 | local module_sig_string="~Module signature appended~" | |
cbc0425d MZ |
100 | local ret=0 |
101 | ||
cef5cd25 MZ |
102 | tail --bytes $((${#module_sig_string} + 1)) $KERNEL_IMAGE | \ |
103 | grep -q "$module_sig_string" | |
104 | if [ $? -eq 0 ]; then | |
cbc0425d MZ |
105 | ret=1 |
106 | log_info "kexec kernel image modsig signed" | |
107 | else | |
108 | log_info "kexec kernel image not modsig signed" | |
109 | fi | |
110 | return $ret | |
111 | } | |
112 | ||
973b71c6 MZ |
113 | kexec_file_load_test() |
114 | { | |
115 | local succeed_msg="kexec_file_load succeeded" | |
116 | local failed_msg="kexec_file_load failed" | |
117 | local key_msg="try enabling the CONFIG_INTEGRITY_PLATFORM_KEYRING" | |
118 | ||
119 | line=$(kexec --load --kexec-file-syscall $KERNEL_IMAGE 2>&1) | |
120 | ||
121 | if [ $? -eq 0 ]; then | |
122 | kexec --unload --kexec-file-syscall | |
123 | ||
124 | # In secureboot mode with an architecture specific | |
125 | # policy, make sure either an IMA or PE signature exists. | |
126 | if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \ | |
cbc0425d MZ |
127 | [ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ] \ |
128 | && [ $ima_modsig -eq 0 ]; then | |
973b71c6 MZ |
129 | log_fail "$succeed_msg (missing sig)" |
130 | fi | |
131 | ||
132 | if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \ | |
133 | && [ $pe_signed -eq 0 ]; then | |
134 | log_fail "$succeed_msg (missing PE sig)" | |
135 | fi | |
136 | ||
cbc0425d MZ |
137 | if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ] \ |
138 | && [ $ima_modsig -eq 0 ]; then | |
973b71c6 MZ |
139 | log_fail "$succeed_msg (missing IMA sig)" |
140 | fi | |
141 | ||
142 | if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ | |
143 | && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \ | |
144 | && [ $ima_read_policy -eq 0 ]; then | |
145 | log_fail "$succeed_msg (possibly missing IMA sig)" | |
146 | fi | |
147 | ||
148 | if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 0 ]; then | |
149 | log_info "No signature verification required" | |
150 | elif [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ | |
151 | && [ $ima_sig_required -eq 0 ] && [ $ima_signed -eq 0 ] \ | |
152 | && [ $ima_read_policy -eq 1 ]; then | |
153 | log_info "No signature verification required" | |
154 | fi | |
155 | ||
156 | log_pass "$succeed_msg" | |
157 | fi | |
158 | ||
159 | # Check the reason for the kexec_file_load failure | |
160 | echo $line | grep -q "Required key not available" | |
161 | if [ $? -eq 0 ]; then | |
162 | if [ $platform_keyring -eq 0 ]; then | |
163 | log_pass "$failed_msg (-ENOKEY), $key_msg" | |
164 | else | |
165 | log_pass "$failed_msg (-ENOKEY)" | |
166 | fi | |
167 | fi | |
168 | ||
169 | if [ $kexec_sig_required -eq 1 -o $pe_sig_required -eq 1 ] \ | |
170 | && [ $pe_signed -eq 0 ]; then | |
171 | log_pass "$failed_msg (missing PE sig)" | |
172 | fi | |
173 | ||
174 | if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then | |
175 | log_pass "$failed_msg (missing IMA sig)" | |
176 | fi | |
177 | ||
178 | if [ $pe_sig_required -eq 0 ] && [ $ima_appraise -eq 1 ] \ | |
179 | && [ $ima_sig_required -eq 0 ] && [ $ima_read_policy -eq 0 ] \ | |
180 | && [ $ima_signed -eq 0 ]; then | |
181 | log_pass "$failed_msg (possibly missing IMA sig)" | |
182 | fi | |
183 | ||
184 | log_pass "$failed_msg" | |
185 | return 0 | |
186 | } | |
187 | ||
188 | # kexec requires root privileges | |
189 | require_root_privileges | |
190 | ||
191 | # get the kernel config | |
192 | get_kconfig | |
193 | ||
7cea0b92 MZ |
194 | kconfig_enabled "CONFIG_KEXEC_FILE=y" "kexec_file_load is enabled" |
195 | if [ $? -eq 0 ]; then | |
196 | log_skip "kexec_file_load is not enabled" | |
197 | fi | |
198 | ||
973b71c6 MZ |
199 | # Determine which kernel config options are enabled |
200 | kconfig_enabled "CONFIG_IMA_APPRAISE=y" "IMA enabled" | |
201 | ima_appraise=$? | |
202 | ||
203 | kconfig_enabled "CONFIG_IMA_ARCH_POLICY=y" \ | |
204 | "architecture specific policy enabled" | |
205 | arch_policy=$? | |
206 | ||
207 | kconfig_enabled "CONFIG_INTEGRITY_PLATFORM_KEYRING=y" \ | |
208 | "platform keyring enabled" | |
209 | platform_keyring=$? | |
210 | ||
211 | kconfig_enabled "CONFIG_IMA_READ_POLICY=y" "reading IMA policy permitted" | |
212 | ima_read_policy=$? | |
213 | ||
214 | kconfig_enabled "CONFIG_KEXEC_SIG_FORCE=y" \ | |
215 | "kexec signed kernel image required" | |
216 | kexec_sig_required=$? | |
217 | ||
218 | kconfig_enabled "CONFIG_KEXEC_BZIMAGE_VERIFY_SIG=y" \ | |
219 | "PE signed kernel image required" | |
220 | pe_sig_required=$? | |
221 | ||
222 | is_ima_sig_required | |
223 | ima_sig_required=$? | |
224 | ||
225 | get_secureboot_mode | |
226 | secureboot=$? | |
227 | ||
228 | # Are there pe and ima signatures | |
229 | check_for_pesig | |
230 | pe_signed=$? | |
231 | ||
232 | check_for_imasig | |
233 | ima_signed=$? | |
234 | ||
cbc0425d MZ |
235 | check_for_modsig |
236 | ima_modsig=$? | |
237 | ||
973b71c6 MZ |
238 | # Test loading the kernel image via kexec_file_load syscall |
239 | kexec_file_load_test |