diff options
Diffstat (limited to 'meta/recipes-bsp')
-rw-r--r-- | meta/recipes-bsp/grub/files/CVE-2020-27749.patch | 609 | ||||
-rw-r--r-- | meta/recipes-bsp/grub/files/CVE-2021-20225.patch | 58 | ||||
-rw-r--r-- | meta/recipes-bsp/grub/files/CVE-2021-20233.patch | 50 | ||||
-rw-r--r-- | meta/recipes-bsp/grub/grub2.inc | 3 |
4 files changed, 720 insertions, 0 deletions
diff --git a/meta/recipes-bsp/grub/files/CVE-2020-27749.patch b/meta/recipes-bsp/grub/files/CVE-2020-27749.patch new file mode 100644 index 0000000000..a2566b2ded --- /dev/null +++ b/meta/recipes-bsp/grub/files/CVE-2020-27749.patch | |||
@@ -0,0 +1,609 @@ | |||
1 | From 4ea7bae51f97e49c84dc67ea30b466ca8633b9f6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Chris Coulson <chris.coulson@canonical.com> | ||
3 | Date: Thu, 7 Jan 2021 19:21:03 +0000 | ||
4 | Subject: kern/parser: Fix a stack buffer overflow | ||
5 | |||
6 | grub_parser_split_cmdline() expands variable names present in the supplied | ||
7 | command line in to their corresponding variable contents and uses a 1 kiB | ||
8 | stack buffer for temporary storage without sufficient bounds checking. If | ||
9 | the function is called with a command line that references a variable with | ||
10 | a sufficiently large payload, it is possible to overflow the stack | ||
11 | buffer via tab completion, corrupt the stack frame and potentially | ||
12 | control execution. | ||
13 | |||
14 | Fixes: CVE-2020-27749 | ||
15 | |||
16 | Reported-by: Chris Coulson <chris.coulson@canonical.com> | ||
17 | Signed-off-by: Chris Coulson <chris.coulson@canonical.com> | ||
18 | Signed-off-by: Darren Kenny <darren.kenny@oracle.com> | ||
19 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | ||
20 | |||
21 | Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=c6c426e5ab6ea715153b72584de6bd8c82f698ec && https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=b1c9e9e889e4273fb15712051c887e6078511448 && https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=3d157bbd06506b170fde5ec23980c4bf9f7660e2 && https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=8bc817014ce3d7a498db44eae33c8b90e2430926 && https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=030fb6c4fa354cdbd6a8d6903dfed5d36eaf3cb2 && https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=4ea7bae51f97e49c84dc67ea30b466ca8633b9f6] | ||
22 | CVE: CVE-2020-27749 | ||
23 | |||
24 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
25 | --- | ||
26 | grub-core/Makefile.core.def | 1 + | ||
27 | grub-core/kern/buffer.c | 117 +++++++++++++++++++++ | ||
28 | grub-core/kern/parser.c | 204 +++++++++++++++++++++++------------- | ||
29 | include/grub/buffer.h | 144 +++++++++++++++++++++++++ | ||
30 | 4 files changed, 395 insertions(+), 71 deletions(-) | ||
31 | create mode 100644 grub-core/kern/buffer.c | ||
32 | create mode 100644 include/grub/buffer.h | ||
33 | |||
34 | diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def | ||
35 | index 651ea2a..823cd57 100644 | ||
36 | --- a/grub-core/Makefile.core.def | ||
37 | +++ b/grub-core/Makefile.core.def | ||
38 | @@ -123,6 +123,7 @@ kernel = { | ||
39 | riscv32_efi_startup = kern/riscv/efi/startup.S; | ||
40 | riscv64_efi_startup = kern/riscv/efi/startup.S; | ||
41 | |||
42 | + common = kern/buffer.c; | ||
43 | common = kern/command.c; | ||
44 | common = kern/corecmd.c; | ||
45 | common = kern/device.c; | ||
46 | diff --git a/grub-core/kern/buffer.c b/grub-core/kern/buffer.c | ||
47 | new file mode 100644 | ||
48 | index 0000000..9f5f8b8 | ||
49 | --- /dev/null | ||
50 | +++ b/grub-core/kern/buffer.c | ||
51 | @@ -0,0 +1,117 @@ | ||
52 | +/* | ||
53 | + * GRUB -- GRand Unified Bootloader | ||
54 | + * Copyright (C) 2021 Free Software Foundation, Inc. | ||
55 | + * | ||
56 | + * GRUB is free software: you can redistribute it and/or modify | ||
57 | + * it under the terms of the GNU General Public License as published by | ||
58 | + * the Free Software Foundation, either version 3 of the License, or | ||
59 | + * (at your option) any later version. | ||
60 | + * | ||
61 | + * GRUB is distributed in the hope that it will be useful, | ||
62 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
63 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
64 | + * GNU General Public License for more details. | ||
65 | + * | ||
66 | + * You should have received a copy of the GNU General Public License | ||
67 | + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | ||
68 | + */ | ||
69 | + | ||
70 | +#include <grub/buffer.h> | ||
71 | +#include <grub/err.h> | ||
72 | +#include <grub/misc.h> | ||
73 | +#include <grub/mm.h> | ||
74 | +#include <grub/safemath.h> | ||
75 | +#include <grub/types.h> | ||
76 | + | ||
77 | +grub_buffer_t | ||
78 | +grub_buffer_new (grub_size_t sz) | ||
79 | +{ | ||
80 | + struct grub_buffer *ret; | ||
81 | + | ||
82 | + ret = (struct grub_buffer *) grub_malloc (sizeof (*ret)); | ||
83 | + if (ret == NULL) | ||
84 | + return NULL; | ||
85 | + | ||
86 | + ret->data = (grub_uint8_t *) grub_malloc (sz); | ||
87 | + if (ret->data == NULL) | ||
88 | + { | ||
89 | + grub_free (ret); | ||
90 | + return NULL; | ||
91 | + } | ||
92 | + | ||
93 | + ret->sz = sz; | ||
94 | + ret->pos = 0; | ||
95 | + ret->used = 0; | ||
96 | + | ||
97 | + return ret; | ||
98 | +} | ||
99 | + | ||
100 | +void | ||
101 | +grub_buffer_free (grub_buffer_t buf) | ||
102 | +{ | ||
103 | + grub_free (buf->data); | ||
104 | + grub_free (buf); | ||
105 | +} | ||
106 | + | ||
107 | +grub_err_t | ||
108 | +grub_buffer_ensure_space (grub_buffer_t buf, grub_size_t req) | ||
109 | +{ | ||
110 | + grub_uint8_t *d; | ||
111 | + grub_size_t newsz = 1; | ||
112 | + | ||
113 | + /* Is the current buffer size adequate? */ | ||
114 | + if (buf->sz >= req) | ||
115 | + return GRUB_ERR_NONE; | ||
116 | + | ||
117 | + /* Find the smallest power-of-2 size that satisfies the request. */ | ||
118 | + while (newsz < req) | ||
119 | + { | ||
120 | + if (newsz == 0) | ||
121 | + return grub_error (GRUB_ERR_OUT_OF_RANGE, | ||
122 | + N_("requested buffer size is too large")); | ||
123 | + newsz <<= 1; | ||
124 | + } | ||
125 | + | ||
126 | + d = (grub_uint8_t *) grub_realloc (buf->data, newsz); | ||
127 | + if (d == NULL) | ||
128 | + return grub_errno; | ||
129 | + | ||
130 | + buf->data = d; | ||
131 | + buf->sz = newsz; | ||
132 | + | ||
133 | + return GRUB_ERR_NONE; | ||
134 | +} | ||
135 | + | ||
136 | +void * | ||
137 | +grub_buffer_take_data (grub_buffer_t buf) | ||
138 | +{ | ||
139 | + void *data = buf->data; | ||
140 | + | ||
141 | + buf->data = NULL; | ||
142 | + buf->sz = buf->pos = buf->used = 0; | ||
143 | + | ||
144 | + return data; | ||
145 | +} | ||
146 | + | ||
147 | +void | ||
148 | +grub_buffer_reset (grub_buffer_t buf) | ||
149 | +{ | ||
150 | + buf->pos = buf->used = 0; | ||
151 | +} | ||
152 | + | ||
153 | +grub_err_t | ||
154 | +grub_buffer_advance_read_pos (grub_buffer_t buf, grub_size_t n) | ||
155 | +{ | ||
156 | + grub_size_t newpos; | ||
157 | + | ||
158 | + if (grub_add (buf->pos, n, &newpos)) | ||
159 | + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); | ||
160 | + | ||
161 | + if (newpos > buf->used) | ||
162 | + return grub_error (GRUB_ERR_OUT_OF_RANGE, | ||
163 | + N_("new read is position beyond the end of the written data")); | ||
164 | + | ||
165 | + buf->pos = newpos; | ||
166 | + | ||
167 | + return GRUB_ERR_NONE; | ||
168 | +} | ||
169 | diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c | ||
170 | index d1cf061..6ab7aa4 100644 | ||
171 | --- a/grub-core/kern/parser.c | ||
172 | +++ b/grub-core/kern/parser.c | ||
173 | @@ -1,7 +1,7 @@ | ||
174 | /* parser.c - the part of the parser that can return partial tokens */ | ||
175 | /* | ||
176 | * GRUB -- GRand Unified Bootloader | ||
177 | - * Copyright (C) 2005,2007,2009 Free Software Foundation, Inc. | ||
178 | + * Copyright (C) 2005,2007,2009,2021 Free Software Foundation, Inc. | ||
179 | * | ||
180 | * GRUB is free software: you can redistribute it and/or modify | ||
181 | * it under the terms of the GNU General Public License as published by | ||
182 | @@ -18,6 +18,7 @@ | ||
183 | */ | ||
184 | |||
185 | #include <grub/parser.h> | ||
186 | +#include <grub/buffer.h> | ||
187 | #include <grub/env.h> | ||
188 | #include <grub/misc.h> | ||
189 | #include <grub/mm.h> | ||
190 | @@ -107,8 +108,8 @@ check_varstate (grub_parser_state_t s) | ||
191 | } | ||
192 | |||
193 | |||
194 | -static void | ||
195 | -add_var (char *varname, char **bp, char **vp, | ||
196 | +static grub_err_t | ||
197 | +add_var (grub_buffer_t varname, grub_buffer_t buf, | ||
198 | grub_parser_state_t state, grub_parser_state_t newstate) | ||
199 | { | ||
200 | const char *val; | ||
201 | @@ -116,17 +117,74 @@ add_var (char *varname, char **bp, char **vp, | ||
202 | /* Check if a variable was being read in and the end of the name | ||
203 | was reached. */ | ||
204 | if (!(check_varstate (state) && !check_varstate (newstate))) | ||
205 | - return; | ||
206 | + return GRUB_ERR_NONE; | ||
207 | + | ||
208 | + if (grub_buffer_append_char (varname, '\0') != GRUB_ERR_NONE) | ||
209 | + return grub_errno; | ||
210 | |||
211 | - *((*vp)++) = '\0'; | ||
212 | - val = grub_env_get (varname); | ||
213 | - *vp = varname; | ||
214 | + val = grub_env_get ((const char *) grub_buffer_peek_data (varname)); | ||
215 | + grub_buffer_reset (varname); | ||
216 | if (!val) | ||
217 | - return; | ||
218 | + return GRUB_ERR_NONE; | ||
219 | |||
220 | /* Insert the contents of the variable in the buffer. */ | ||
221 | - for (; *val; val++) | ||
222 | - *((*bp)++) = *val; | ||
223 | + return grub_buffer_append_data (buf, val, grub_strlen (val)); | ||
224 | +} | ||
225 | + | ||
226 | +static grub_err_t | ||
227 | +terminate_arg (grub_buffer_t buffer, int *argc) | ||
228 | +{ | ||
229 | + grub_size_t unread = grub_buffer_get_unread_bytes (buffer); | ||
230 | + | ||
231 | + if (unread == 0) | ||
232 | + return GRUB_ERR_NONE; | ||
233 | + | ||
234 | + if (*(const char *) grub_buffer_peek_data_at (buffer, unread - 1) == '\0') | ||
235 | + return GRUB_ERR_NONE; | ||
236 | + | ||
237 | + if (grub_buffer_append_char (buffer, '\0') != GRUB_ERR_NONE) | ||
238 | + return grub_errno; | ||
239 | + | ||
240 | + (*argc)++; | ||
241 | + | ||
242 | + return GRUB_ERR_NONE; | ||
243 | +} | ||
244 | + | ||
245 | +static grub_err_t | ||
246 | +process_char (char c, grub_buffer_t buffer, grub_buffer_t varname, | ||
247 | + grub_parser_state_t state, int *argc, | ||
248 | + grub_parser_state_t *newstate) | ||
249 | +{ | ||
250 | + char use; | ||
251 | + | ||
252 | + *newstate = grub_parser_cmdline_state (state, c, &use); | ||
253 | + | ||
254 | + /* | ||
255 | + * If a variable was being processed and this character does | ||
256 | + * not describe the variable anymore, write the variable to | ||
257 | + * the buffer. | ||
258 | + */ | ||
259 | + if (add_var (varname, buffer, state, *newstate) != GRUB_ERR_NONE) | ||
260 | + return grub_errno; | ||
261 | + | ||
262 | + if (check_varstate (*newstate)) | ||
263 | + { | ||
264 | + if (use) | ||
265 | + return grub_buffer_append_char (varname, use); | ||
266 | + } | ||
267 | + else if (*newstate == GRUB_PARSER_STATE_TEXT && | ||
268 | + state != GRUB_PARSER_STATE_ESC && grub_isspace (use)) | ||
269 | + { | ||
270 | + /* | ||
271 | + * Don't add more than one argument if multiple | ||
272 | + * spaces are used. | ||
273 | + */ | ||
274 | + return terminate_arg (buffer, argc); | ||
275 | + } | ||
276 | + else if (use) | ||
277 | + return grub_buffer_append_char (buffer, use); | ||
278 | + | ||
279 | + return GRUB_ERR_NONE; | ||
280 | } | ||
281 | |||
282 | grub_err_t | ||
283 | @@ -135,24 +193,36 @@ grub_parser_split_cmdline (const char *cmdline, | ||
284 | int *argc, char ***argv) | ||
285 | { | ||
286 | grub_parser_state_t state = GRUB_PARSER_STATE_TEXT; | ||
287 | - /* XXX: Fixed size buffer, perhaps this buffer should be dynamically | ||
288 | - allocated. */ | ||
289 | - char buffer[1024]; | ||
290 | - char *bp = buffer; | ||
291 | + grub_buffer_t buffer, varname; | ||
292 | char *rd = (char *) cmdline; | ||
293 | - char varname[200]; | ||
294 | - char *vp = varname; | ||
295 | - char *args; | ||
296 | + char *rp = rd; | ||
297 | int i; | ||
298 | |||
299 | *argc = 0; | ||
300 | *argv = NULL; | ||
301 | + | ||
302 | + buffer = grub_buffer_new (1024); | ||
303 | + if (buffer == NULL) | ||
304 | + return grub_errno; | ||
305 | + | ||
306 | + varname = grub_buffer_new (200); | ||
307 | + if (varname == NULL) | ||
308 | + goto fail; | ||
309 | + | ||
310 | do | ||
311 | { | ||
312 | - if (!rd || !*rd) | ||
313 | + if (rp == NULL || *rp == '\0') | ||
314 | { | ||
315 | + if (rd != cmdline) | ||
316 | + { | ||
317 | + grub_free (rd); | ||
318 | + rd = rp = NULL; | ||
319 | + } | ||
320 | if (getline) | ||
321 | - getline (&rd, 1, getline_data); | ||
322 | + { | ||
323 | + getline (&rd, 1, getline_data); | ||
324 | + rp = rd; | ||
325 | + } | ||
326 | else | ||
327 | break; | ||
328 | } | ||
329 | @@ -160,39 +230,14 @@ grub_parser_split_cmdline (const char *cmdline, | ||
330 | if (!rd) | ||
331 | break; | ||
332 | |||
333 | - for (; *rd; rd++) | ||
334 | + for (; *rp != '\0'; rp++) | ||
335 | { | ||
336 | grub_parser_state_t newstate; | ||
337 | - char use; | ||
338 | |||
339 | - newstate = grub_parser_cmdline_state (state, *rd, &use); | ||
340 | + if (process_char (*rp, buffer, varname, state, argc, | ||
341 | + &newstate) != GRUB_ERR_NONE) | ||
342 | + goto fail; | ||
343 | |||
344 | - /* If a variable was being processed and this character does | ||
345 | - not describe the variable anymore, write the variable to | ||
346 | - the buffer. */ | ||
347 | - add_var (varname, &bp, &vp, state, newstate); | ||
348 | - | ||
349 | - if (check_varstate (newstate)) | ||
350 | - { | ||
351 | - if (use) | ||
352 | - *(vp++) = use; | ||
353 | - } | ||
354 | - else | ||
355 | - { | ||
356 | - if (newstate == GRUB_PARSER_STATE_TEXT | ||
357 | - && state != GRUB_PARSER_STATE_ESC && grub_isspace (use)) | ||
358 | - { | ||
359 | - /* Don't add more than one argument if multiple | ||
360 | - spaces are used. */ | ||
361 | - if (bp != buffer && *(bp - 1)) | ||
362 | - { | ||
363 | - *(bp++) = '\0'; | ||
364 | - (*argc)++; | ||
365 | - } | ||
366 | - } | ||
367 | - else if (use) | ||
368 | - *(bp++) = use; | ||
369 | - } | ||
370 | state = newstate; | ||
371 | } | ||
372 | } | ||
373 | @@ -200,43 +245,60 @@ grub_parser_split_cmdline (const char *cmdline, | ||
374 | |||
375 | /* A special case for when the last character was part of a | ||
376 | variable. */ | ||
377 | - add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT); | ||
378 | + if (add_var (varname, buffer, state, GRUB_PARSER_STATE_TEXT) != GRUB_ERR_NONE) | ||
379 | + goto fail; | ||
380 | |||
381 | - if (bp != buffer && *(bp - 1)) | ||
382 | - { | ||
383 | - *(bp++) = '\0'; | ||
384 | - (*argc)++; | ||
385 | - } | ||
386 | + /* Ensure that the last argument is terminated. */ | ||
387 | + if (terminate_arg (buffer, argc) != GRUB_ERR_NONE) | ||
388 | + goto fail; | ||
389 | |||
390 | /* If there are no args, then we're done. */ | ||
391 | if (!*argc) | ||
392 | - return 0; | ||
393 | - | ||
394 | - /* Reserve memory for the return values. */ | ||
395 | - args = grub_malloc (bp - buffer); | ||
396 | - if (!args) | ||
397 | - return grub_errno; | ||
398 | - grub_memcpy (args, buffer, bp - buffer); | ||
399 | + { | ||
400 | + grub_errno = GRUB_ERR_NONE; | ||
401 | + goto out; | ||
402 | + } | ||
403 | |||
404 | *argv = grub_calloc (*argc + 1, sizeof (char *)); | ||
405 | if (!*argv) | ||
406 | - { | ||
407 | - grub_free (args); | ||
408 | - return grub_errno; | ||
409 | - } | ||
410 | + goto fail; | ||
411 | |||
412 | /* The arguments are separated with 0's, setup argv so it points to | ||
413 | the right values. */ | ||
414 | - bp = args; | ||
415 | for (i = 0; i < *argc; i++) | ||
416 | { | ||
417 | - (*argv)[i] = bp; | ||
418 | - while (*bp) | ||
419 | - bp++; | ||
420 | - bp++; | ||
421 | + char *arg; | ||
422 | + | ||
423 | + if (i > 0) | ||
424 | + { | ||
425 | + if (grub_buffer_advance_read_pos (buffer, 1) != GRUB_ERR_NONE) | ||
426 | + goto fail; | ||
427 | + } | ||
428 | + | ||
429 | + arg = (char *) grub_buffer_peek_data (buffer); | ||
430 | + if (arg == NULL || | ||
431 | + grub_buffer_advance_read_pos (buffer, grub_strlen (arg)) != GRUB_ERR_NONE) | ||
432 | + goto fail; | ||
433 | + | ||
434 | + (*argv)[i] = arg; | ||
435 | } | ||
436 | |||
437 | - return 0; | ||
438 | + /* Keep memory for the return values. */ | ||
439 | + grub_buffer_take_data (buffer); | ||
440 | + | ||
441 | + grub_errno = GRUB_ERR_NONE; | ||
442 | + | ||
443 | + out: | ||
444 | + if (rd != cmdline) | ||
445 | + grub_free (rd); | ||
446 | + grub_buffer_free (buffer); | ||
447 | + grub_buffer_free (varname); | ||
448 | + | ||
449 | + return grub_errno; | ||
450 | + | ||
451 | + fail: | ||
452 | + grub_free (*argv); | ||
453 | + goto out; | ||
454 | } | ||
455 | |||
456 | /* Helper for grub_parser_execute. */ | ||
457 | diff --git a/include/grub/buffer.h b/include/grub/buffer.h | ||
458 | new file mode 100644 | ||
459 | index 0000000..f4b10cf | ||
460 | --- /dev/null | ||
461 | +++ b/include/grub/buffer.h | ||
462 | @@ -0,0 +1,144 @@ | ||
463 | +/* | ||
464 | + * GRUB -- GRand Unified Bootloader | ||
465 | + * Copyright (C) 2021 Free Software Foundation, Inc. | ||
466 | + * | ||
467 | + * GRUB is free software: you can redistribute it and/or modify | ||
468 | + * it under the terms of the GNU General Public License as published by | ||
469 | + * the Free Software Foundation, either version 3 of the License, or | ||
470 | + * (at your option) any later version. | ||
471 | + * | ||
472 | + * GRUB is distributed in the hope that it will be useful, | ||
473 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
474 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
475 | + * GNU General Public License for more details. | ||
476 | + * | ||
477 | + * You should have received a copy of the GNU General Public License | ||
478 | + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | ||
479 | + */ | ||
480 | + | ||
481 | +#ifndef GRUB_BUFFER_H | ||
482 | +#define GRUB_BUFFER_H 1 | ||
483 | + | ||
484 | +#include <grub/err.h> | ||
485 | +#include <grub/misc.h> | ||
486 | +#include <grub/mm.h> | ||
487 | +#include <grub/safemath.h> | ||
488 | +#include <grub/types.h> | ||
489 | + | ||
490 | +struct grub_buffer | ||
491 | +{ | ||
492 | + grub_uint8_t *data; | ||
493 | + grub_size_t sz; | ||
494 | + grub_size_t pos; | ||
495 | + grub_size_t used; | ||
496 | +}; | ||
497 | + | ||
498 | +/* | ||
499 | + * grub_buffer_t represents a simple variable sized byte buffer with | ||
500 | + * read and write cursors. It currently only implements | ||
501 | + * functionality required by the only user in GRUB (append byte[s], | ||
502 | + * peeking data at a specified position and updating the read cursor. | ||
503 | + * Some things that this doesn't do yet are: | ||
504 | + * - Reading a portion of the buffer by copying data from the current | ||
505 | + * read position in to a caller supplied destination buffer and then | ||
506 | + * automatically updating the read cursor. | ||
507 | + * - Dropping the read part at the start of the buffer when an append | ||
508 | + * requires more space. | ||
509 | + */ | ||
510 | +typedef struct grub_buffer *grub_buffer_t; | ||
511 | + | ||
512 | +/* Allocate a new buffer with the specified initial size. */ | ||
513 | +extern grub_buffer_t grub_buffer_new (grub_size_t sz); | ||
514 | + | ||
515 | +/* Free the buffer and its resources. */ | ||
516 | +extern void grub_buffer_free (grub_buffer_t buf); | ||
517 | + | ||
518 | +/* Return the number of unread bytes in this buffer. */ | ||
519 | +static inline grub_size_t | ||
520 | +grub_buffer_get_unread_bytes (grub_buffer_t buf) | ||
521 | +{ | ||
522 | + return buf->used - buf->pos; | ||
523 | +} | ||
524 | + | ||
525 | +/* | ||
526 | + * Ensure that the buffer size is at least the requested | ||
527 | + * number of bytes. | ||
528 | + */ | ||
529 | +extern grub_err_t grub_buffer_ensure_space (grub_buffer_t buf, grub_size_t req); | ||
530 | + | ||
531 | +/* | ||
532 | + * Append the specified number of bytes from the supplied | ||
533 | + * data to the buffer. | ||
534 | + */ | ||
535 | +static inline grub_err_t | ||
536 | +grub_buffer_append_data (grub_buffer_t buf, const void *data, grub_size_t len) | ||
537 | +{ | ||
538 | + grub_size_t req; | ||
539 | + | ||
540 | + if (grub_add (buf->used, len, &req)) | ||
541 | + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); | ||
542 | + | ||
543 | + if (grub_buffer_ensure_space (buf, req) != GRUB_ERR_NONE) | ||
544 | + return grub_errno; | ||
545 | + | ||
546 | + grub_memcpy (&buf->data[buf->used], data, len); | ||
547 | + buf->used = req; | ||
548 | + | ||
549 | + return GRUB_ERR_NONE; | ||
550 | +} | ||
551 | + | ||
552 | +/* Append the supplied character to the buffer. */ | ||
553 | +static inline grub_err_t | ||
554 | +grub_buffer_append_char (grub_buffer_t buf, char c) | ||
555 | +{ | ||
556 | + return grub_buffer_append_data (buf, &c, 1); | ||
557 | +} | ||
558 | + | ||
559 | +/* | ||
560 | + * Forget and return the underlying data buffer. The caller | ||
561 | + * becomes the owner of this buffer, and must free it when it | ||
562 | + * is no longer required. | ||
563 | + */ | ||
564 | +extern void *grub_buffer_take_data (grub_buffer_t buf); | ||
565 | + | ||
566 | +/* Reset this buffer. Note that this does not deallocate any resources. */ | ||
567 | +void grub_buffer_reset (grub_buffer_t buf); | ||
568 | + | ||
569 | +/* | ||
570 | + * Return a pointer to the underlying data buffer at the specified | ||
571 | + * offset from the current read position. Note that this pointer may | ||
572 | + * become invalid if the buffer is mutated further. | ||
573 | + */ | ||
574 | +static inline void * | ||
575 | +grub_buffer_peek_data_at (grub_buffer_t buf, grub_size_t off) | ||
576 | +{ | ||
577 | + if (grub_add (buf->pos, off, &off)) | ||
578 | + { | ||
579 | + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected.")); | ||
580 | + return NULL; | ||
581 | + } | ||
582 | + | ||
583 | + if (off >= buf->used) | ||
584 | + { | ||
585 | + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("peek out of range")); | ||
586 | + return NULL; | ||
587 | + } | ||
588 | + | ||
589 | + return &buf->data[off]; | ||
590 | +} | ||
591 | + | ||
592 | +/* | ||
593 | + * Return a pointer to the underlying data buffer at the current | ||
594 | + * read position. Note that this pointer may become invalid if the | ||
595 | + * buffer is mutated further. | ||
596 | + */ | ||
597 | +static inline void * | ||
598 | +grub_buffer_peek_data (grub_buffer_t buf) | ||
599 | +{ | ||
600 | + return grub_buffer_peek_data_at (buf, 0); | ||
601 | +} | ||
602 | + | ||
603 | +/* Advance the read position by the specified number of bytes. */ | ||
604 | +extern grub_err_t grub_buffer_advance_read_pos (grub_buffer_t buf, grub_size_t n); | ||
605 | + | ||
606 | +#endif /* GRUB_BUFFER_H */ | ||
607 | -- | ||
608 | 2.25.1 | ||
609 | |||
diff --git a/meta/recipes-bsp/grub/files/CVE-2021-20225.patch b/meta/recipes-bsp/grub/files/CVE-2021-20225.patch new file mode 100644 index 0000000000..b864febe62 --- /dev/null +++ b/meta/recipes-bsp/grub/files/CVE-2021-20225.patch | |||
@@ -0,0 +1,58 @@ | |||
1 | From 2a330dba93ff11bc00eda76e9419bc52b0c7ead6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Axtens <dja@axtens.net> | ||
3 | Date: Fri, 22 Jan 2021 16:07:29 +1100 | ||
4 | Subject: lib/arg: Block repeated short options that require an argument | ||
5 | |||
6 | Fuzzing found the following crash: | ||
7 | |||
8 | search -hhhhhhhhhhhhhf | ||
9 | |||
10 | We didn't allocate enough option space for 13 hints because the | ||
11 | allocation code counts the number of discrete arguments (i.e. argc). | ||
12 | However, the shortopt parsing code will happily keep processing | ||
13 | a combination of short options without checking if those short | ||
14 | options require an argument. This means you can easily end writing | ||
15 | past the allocated option space. | ||
16 | |||
17 | This fixes a OOB write which can cause heap corruption. | ||
18 | |||
19 | Fixes: CVE-2021-20225 | ||
20 | |||
21 | Reported-by: Daniel Axtens <dja@axtens.net> | ||
22 | Signed-off-by: Daniel Axtens <dja@axtens.net> | ||
23 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | ||
24 | |||
25 | Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=2a330dba93ff11bc00eda76e9419bc52b0c7ead6] | ||
26 | CVE: CVE-2021-20225 | ||
27 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
28 | --- | ||
29 | grub-core/lib/arg.c | 13 +++++++++++++ | ||
30 | 1 file changed, 13 insertions(+) | ||
31 | |||
32 | diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c | ||
33 | index 3288609..537c5e9 100644 | ||
34 | --- a/grub-core/lib/arg.c | ||
35 | +++ b/grub-core/lib/arg.c | ||
36 | @@ -299,6 +299,19 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, | ||
37 | it can have an argument value. */ | ||
38 | if (*curshort) | ||
39 | { | ||
40 | + /* | ||
41 | + * Only permit further short opts if this one doesn't | ||
42 | + * require a value. | ||
43 | + */ | ||
44 | + if (opt->type != ARG_TYPE_NONE && | ||
45 | + !(opt->flags & GRUB_ARG_OPTION_OPTIONAL)) | ||
46 | + { | ||
47 | + grub_error (GRUB_ERR_BAD_ARGUMENT, | ||
48 | + N_("missing mandatory option for `%s'"), | ||
49 | + opt->longarg); | ||
50 | + goto fail; | ||
51 | + } | ||
52 | + | ||
53 | if (parse_option (cmd, opt, 0, usr) || grub_errno) | ||
54 | goto fail; | ||
55 | } | ||
56 | -- | ||
57 | 2.25.1 | ||
58 | |||
diff --git a/meta/recipes-bsp/grub/files/CVE-2021-20233.patch b/meta/recipes-bsp/grub/files/CVE-2021-20233.patch new file mode 100644 index 0000000000..d2069afc18 --- /dev/null +++ b/meta/recipes-bsp/grub/files/CVE-2021-20233.patch | |||
@@ -0,0 +1,50 @@ | |||
1 | From 2f533a89a8dfcacbf2c9dbc77d910f111f24bf33 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Axtens <dja@axtens.net> | ||
3 | Date: Fri, 22 Jan 2021 17:10:48 +1100 | ||
4 | Subject: commands/menuentry: Fix quoting in setparams_prefix() | ||
5 | |||
6 | Commit 9acdcbf32542 (use single quotes in menuentry setparams command) | ||
7 | says that expressing a quoted single quote will require 3 characters. It | ||
8 | actually requires (and always did require!) 4 characters: | ||
9 | |||
10 | str: a'b => a'\''b | ||
11 | len: 3 => 6 (2 for the letters + 4 for the quote) | ||
12 | |||
13 | This leads to not allocating enough memory and thus out of bounds writes | ||
14 | that have been observed to cause heap corruption. | ||
15 | |||
16 | Allocate 4 bytes for each single quote. | ||
17 | |||
18 | Commit 22e7dbb2bb81 (Fix quoting in legacy parser.) does the same | ||
19 | quoting, but it adds 3 as extra overhead on top of the single byte that | ||
20 | the quote already needs. So it's correct. | ||
21 | |||
22 | Fixes: 9acdcbf32542 (use single quotes in menuentry setparams command) | ||
23 | Fixes: CVE-2021-20233 | ||
24 | |||
25 | Reported-by: Daniel Axtens <dja@axtens.net> | ||
26 | Signed-off-by: Daniel Axtens <dja@axtens.net> | ||
27 | |||
28 | Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/grub.git/commit/?h=grub-2.06&id=2f533a89a8dfcacbf2c9dbc77d910f111f24bf33] | ||
29 | CVE: CVE-2021-20233 | ||
30 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> | ||
31 | --- | ||
32 | grub-core/commands/menuentry.c | 2 +- | ||
33 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
34 | |||
35 | diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c | ||
36 | index 9164df7..720e6d8 100644 | ||
37 | --- a/grub-core/commands/menuentry.c | ||
38 | +++ b/grub-core/commands/menuentry.c | ||
39 | @@ -230,7 +230,7 @@ setparams_prefix (int argc, char **args) | ||
40 | len += 3; /* 3 = 1 space + 2 quotes */ | ||
41 | p = args[i]; | ||
42 | while (*p) | ||
43 | - len += (*p++ == '\'' ? 3 : 1); | ||
44 | + len += (*p++ == '\'' ? 4 : 1); | ||
45 | } | ||
46 | |||
47 | result = grub_malloc (len + 2); | ||
48 | -- | ||
49 | 2.25.1 | ||
50 | |||
diff --git a/meta/recipes-bsp/grub/grub2.inc b/meta/recipes-bsp/grub/grub2.inc index d09eecd8ac..5a6e213936 100644 --- a/meta/recipes-bsp/grub/grub2.inc +++ b/meta/recipes-bsp/grub/grub2.inc | |||
@@ -106,6 +106,9 @@ SRC_URI = "${GNU_MIRROR}/grub/grub-${PV}.tar.gz \ | |||
106 | file://font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch \ | 106 | file://font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch \ |
107 | file://CVE-2022-2601.patch \ | 107 | file://CVE-2022-2601.patch \ |
108 | file://CVE-2022-3775.patch \ | 108 | file://CVE-2022-3775.patch \ |
109 | file://CVE-2020-27749.patch \ | ||
110 | file://CVE-2021-20225.patch \ | ||
111 | file://CVE-2021-20233.patch \ | ||
109 | " | 112 | " |
110 | SRC_URI[md5sum] = "5ce674ca6b2612d8939b9e6abed32934" | 113 | SRC_URI[md5sum] = "5ce674ca6b2612d8939b9e6abed32934" |
111 | SRC_URI[sha256sum] = "f10c85ae3e204dbaec39ae22fa3c5e99f0665417e91c2cb49b7e5031658ba6ea" | 114 | SRC_URI[sha256sum] = "f10c85ae3e204dbaec39ae22fa3c5e99f0665417e91c2cb49b7e5031658ba6ea" |