diff options
Diffstat (limited to 'meta/recipes-bsp/grub/files/CVE-2022-28735.patch')
-rw-r--r-- | meta/recipes-bsp/grub/files/CVE-2022-28735.patch | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/meta/recipes-bsp/grub/files/CVE-2022-28735.patch b/meta/recipes-bsp/grub/files/CVE-2022-28735.patch new file mode 100644 index 0000000000..89b653a8da --- /dev/null +++ b/meta/recipes-bsp/grub/files/CVE-2022-28735.patch | |||
@@ -0,0 +1,271 @@ | |||
1 | From 6fe755c5c07bb386fda58306bfd19e4a1c974c53 Mon Sep 17 00:00:00 2001 | ||
2 | From: Julian Andres Klode <julian.klode@canonical.com> | ||
3 | Date: Thu, 2 Dec 2021 15:03:53 +0100 | ||
4 | Subject: kern/efi/sb: Reject non-kernel files in the shim_lock verifier | ||
5 | |||
6 | Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/grub.git/commit/?id=6fe755c5c07bb386fda58306bfd19e4a1c974c53] | ||
7 | CVE: CVE-2022-28735 | ||
8 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
9 | |||
10 | We must not allow other verifiers to pass things like the GRUB modules. | ||
11 | Instead of maintaining a blocklist, maintain an allowlist of things | ||
12 | that we do not care about. | ||
13 | |||
14 | This allowlist really should be made reusable, and shared by the | ||
15 | lockdown verifier, but this is the minimal patch addressing | ||
16 | security concerns where the TPM verifier was able to mark modules | ||
17 | as verified (or the OpenPGP verifier for that matter), when it | ||
18 | should not do so on shim-powered secure boot systems. | ||
19 | |||
20 | Fixes: CVE-2022-28735 | ||
21 | |||
22 | Signed-off-by: Julian Andres Klode <julian.klode@canonical.com> | ||
23 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | ||
24 | --- | ||
25 | grub-core/kern/efi/sb.c | 221 ++++++++++++++++++++++++++++++++++++++++ | ||
26 | include/grub/verify.h | 1 + | ||
27 | 2 files changed, 222 insertions(+) | ||
28 | create mode 100644 grub-core/kern/efi/sb.c | ||
29 | |||
30 | diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c | ||
31 | new file mode 100644 | ||
32 | index 0000000..89c4bb3 | ||
33 | --- /dev/null | ||
34 | +++ b/grub-core/kern/efi/sb.c | ||
35 | @@ -0,0 +1,221 @@ | ||
36 | +/* | ||
37 | + * GRUB -- GRand Unified Bootloader | ||
38 | + * Copyright (C) 2020 Free Software Foundation, Inc. | ||
39 | + * | ||
40 | + * GRUB is free software: you can redistribute it and/or modify | ||
41 | + * it under the terms of the GNU General Public License as published by | ||
42 | + * the Free Software Foundation, either version 3 of the License, or | ||
43 | + * (at your option) any later version. | ||
44 | + * | ||
45 | + * GRUB is distributed in the hope that it will be useful, | ||
46 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
47 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
48 | + * GNU General Public License for more details. | ||
49 | + * | ||
50 | + * You should have received a copy of the GNU General Public License | ||
51 | + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | ||
52 | + * | ||
53 | + * UEFI Secure Boot related checkings. | ||
54 | + */ | ||
55 | + | ||
56 | +#include <grub/efi/efi.h> | ||
57 | +#include <grub/efi/pe32.h> | ||
58 | +#include <grub/efi/sb.h> | ||
59 | +#include <grub/env.h> | ||
60 | +#include <grub/err.h> | ||
61 | +#include <grub/file.h> | ||
62 | +#include <grub/i386/linux.h> | ||
63 | +#include <grub/kernel.h> | ||
64 | +#include <grub/mm.h> | ||
65 | +#include <grub/types.h> | ||
66 | +#include <grub/verify.h> | ||
67 | + | ||
68 | +static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID; | ||
69 | + | ||
70 | +/* | ||
71 | + * Determine whether we're in secure boot mode. | ||
72 | + * | ||
73 | + * Please keep the logic in sync with the Linux kernel, | ||
74 | + * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot(). | ||
75 | + */ | ||
76 | +grub_uint8_t | ||
77 | +grub_efi_get_secureboot (void) | ||
78 | +{ | ||
79 | + static grub_efi_guid_t efi_variable_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; | ||
80 | + grub_efi_status_t status; | ||
81 | + grub_efi_uint32_t attr = 0; | ||
82 | + grub_size_t size = 0; | ||
83 | + grub_uint8_t *secboot = NULL; | ||
84 | + grub_uint8_t *setupmode = NULL; | ||
85 | + grub_uint8_t *moksbstate = NULL; | ||
86 | + grub_uint8_t secureboot = GRUB_EFI_SECUREBOOT_MODE_UNKNOWN; | ||
87 | + const char *secureboot_str = "UNKNOWN"; | ||
88 | + | ||
89 | + status = grub_efi_get_variable ("SecureBoot", &efi_variable_guid, | ||
90 | + &size, (void **) &secboot); | ||
91 | + | ||
92 | + if (status == GRUB_EFI_NOT_FOUND) | ||
93 | + { | ||
94 | + secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED; | ||
95 | + goto out; | ||
96 | + } | ||
97 | + | ||
98 | + if (status != GRUB_EFI_SUCCESS) | ||
99 | + goto out; | ||
100 | + | ||
101 | + status = grub_efi_get_variable ("SetupMode", &efi_variable_guid, | ||
102 | + &size, (void **) &setupmode); | ||
103 | + | ||
104 | + if (status != GRUB_EFI_SUCCESS) | ||
105 | + goto out; | ||
106 | + | ||
107 | + if ((*secboot == 0) || (*setupmode == 1)) | ||
108 | + { | ||
109 | + secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED; | ||
110 | + goto out; | ||
111 | + } | ||
112 | + | ||
113 | + /* | ||
114 | + * See if a user has put the shim into insecure mode. If so, and if the | ||
115 | + * variable doesn't have the runtime attribute set, we might as well | ||
116 | + * honor that. | ||
117 | + */ | ||
118 | + status = grub_efi_get_variable_with_attributes ("MokSBState", &shim_lock_guid, | ||
119 | + &size, (void **) &moksbstate, &attr); | ||
120 | + | ||
121 | + /* If it fails, we don't care why. Default to secure. */ | ||
122 | + if (status != GRUB_EFI_SUCCESS) | ||
123 | + { | ||
124 | + secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED; | ||
125 | + goto out; | ||
126 | + } | ||
127 | + | ||
128 | + if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1) | ||
129 | + { | ||
130 | + secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED; | ||
131 | + goto out; | ||
132 | + } | ||
133 | + | ||
134 | + secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED; | ||
135 | + | ||
136 | + out: | ||
137 | + grub_free (moksbstate); | ||
138 | + grub_free (setupmode); | ||
139 | + grub_free (secboot); | ||
140 | + | ||
141 | + if (secureboot == GRUB_EFI_SECUREBOOT_MODE_DISABLED) | ||
142 | + secureboot_str = "Disabled"; | ||
143 | + else if (secureboot == GRUB_EFI_SECUREBOOT_MODE_ENABLED) | ||
144 | + secureboot_str = "Enabled"; | ||
145 | + | ||
146 | + grub_dprintf ("efi", "UEFI Secure Boot state: %s\n", secureboot_str); | ||
147 | + | ||
148 | + return secureboot; | ||
149 | +} | ||
150 | + | ||
151 | +static grub_err_t | ||
152 | +shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), | ||
153 | + enum grub_file_type type, | ||
154 | + void **context __attribute__ ((unused)), | ||
155 | + enum grub_verify_flags *flags) | ||
156 | +{ | ||
157 | + *flags = GRUB_VERIFY_FLAGS_NONE; | ||
158 | + | ||
159 | + switch (type & GRUB_FILE_TYPE_MASK) | ||
160 | + { | ||
161 | + /* Files we check. */ | ||
162 | + case GRUB_FILE_TYPE_LINUX_KERNEL: | ||
163 | + case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: | ||
164 | + case GRUB_FILE_TYPE_BSD_KERNEL: | ||
165 | + case GRUB_FILE_TYPE_XNU_KERNEL: | ||
166 | + case GRUB_FILE_TYPE_PLAN9_KERNEL: | ||
167 | + case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: | ||
168 | + *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; | ||
169 | + return GRUB_ERR_NONE; | ||
170 | + | ||
171 | + /* Files that do not affect secureboot state. */ | ||
172 | + case GRUB_FILE_TYPE_NONE: | ||
173 | + case GRUB_FILE_TYPE_LOOPBACK: | ||
174 | + case GRUB_FILE_TYPE_LINUX_INITRD: | ||
175 | + case GRUB_FILE_TYPE_OPENBSD_RAMDISK: | ||
176 | + case GRUB_FILE_TYPE_XNU_RAMDISK: | ||
177 | + case GRUB_FILE_TYPE_SIGNATURE: | ||
178 | + case GRUB_FILE_TYPE_PUBLIC_KEY: | ||
179 | + case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST: | ||
180 | + case GRUB_FILE_TYPE_PRINT_BLOCKLIST: | ||
181 | + case GRUB_FILE_TYPE_TESTLOAD: | ||
182 | + case GRUB_FILE_TYPE_GET_SIZE: | ||
183 | + case GRUB_FILE_TYPE_FONT: | ||
184 | + case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: | ||
185 | + case GRUB_FILE_TYPE_CAT: | ||
186 | + case GRUB_FILE_TYPE_HEXCAT: | ||
187 | + case GRUB_FILE_TYPE_CMP: | ||
188 | + case GRUB_FILE_TYPE_HASHLIST: | ||
189 | + case GRUB_FILE_TYPE_TO_HASH: | ||
190 | + case GRUB_FILE_TYPE_KEYBOARD_LAYOUT: | ||
191 | + case GRUB_FILE_TYPE_PIXMAP: | ||
192 | + case GRUB_FILE_TYPE_GRUB_MODULE_LIST: | ||
193 | + case GRUB_FILE_TYPE_CONFIG: | ||
194 | + case GRUB_FILE_TYPE_THEME: | ||
195 | + case GRUB_FILE_TYPE_GETTEXT_CATALOG: | ||
196 | + case GRUB_FILE_TYPE_FS_SEARCH: | ||
197 | + case GRUB_FILE_TYPE_LOADENV: | ||
198 | + case GRUB_FILE_TYPE_SAVEENV: | ||
199 | + case GRUB_FILE_TYPE_VERIFY_SIGNATURE: | ||
200 | + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; | ||
201 | + return GRUB_ERR_NONE; | ||
202 | + | ||
203 | + /* Other files. */ | ||
204 | + default: | ||
205 | + return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy")); | ||
206 | + } | ||
207 | +} | ||
208 | + | ||
209 | +static grub_err_t | ||
210 | +shim_lock_verifier_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size) | ||
211 | +{ | ||
212 | + grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0); | ||
213 | + | ||
214 | + if (!sl) | ||
215 | + return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found")); | ||
216 | + | ||
217 | + if (sl->verify (buf, size) != GRUB_EFI_SUCCESS) | ||
218 | + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature")); | ||
219 | + | ||
220 | + return GRUB_ERR_NONE; | ||
221 | +} | ||
222 | + | ||
223 | +struct grub_file_verifier shim_lock_verifier = | ||
224 | + { | ||
225 | + .name = "shim_lock_verifier", | ||
226 | + .init = shim_lock_verifier_init, | ||
227 | + .write = shim_lock_verifier_write | ||
228 | + }; | ||
229 | + | ||
230 | +void | ||
231 | +grub_shim_lock_verifier_setup (void) | ||
232 | +{ | ||
233 | + struct grub_module_header *header; | ||
234 | + grub_efi_shim_lock_protocol_t *sl = | ||
235 | + grub_efi_locate_protocol (&shim_lock_guid, 0); | ||
236 | + | ||
237 | + /* shim_lock is missing, check if GRUB image is built with --disable-shim-lock. */ | ||
238 | + if (!sl) | ||
239 | + { | ||
240 | + FOR_MODULES (header) | ||
241 | + { | ||
242 | + if (header->type == OBJ_TYPE_DISABLE_SHIM_LOCK) | ||
243 | + return; | ||
244 | + } | ||
245 | + } | ||
246 | + | ||
247 | + /* Secure Boot is off. Do not load shim_lock. */ | ||
248 | + if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED) | ||
249 | + return; | ||
250 | + | ||
251 | + /* Enforce shim_lock_verifier. */ | ||
252 | + grub_verifier_register (&shim_lock_verifier); | ||
253 | + | ||
254 | + grub_env_set ("shim_lock", "y"); | ||
255 | + grub_env_export ("shim_lock"); | ||
256 | +} | ||
257 | diff --git a/include/grub/verify.h b/include/grub/verify.h | ||
258 | index cd129c3..672ae16 100644 | ||
259 | --- a/include/grub/verify.h | ||
260 | +++ b/include/grub/verify.h | ||
261 | @@ -24,6 +24,7 @@ | ||
262 | |||
263 | enum grub_verify_flags | ||
264 | { | ||
265 | + GRUB_VERIFY_FLAGS_NONE = 0, | ||
266 | GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1, | ||
267 | GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2, | ||
268 | /* Defer verification to another authority. */ | ||
269 | -- | ||
270 | 2.25.1 | ||
271 | |||