diff options
Diffstat (limited to 'meta/recipes-bsp/grub/files/CVE-2022-28736.patch')
-rw-r--r-- | meta/recipes-bsp/grub/files/CVE-2022-28736.patch | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/meta/recipes-bsp/grub/files/CVE-2022-28736.patch b/meta/recipes-bsp/grub/files/CVE-2022-28736.patch new file mode 100644 index 0000000000..4fc9fdaf05 --- /dev/null +++ b/meta/recipes-bsp/grub/files/CVE-2022-28736.patch | |||
@@ -0,0 +1,275 @@ | |||
1 | From 431a111c60095fc973d83fe9209f26f29ce78784 Mon Sep 17 00:00:00 2001 | ||
2 | From: Hitendra Prajapati <hprajapati@mvista.com> | ||
3 | Date: Mon, 1 Aug 2022 11:17:17 +0530 | ||
4 | Subject: [PATCH] CVE-2022-28736 | ||
5 | |||
6 | Upstream-Status: Backport [https://git.savannah.gnu.org/gitweb/?p=grub.git;a=commit;h=04c86e0bb7b58fc2f913f798cdb18934933e532d] | ||
7 | CVE: CVE-2022-28736 | ||
8 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
9 | |||
10 | loader/efi/chainloader: Use grub_loader_set_ex() | ||
11 | |||
12 | This ports the EFI chainloader to use grub_loader_set_ex() in order to fix | ||
13 | a use-after-free bug that occurs when grub_cmd_chainloader() is executed | ||
14 | more than once before a boot attempt is performed. | ||
15 | |||
16 | Fixes: CVE-2022-28736 | ||
17 | |||
18 | Signed-off-by: Chris Coulson <chris.coulson@canonical.com> | ||
19 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | ||
20 | --- | ||
21 | grub-core/commands/boot.c | 66 ++++++++++++++++++++++++++---- | ||
22 | grub-core/loader/efi/chainloader.c | 46 +++++++++++---------- | ||
23 | include/grub/loader.h | 5 +++ | ||
24 | 3 files changed, 87 insertions(+), 30 deletions(-) | ||
25 | |||
26 | diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c | ||
27 | index bbca81e..6151478 100644 | ||
28 | --- a/grub-core/commands/boot.c | ||
29 | +++ b/grub-core/commands/boot.c | ||
30 | @@ -27,10 +27,20 @@ | ||
31 | |||
32 | GRUB_MOD_LICENSE ("GPLv3+"); | ||
33 | |||
34 | -static grub_err_t (*grub_loader_boot_func) (void); | ||
35 | -static grub_err_t (*grub_loader_unload_func) (void); | ||
36 | +static grub_err_t (*grub_loader_boot_func) (void *context); | ||
37 | +static grub_err_t (*grub_loader_unload_func) (void *context); | ||
38 | +static void *grub_loader_context; | ||
39 | static int grub_loader_flags; | ||
40 | |||
41 | +struct grub_simple_loader_hooks | ||
42 | +{ | ||
43 | + grub_err_t (*boot) (void); | ||
44 | + grub_err_t (*unload) (void); | ||
45 | +}; | ||
46 | + | ||
47 | +/* Don't heap allocate this to avoid making grub_loader_set() fallible. */ | ||
48 | +static struct grub_simple_loader_hooks simple_loader_hooks; | ||
49 | + | ||
50 | struct grub_preboot | ||
51 | { | ||
52 | grub_err_t (*preboot_func) (int); | ||
53 | @@ -44,6 +54,29 @@ static int grub_loader_loaded; | ||
54 | static struct grub_preboot *preboots_head = 0, | ||
55 | *preboots_tail = 0; | ||
56 | |||
57 | +static grub_err_t | ||
58 | +grub_simple_boot_hook (void *context) | ||
59 | +{ | ||
60 | + struct grub_simple_loader_hooks *hooks; | ||
61 | + | ||
62 | + hooks = (struct grub_simple_loader_hooks *) context; | ||
63 | + return hooks->boot (); | ||
64 | +} | ||
65 | + | ||
66 | +static grub_err_t | ||
67 | +grub_simple_unload_hook (void *context) | ||
68 | +{ | ||
69 | + struct grub_simple_loader_hooks *hooks; | ||
70 | + grub_err_t ret; | ||
71 | + | ||
72 | + hooks = (struct grub_simple_loader_hooks *) context; | ||
73 | + | ||
74 | + ret = hooks->unload (); | ||
75 | + grub_memset (hooks, 0, sizeof (*hooks)); | ||
76 | + | ||
77 | + return ret; | ||
78 | +} | ||
79 | + | ||
80 | int | ||
81 | grub_loader_is_loaded (void) | ||
82 | { | ||
83 | @@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) | ||
84 | } | ||
85 | |||
86 | void | ||
87 | -grub_loader_set (grub_err_t (*boot) (void), | ||
88 | - grub_err_t (*unload) (void), | ||
89 | - int flags) | ||
90 | +grub_loader_set_ex (grub_err_t (*boot) (void *context), | ||
91 | + grub_err_t (*unload) (void *context), | ||
92 | + void *context, | ||
93 | + int flags) | ||
94 | { | ||
95 | if (grub_loader_loaded && grub_loader_unload_func) | ||
96 | - grub_loader_unload_func (); | ||
97 | + grub_loader_unload_func (grub_loader_context); | ||
98 | |||
99 | grub_loader_boot_func = boot; | ||
100 | grub_loader_unload_func = unload; | ||
101 | + grub_loader_context = context; | ||
102 | grub_loader_flags = flags; | ||
103 | |||
104 | grub_loader_loaded = 1; | ||
105 | } | ||
106 | |||
107 | +void | ||
108 | +grub_loader_set (grub_err_t (*boot) (void), | ||
109 | + grub_err_t (*unload) (void), | ||
110 | + int flags) | ||
111 | +{ | ||
112 | + grub_loader_set_ex (grub_simple_boot_hook, | ||
113 | + grub_simple_unload_hook, | ||
114 | + &simple_loader_hooks, | ||
115 | + flags); | ||
116 | + | ||
117 | + simple_loader_hooks.boot = boot; | ||
118 | + simple_loader_hooks.unload = unload; | ||
119 | +} | ||
120 | + | ||
121 | void | ||
122 | grub_loader_unset(void) | ||
123 | { | ||
124 | if (grub_loader_loaded && grub_loader_unload_func) | ||
125 | - grub_loader_unload_func (); | ||
126 | + grub_loader_unload_func (grub_loader_context); | ||
127 | |||
128 | grub_loader_boot_func = 0; | ||
129 | grub_loader_unload_func = 0; | ||
130 | + grub_loader_context = 0; | ||
131 | |||
132 | grub_loader_loaded = 0; | ||
133 | } | ||
134 | @@ -158,7 +208,7 @@ grub_loader_boot (void) | ||
135 | return err; | ||
136 | } | ||
137 | } | ||
138 | - err = (grub_loader_boot_func) (); | ||
139 | + err = (grub_loader_boot_func) (grub_loader_context); | ||
140 | |||
141 | for (cur = preboots_tail; cur; cur = cur->prev) | ||
142 | if (! err) | ||
143 | diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c | ||
144 | index a8d7b91..93a028a 100644 | ||
145 | --- a/grub-core/loader/efi/chainloader.c | ||
146 | +++ b/grub-core/loader/efi/chainloader.c | ||
147 | @@ -44,33 +44,28 @@ GRUB_MOD_LICENSE ("GPLv3+"); | ||
148 | |||
149 | static grub_dl_t my_mod; | ||
150 | |||
151 | -static grub_efi_physical_address_t address; | ||
152 | -static grub_efi_uintn_t pages; | ||
153 | -static grub_efi_device_path_t *file_path; | ||
154 | -static grub_efi_handle_t image_handle; | ||
155 | -static grub_efi_char16_t *cmdline; | ||
156 | - | ||
157 | static grub_err_t | ||
158 | -grub_chainloader_unload (void) | ||
159 | +grub_chainloader_unload (void *context) | ||
160 | { | ||
161 | + grub_efi_handle_t image_handle = (grub_efi_handle_t) context; | ||
162 | + grub_efi_loaded_image_t *loaded_image; | ||
163 | grub_efi_boot_services_t *b; | ||
164 | |||
165 | + loaded_image = grub_efi_get_loaded_image (image_handle); | ||
166 | + if (loaded_image != NULL) | ||
167 | + grub_free (loaded_image->load_options); | ||
168 | + | ||
169 | b = grub_efi_system_table->boot_services; | ||
170 | efi_call_1 (b->unload_image, image_handle); | ||
171 | - efi_call_2 (b->free_pages, address, pages); | ||
172 | - | ||
173 | - grub_free (file_path); | ||
174 | - grub_free (cmdline); | ||
175 | - cmdline = 0; | ||
176 | - file_path = 0; | ||
177 | |||
178 | grub_dl_unref (my_mod); | ||
179 | return GRUB_ERR_NONE; | ||
180 | } | ||
181 | |||
182 | static grub_err_t | ||
183 | -grub_chainloader_boot (void) | ||
184 | +grub_chainloader_boot (void *context) | ||
185 | { | ||
186 | + grub_efi_handle_t image_handle = (grub_efi_handle_t) context; | ||
187 | grub_efi_boot_services_t *b; | ||
188 | grub_efi_status_t status; | ||
189 | grub_efi_uintn_t exit_data_size; | ||
190 | @@ -139,7 +134,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) | ||
191 | char *dir_start; | ||
192 | char *dir_end; | ||
193 | grub_size_t size; | ||
194 | - grub_efi_device_path_t *d; | ||
195 | + grub_efi_device_path_t *d, *file_path; | ||
196 | |||
197 | dir_start = grub_strchr (filename, ')'); | ||
198 | if (! dir_start) | ||
199 | @@ -215,11 +210,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
200 | grub_efi_status_t status; | ||
201 | grub_efi_boot_services_t *b; | ||
202 | grub_device_t dev = 0; | ||
203 | - grub_efi_device_path_t *dp = 0; | ||
204 | + grub_efi_device_path_t *dp = NULL, *file_path = NULL; | ||
205 | grub_efi_loaded_image_t *loaded_image; | ||
206 | char *filename; | ||
207 | void *boot_image = 0; | ||
208 | grub_efi_handle_t dev_handle = 0; | ||
209 | + grub_efi_physical_address_t address = 0; | ||
210 | + grub_efi_uintn_t pages = 0; | ||
211 | + grub_efi_char16_t *cmdline = NULL; | ||
212 | + grub_efi_handle_t image_handle = NULL; | ||
213 | |||
214 | if (argc == 0) | ||
215 | return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); | ||
216 | @@ -227,11 +226,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
217 | |||
218 | grub_dl_ref (my_mod); | ||
219 | |||
220 | - /* Initialize some global variables. */ | ||
221 | - address = 0; | ||
222 | - image_handle = 0; | ||
223 | - file_path = 0; | ||
224 | - | ||
225 | b = grub_efi_system_table->boot_services; | ||
226 | |||
227 | file = grub_file_open (filename, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE); | ||
228 | @@ -401,7 +395,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
229 | grub_file_close (file); | ||
230 | grub_device_close (dev); | ||
231 | |||
232 | - grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); | ||
233 | + /* We're finished with the source image buffer and file path now. */ | ||
234 | + efi_call_2 (b->free_pages, address, pages); | ||
235 | + grub_free (file_path); | ||
236 | + | ||
237 | + grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0); | ||
238 | return 0; | ||
239 | |||
240 | fail: | ||
241 | @@ -412,11 +410,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
242 | if (file) | ||
243 | grub_file_close (file); | ||
244 | |||
245 | + grub_free (cmdline); | ||
246 | grub_free (file_path); | ||
247 | |||
248 | if (address) | ||
249 | efi_call_2 (b->free_pages, address, pages); | ||
250 | |||
251 | + if (image_handle != NULL) | ||
252 | + efi_call_1 (b->unload_image, image_handle); | ||
253 | + | ||
254 | grub_dl_unref (my_mod); | ||
255 | |||
256 | return grub_errno; | ||
257 | diff --git a/include/grub/loader.h b/include/grub/loader.h | ||
258 | index 7f82a49..3071a50 100644 | ||
259 | --- a/include/grub/loader.h | ||
260 | +++ b/include/grub/loader.h | ||
261 | @@ -39,6 +39,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), | ||
262 | grub_err_t (*unload) (void), | ||
263 | int flags); | ||
264 | |||
265 | +void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *context), | ||
266 | + grub_err_t (*unload) (void *context), | ||
267 | + void *context, | ||
268 | + int flags); | ||
269 | + | ||
270 | /* Unset current loader, if any. */ | ||
271 | void EXPORT_FUNC (grub_loader_unset) (void); | ||
272 | |||
273 | -- | ||
274 | 2.25.1 | ||
275 | |||