]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/grub/grub-2.04-BootHole.patch
Merge branch 'next'
[ipfire-2.x.git] / src / patches / grub / grub-2.04-BootHole.patch
CommitLineData
f8561a5c
AF
1From 705b89f19fff03054f7167e1785461492688d61b Mon Sep 17 00:00:00 2001
2From: Peter Jones <pjones@redhat.com>
3Date: Wed, 15 Apr 2020 15:45:02 -0400
4Subject: yylex: Make lexer fatal errors actually be fatal
5
6When presented with a command that can't be tokenized to anything
7smaller than YYLMAX characters, the parser calls YY_FATAL_ERROR(errmsg),
8expecting that will stop further processing, as such:
9
10 #define YY_DO_BEFORE_ACTION \
11 yyg->yytext_ptr = yy_bp; \
12 yyleng = (int) (yy_cp - yy_bp); \
13 yyg->yy_hold_char = *yy_cp; \
14 *yy_cp = '\0'; \
15 if ( yyleng >= YYLMAX ) \
16 YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
17 yy_flex_strncpy( yytext, yyg->yytext_ptr, yyleng + 1 , yyscanner); \
18 yyg->yy_c_buf_p = yy_cp;
19
20The code flex generates expects that YY_FATAL_ERROR() will either return
21for it or do some form of longjmp(), or handle the error in some way at
22least, and so the strncpy() call isn't in an "else" clause, and thus if
23YY_FATAL_ERROR() is *not* actually fatal, it does the call with the
24questionable limit, and predictable results ensue.
25
26Unfortunately, our implementation of YY_FATAL_ERROR() is:
27
28 #define YY_FATAL_ERROR(msg) \
29 do { \
30 grub_printf (_("fatal error: %s\n"), _(msg)); \
31 } while (0)
32
33The same pattern exists in yyless(), and similar problems exist in users
34of YY_INPUT(), several places in the main parsing loop,
35yy_get_next_buffer(), yy_load_buffer_state(), yyensure_buffer_stack,
36yy_scan_buffer(), etc.
37
38All of these callers expect YY_FATAL_ERROR() to actually be fatal, and
39the things they do if it returns after calling it are wildly unsafe.
40
41Fixes: CVE-2020-10713
42
43Signed-off-by: Peter Jones <pjones@redhat.com>
44Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
45---
46 grub-core/script/yylex.l | 4 ++--
47 1 file changed, 2 insertions(+), 2 deletions(-)
48
49diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l
50index 7b44c37b7..b7203c823 100644
51--- a/grub-core/script/yylex.l
52+++ b/grub-core/script/yylex.l
53@@ -37,11 +37,11 @@
54
55 /*
56 * As we don't have access to yyscanner, we cannot do much except to
57- * print the fatal error.
58+ * print the fatal error and exit.
59 */
60 #define YY_FATAL_ERROR(msg) \
61 do { \
62- grub_printf (_("fatal error: %s\n"), _(msg)); \
63+ grub_fatal (_("fatal error: %s\n"), _(msg));\
64 } while (0)
65
66 #define COPY(str, hint) \
67
68From 016977edbd5d9f6fbab6412fb8b4d1f50eb432e7 Mon Sep 17 00:00:00 2001
69From: Peter Jones <pjones@redhat.com>
70Date: Mon, 15 Jun 2020 10:58:42 -0400
71Subject: safemath: Add some arithmetic primitives that check for
72 overflow
73
74This adds a new header, include/grub/safemath.h, that includes easy to
75use wrappers for __builtin_{add,sub,mul}_overflow() declared like:
76
77 bool OP(a, b, res)
78
79where OP is grub_add, grub_sub or grub_mul. OP() returns true in the
80case where the operation would overflow and res is not modified.
81Otherwise, false is returned and the operation is executed.
82
83These arithmetic primitives require newer compiler versions. So, bump
84these requirements in the INSTALL file too.
85
86Signed-off-by: Peter Jones <pjones@redhat.com>
87Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
88---
89 INSTALL | 22 ++--------------------
90 include/grub/compiler.h | 8 ++++++++
91 include/grub/safemath.h | 37 +++++++++++++++++++++++++++++++++++++
92 3 files changed, 47 insertions(+), 20 deletions(-)
93 create mode 100644 include/grub/safemath.h
94
95diff --git a/INSTALL b/INSTALL
96index 342c158e9..991479b52 100644
97--- a/INSTALL
98+++ b/INSTALL
99@@ -11,27 +11,9 @@ GRUB depends on some software packages installed into your system. If
100 you don't have any of them, please obtain and install them before
101 configuring the GRUB.
102
103-* GCC 4.1.3 or later
104- Note: older versions may work but support is limited
105-
106- Experimental support for clang 3.3 or later (results in much bigger binaries)
107+* GCC 5.1.0 or later
108+ Experimental support for clang 3.8.0 or later (results in much bigger binaries)
109 for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64
110- Note: clang 3.2 or later works for i386 and x86_64 targets but results in
111- much bigger binaries.
112- earlier versions not tested
113- Note: clang 3.2 or later works for arm
114- earlier versions not tested
115- Note: clang on arm64 is not supported due to
116- https://llvm.org/bugs/show_bug.cgi?id=26030
117- Note: clang 3.3 or later works for mips(el)
118- earlier versions fail to generate .reginfo and hence gprel relocations
119- fail.
120- Note: clang 3.2 or later works for powerpc
121- earlier versions not tested
122- Note: clang 3.5 or later works for sparc64
123- earlier versions return "error: unable to interface with target machine"
124- Note: clang has no support for ia64 and hence you can't compile GRUB
125- for ia64 with clang
126 * GNU Make
127 * GNU Bison 2.3 or later
128 * GNU gettext 0.17 or later
129diff --git a/include/grub/compiler.h b/include/grub/compiler.h
130index c9e1d7a73..8f3be3ae7 100644
131--- a/include/grub/compiler.h
132+++ b/include/grub/compiler.h
133@@ -48,4 +48,12 @@
134 # define WARN_UNUSED_RESULT
135 #endif
136
137+#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
138+# define CLANG_PREREQ(maj,min) \
139+ ((__clang_major__ > (maj)) || \
140+ (__clang_major__ == (maj) && __clang_minor__ >= (min)))
141+#else
142+# define CLANG_PREREQ(maj,min) 0
143+#endif
144+
145 #endif /* ! GRUB_COMPILER_HEADER */
146diff --git a/include/grub/safemath.h b/include/grub/safemath.h
147new file mode 100644
148index 000000000..c17b89bba
149--- /dev/null
150+++ b/include/grub/safemath.h
151@@ -0,0 +1,37 @@
152+/*
153+ * GRUB -- GRand Unified Bootloader
154+ * Copyright (C) 2020 Free Software Foundation, Inc.
155+ *
156+ * GRUB is free software: you can redistribute it and/or modify
157+ * it under the terms of the GNU General Public License as published by
158+ * the Free Software Foundation, either version 3 of the License, or
159+ * (at your option) any later version.
160+ *
161+ * GRUB is distributed in the hope that it will be useful,
162+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
163+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
164+ * GNU General Public License for more details.
165+ *
166+ * You should have received a copy of the GNU General Public License
167+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
168+ *
169+ * Arithmetic operations that protect against overflow.
170+ */
171+
172+#ifndef GRUB_SAFEMATH_H
173+#define GRUB_SAFEMATH_H 1
174+
175+#include <grub/compiler.h>
176+
177+/* These appear in gcc 5.1 and clang 3.8. */
178+#if GNUC_PREREQ(5, 1) || CLANG_PREREQ(3, 8)
179+
180+#define grub_add(a, b, res) __builtin_add_overflow(a, b, res)
181+#define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res)
182+#define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
183+
184+#else
185+#error gcc 5.1 or newer or clang 3.8 or newer is required
186+#endif
187+
188+#endif /* GRUB_SAFEMATH_H */
189
190From f80ca28e207484650fc7634545cd3dc6037de3c8 Mon Sep 17 00:00:00 2001
191From: Peter Jones <pjones@redhat.com>
192Date: Mon, 15 Jun 2020 12:15:29 -0400
193Subject: calloc: Make sure we always have an overflow-checking
194 calloc() available
195
196This tries to make sure that everywhere in this source tree, we always have
197an appropriate version of calloc() (i.e. grub_calloc(), xcalloc(), etc.)
198available, and that they all safely check for overflow and return NULL when
199it would occur.
200
201Signed-off-by: Peter Jones <pjones@redhat.com>
202Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
203---
204 grub-core/kern/emu/misc.c | 12 +++++++++
205 grub-core/kern/emu/mm.c | 10 ++++++++
206 grub-core/kern/mm.c | 40 ++++++++++++++++++++++++++++++
207 grub-core/lib/libgcrypt_wrap/mem.c | 11 ++++++--
208 grub-core/lib/posix_wrap/stdlib.h | 8 +++++-
209 include/grub/emu/misc.h | 1 +
210 include/grub/mm.h | 6 +++++
211 7 files changed, 85 insertions(+), 3 deletions(-)
212
213diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
214index 65db79baa..dfd8a8ec4 100644
215--- a/grub-core/kern/emu/misc.c
216+++ b/grub-core/kern/emu/misc.c
217@@ -85,6 +85,18 @@ grub_util_error (const char *fmt, ...)
218 exit (1);
219 }
220
221+void *
222+xcalloc (grub_size_t nmemb, grub_size_t size)
223+{
224+ void *p;
225+
226+ p = calloc (nmemb, size);
227+ if (!p)
228+ grub_util_error ("%s", _("out of memory"));
229+
230+ return p;
231+}
232+
233 void *
234 xmalloc (grub_size_t size)
235 {
236diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
237index f262e95e3..145b01d37 100644
238--- a/grub-core/kern/emu/mm.c
239+++ b/grub-core/kern/emu/mm.c
240@@ -25,6 +25,16 @@
241 #include <string.h>
242 #include <grub/i18n.h>
243
244+void *
245+grub_calloc (grub_size_t nmemb, grub_size_t size)
246+{
247+ void *ret;
248+ ret = calloc (nmemb, size);
249+ if (!ret)
250+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
251+ return ret;
252+}
253+
254 void *
255 grub_malloc (grub_size_t size)
256 {
257diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
258index ee88ff611..f2822a836 100644
259--- a/grub-core/kern/mm.c
260+++ b/grub-core/kern/mm.c
261@@ -67,8 +67,10 @@
262 #include <grub/dl.h>
263 #include <grub/i18n.h>
264 #include <grub/mm_private.h>
265+#include <grub/safemath.h>
266
267 #ifdef MM_DEBUG
268+# undef grub_calloc
269 # undef grub_malloc
270 # undef grub_zalloc
271 # undef grub_realloc
272@@ -375,6 +377,30 @@ grub_memalign (grub_size_t align, grub_size_t size)
273 return 0;
274 }
275
276+/*
277+ * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
278+ * integer overflow.
279+ */
280+void *
281+grub_calloc (grub_size_t nmemb, grub_size_t size)
282+{
283+ void *ret;
284+ grub_size_t sz = 0;
285+
286+ if (grub_mul (nmemb, size, &sz))
287+ {
288+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
289+ return NULL;
290+ }
291+
292+ ret = grub_memalign (0, sz);
293+ if (!ret)
294+ return NULL;
295+
296+ grub_memset (ret, 0, sz);
297+ return ret;
298+}
299+
300 /* Allocate SIZE bytes and return the pointer. */
301 void *
302 grub_malloc (grub_size_t size)
303@@ -561,6 +587,20 @@ grub_mm_dump (unsigned lineno)
304 grub_printf ("\n");
305 }
306
307+void *
308+grub_debug_calloc (const char *file, int line, grub_size_t nmemb, grub_size_t size)
309+{
310+ void *ptr;
311+
312+ if (grub_mm_debug)
313+ grub_printf ("%s:%d: calloc (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ",
314+ file, line, size);
315+ ptr = grub_calloc (nmemb, size);
316+ if (grub_mm_debug)
317+ grub_printf ("%p\n", ptr);
318+ return ptr;
319+}
320+
321 void *
322 grub_debug_malloc (const char *file, int line, grub_size_t size)
323 {
324diff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c
325index beeb661a3..74c6eafe5 100644
326--- a/grub-core/lib/libgcrypt_wrap/mem.c
327+++ b/grub-core/lib/libgcrypt_wrap/mem.c
328@@ -4,6 +4,7 @@
329 #include <grub/crypto.h>
330 #include <grub/dl.h>
331 #include <grub/env.h>
332+#include <grub/safemath.h>
333
334 GRUB_MOD_LICENSE ("GPLv3+");
335
336@@ -36,7 +37,10 @@ void *
337 gcry_xcalloc (size_t n, size_t m)
338 {
339 void *ret;
340- ret = grub_zalloc (n * m);
341+ size_t sz;
342+ if (grub_mul (n, m, &sz))
343+ grub_fatal ("gcry_xcalloc would overflow");
344+ ret = grub_zalloc (sz);
345 if (!ret)
346 grub_fatal ("gcry_xcalloc failed");
347 return ret;
348@@ -56,7 +60,10 @@ void *
349 gcry_xcalloc_secure (size_t n, size_t m)
350 {
351 void *ret;
352- ret = grub_zalloc (n * m);
353+ size_t sz;
354+ if (grub_mul (n, m, &sz))
355+ grub_fatal ("gcry_xcalloc would overflow");
356+ ret = grub_zalloc (sz);
357 if (!ret)
358 grub_fatal ("gcry_xcalloc failed");
359 return ret;
360diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h
361index 3b46f47ff..7a8d385e9 100644
362--- a/grub-core/lib/posix_wrap/stdlib.h
363+++ b/grub-core/lib/posix_wrap/stdlib.h
364@@ -21,6 +21,7 @@
365
366 #include <grub/mm.h>
367 #include <grub/misc.h>
368+#include <grub/safemath.h>
369
370 static inline void
371 free (void *ptr)
372@@ -37,7 +38,12 @@ malloc (grub_size_t size)
373 static inline void *
374 calloc (grub_size_t size, grub_size_t nelem)
375 {
376- return grub_zalloc (size * nelem);
377+ grub_size_t sz;
378+
379+ if (grub_mul (size, nelem, &sz))
380+ return NULL;
381+
382+ return grub_zalloc (sz);
383 }
384
385 static inline void *
386diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
387index ce464cfd0..ff9c48a64 100644
388--- a/include/grub/emu/misc.h
389+++ b/include/grub/emu/misc.h
390@@ -47,6 +47,7 @@ grub_util_device_is_mapped (const char *dev);
391 #define GRUB_HOST_PRIuLONG_LONG "llu"
392 #define GRUB_HOST_PRIxLONG_LONG "llx"
393
394+void * EXPORT_FUNC(xcalloc) (grub_size_t nmemb, grub_size_t size) WARN_UNUSED_RESULT;
395 void * EXPORT_FUNC(xmalloc) (grub_size_t size) WARN_UNUSED_RESULT;
396 void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) WARN_UNUSED_RESULT;
397 char * EXPORT_FUNC(xstrdup) (const char *str) WARN_UNUSED_RESULT;
398diff --git a/include/grub/mm.h b/include/grub/mm.h
399index 28e2e53eb..9c38dd3ca 100644
400--- a/include/grub/mm.h
401+++ b/include/grub/mm.h
402@@ -29,6 +29,7 @@
403 #endif
404
405 void grub_mm_init_region (void *addr, grub_size_t size);
406+void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
407 void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
408 void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
409 void EXPORT_FUNC(grub_free) (void *ptr);
410@@ -48,6 +49,9 @@ extern int EXPORT_VAR(grub_mm_debug);
411 void grub_mm_dump_free (void);
412 void grub_mm_dump (unsigned lineno);
413
414+#define grub_calloc(nmemb, size) \
415+ grub_debug_calloc (GRUB_FILE, __LINE__, nmemb, size)
416+
417 #define grub_malloc(size) \
418 grub_debug_malloc (GRUB_FILE, __LINE__, size)
419
420@@ -63,6 +67,8 @@ void grub_mm_dump (unsigned lineno);
421 #define grub_free(ptr) \
422 grub_debug_free (GRUB_FILE, __LINE__, ptr)
423
424+void *EXPORT_FUNC(grub_debug_calloc) (const char *file, int line,
425+ grub_size_t nmemb, grub_size_t size);
426 void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
427 grub_size_t size);
428 void *EXPORT_FUNC(grub_debug_zalloc) (const char *file, int line,
429
430From 65dfa11751111173ce6f492afce13d4a2c2b006c Mon Sep 17 00:00:00 2001
431From: Peter Jones <pjones@redhat.com>
432Date: Mon, 15 Jun 2020 12:26:01 -0400
433Subject: calloc: Use calloc() at most places
434
435This modifies most of the places we do some form of:
436
437 X = malloc(Y * Z);
438
439to use calloc(Y, Z) instead.
440
441Among other issues, this fixes:
442 - allocation of integer overflow in grub_png_decode_image_header()
443 reported by Chris Coulson,
444 - allocation of integer overflow in luks_recover_key()
445 reported by Chris Coulson,
446 - allocation of integer overflow in grub_lvm_detect()
447 reported by Chris Coulson.
448
449Fixes: CVE-2020-14308
450
451Signed-off-by: Peter Jones <pjones@redhat.com>
452Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
453---
454 grub-core/bus/usb/usbhub.c | 8 ++++----
455 grub-core/commands/efi/lsefisystab.c | 3 ++-
456 grub-core/commands/legacycfg.c | 6 +++---
457 grub-core/commands/menuentry.c | 2 +-
458 grub-core/commands/nativedisk.c | 2 +-
459 grub-core/commands/parttool.c | 12 +++++++++---
460 grub-core/commands/regexp.c | 2 +-
461 grub-core/commands/search_wrap.c | 2 +-
462 grub-core/disk/diskfilter.c | 4 ++--
463 grub-core/disk/ieee1275/ofdisk.c | 2 +-
464 grub-core/disk/ldm.c | 14 +++++++-------
465 grub-core/disk/luks.c | 2 +-
466 grub-core/disk/lvm.c | 8 ++++----
467 grub-core/disk/xen/xendisk.c | 2 +-
468 grub-core/efiemu/loadcore.c | 2 +-
469 grub-core/efiemu/mm.c | 6 +++---
470 grub-core/font/font.c | 3 +--
471 grub-core/fs/affs.c | 6 +++---
472 grub-core/fs/btrfs.c | 6 +++---
473 grub-core/fs/hfs.c | 2 +-
474 grub-core/fs/hfsplus.c | 6 +++---
475 grub-core/fs/iso9660.c | 2 +-
476 grub-core/fs/ntfs.c | 4 ++--
477 grub-core/fs/sfs.c | 2 +-
478 grub-core/fs/tar.c | 2 +-
479 grub-core/fs/udf.c | 4 ++--
480 grub-core/fs/zfs/zfs.c | 4 ++--
481 grub-core/gfxmenu/gui_string_util.c | 2 +-
482 grub-core/gfxmenu/widget-box.c | 4 ++--
483 grub-core/io/gzio.c | 2 +-
484 grub-core/kern/efi/efi.c | 6 +++---
485 grub-core/kern/emu/hostdisk.c | 2 +-
486 grub-core/kern/fs.c | 2 +-
487 grub-core/kern/misc.c | 2 +-
488 grub-core/kern/parser.c | 2 +-
489 grub-core/kern/uboot/uboot.c | 2 +-
490 grub-core/lib/libgcrypt/cipher/ac.c | 8 ++++----
491 grub-core/lib/libgcrypt/cipher/primegen.c | 4 ++--
492 grub-core/lib/libgcrypt/cipher/pubkey.c | 4 ++--
493 grub-core/lib/priority_queue.c | 2 +-
494 grub-core/lib/reed_solomon.c | 7 +++----
495 grub-core/lib/relocator.c | 10 +++++-----
496 grub-core/lib/zstd/fse_decompress.c | 2 +-
497 grub-core/loader/arm/linux.c | 2 +-
498 grub-core/loader/efi/chainloader.c | 2 +-
499 grub-core/loader/i386/bsdXX.c | 2 +-
500 grub-core/loader/i386/xnu.c | 4 ++--
501 grub-core/loader/macho.c | 2 +-
502 grub-core/loader/multiboot_elfxx.c | 2 +-
503 grub-core/loader/xnu.c | 2 +-
504 grub-core/mmap/mmap.c | 4 ++--
505 grub-core/net/bootp.c | 2 +-
506 grub-core/net/dns.c | 10 +++++-----
507 grub-core/net/net.c | 4 ++--
508 grub-core/normal/charset.c | 10 +++++-----
509 grub-core/normal/cmdline.c | 14 +++++++-------
510 grub-core/normal/menu_entry.c | 14 +++++++-------
511 grub-core/normal/menu_text.c | 4 ++--
512 grub-core/normal/term.c | 4 ++--
513 grub-core/osdep/linux/getroot.c | 6 +++---
514 grub-core/osdep/windows/getroot.c | 2 +-
515 grub-core/osdep/windows/hostdisk.c | 4 ++--
516 grub-core/osdep/windows/init.c | 2 +-
517 grub-core/osdep/windows/platform.c | 4 ++--
518 grub-core/osdep/windows/relpath.c | 2 +-
519 grub-core/partmap/gpt.c | 2 +-
520 grub-core/partmap/msdos.c | 2 +-
521 grub-core/script/execute.c | 2 +-
522 grub-core/tests/fake_input.c | 2 +-
523 grub-core/tests/video_checksum.c | 6 +++---
524 grub-core/video/capture.c | 2 +-
525 grub-core/video/emu/sdl.c | 2 +-
526 grub-core/video/i386/pc/vga.c | 2 +-
527 grub-core/video/readers/png.c | 2 +-
528 include/grub/unicode.h | 4 ++--
529 util/getroot.c | 2 +-
530 util/grub-file.c | 2 +-
531 util/grub-fstest.c | 4 ++--
532 util/grub-install-common.c | 2 +-
533 util/grub-install.c | 4 ++--
534 util/grub-mkimagexx.c | 6 ++----
535 util/grub-mkrescue.c | 4 ++--
536 util/grub-mkstandalone.c | 2 +-
537 util/grub-pe2elf.c | 12 +++++-------
538 util/grub-probe.c | 4 ++--
539 85 files changed, 175 insertions(+), 174 deletions(-)
540
541diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
542index 34a7ff1b5..a06cce302 100644
543--- a/grub-core/bus/usb/usbhub.c
544+++ b/grub-core/bus/usb/usbhub.c
545@@ -149,8 +149,8 @@ grub_usb_add_hub (grub_usb_device_t dev)
546 grub_usb_set_configuration (dev, 1);
547
548 dev->nports = hubdesc.portcnt;
549- dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0]));
550- dev->ports = grub_zalloc (dev->nports * sizeof (dev->ports[0]));
551+ dev->children = grub_calloc (hubdesc.portcnt, sizeof (dev->children[0]));
552+ dev->ports = grub_calloc (dev->nports, sizeof (dev->ports[0]));
553 if (!dev->children || !dev->ports)
554 {
555 grub_free (dev->children);
556@@ -268,8 +268,8 @@ grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *d
557
558 /* Query the number of ports the root Hub has. */
559 hub->nports = controller->dev->hubports (controller);
560- hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports);
561- hub->ports = grub_zalloc (sizeof (hub->ports[0]) * hub->nports);
562+ hub->devices = grub_calloc (hub->nports, sizeof (hub->devices[0]));
563+ hub->ports = grub_calloc (hub->nports, sizeof (hub->ports[0]));
564 if (!hub->devices || !hub->ports)
565 {
566 grub_free (hub->devices);
567diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c
568index df1030221..cd81507f5 100644
569--- a/grub-core/commands/efi/lsefisystab.c
570+++ b/grub-core/commands/efi/lsefisystab.c
571@@ -71,7 +71,8 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)),
572 grub_printf ("Vendor: ");
573
574 for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++);
575- vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1);
576+ /* Allocate extra 3 bytes to simplify math. */
577+ vendor = grub_calloc (4, vendor_utf16 - st->firmware_vendor + 1);
578 if (!vendor)
579 return grub_errno;
580 *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor,
581diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
582index db7a8f002..5e3ec0d5e 100644
583--- a/grub-core/commands/legacycfg.c
584+++ b/grub-core/commands/legacycfg.c
585@@ -314,7 +314,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
586 if (argc < 2)
587 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
588
589- cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
590+ cutargs = grub_calloc (argc - 1, sizeof (cutargs[0]));
591 if (!cutargs)
592 return grub_errno;
593 cutargc = argc - 1;
594@@ -436,7 +436,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
595 {
596 char rbuf[3] = "-r";
597 bsdargc = cutargc + 2;
598- bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
599+ bsdargs = grub_calloc (bsdargc, sizeof (bsdargs[0]));
600 if (!bsdargs)
601 {
602 err = grub_errno;
603@@ -559,7 +559,7 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
604 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
605 "module");
606
607- newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
608+ newargs = grub_calloc (argc + 1, sizeof (newargs[0]));
609 if (!newargs)
610 return grub_errno;
611 grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
612diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
613index 2c5363da7..9164df744 100644
614--- a/grub-core/commands/menuentry.c
615+++ b/grub-core/commands/menuentry.c
616@@ -154,7 +154,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
617 goto fail;
618
619 /* Save argc, args to pass as parameters to block arg later. */
620- menu_args = grub_malloc (sizeof (char*) * (argc + 1));
621+ menu_args = grub_calloc (argc + 1, sizeof (char *));
622 if (! menu_args)
623 goto fail;
624
625diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c
626index 699447d11..7c8f97f6a 100644
627--- a/grub-core/commands/nativedisk.c
628+++ b/grub-core/commands/nativedisk.c
629@@ -195,7 +195,7 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
630 else
631 path_prefix = prefix;
632
633- mods = grub_malloc (argc * sizeof (mods[0]));
634+ mods = grub_calloc (argc, sizeof (mods[0]));
635 if (!mods)
636 return grub_errno;
637
638diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c
639index 22b46b187..051e31320 100644
640--- a/grub-core/commands/parttool.c
641+++ b/grub-core/commands/parttool.c
642@@ -59,7 +59,13 @@ grub_parttool_register(const char *part_name,
643 for (nargs = 0; args[nargs].name != 0; nargs++);
644 cur->nargs = nargs;
645 cur->args = (struct grub_parttool_argdesc *)
646- grub_malloc ((nargs + 1) * sizeof (struct grub_parttool_argdesc));
647+ grub_calloc (nargs + 1, sizeof (struct grub_parttool_argdesc));
648+ if (!cur->args)
649+ {
650+ grub_free (cur);
651+ curhandle--;
652+ return -1;
653+ }
654 grub_memcpy (cur->args, args,
655 (nargs + 1) * sizeof (struct grub_parttool_argdesc));
656
657@@ -257,7 +263,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
658 return err;
659 }
660
661- parsed = (int *) grub_zalloc (argc * sizeof (int));
662+ parsed = (int *) grub_calloc (argc, sizeof (int));
663
664 for (i = 1; i < argc; i++)
665 if (! parsed[i])
666@@ -290,7 +296,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
667 }
668 ptool = cur;
669 pargs = (struct grub_parttool_args *)
670- grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args));
671+ grub_calloc (ptool->nargs, sizeof (struct grub_parttool_args));
672 for (j = i; j < argc; j++)
673 if (! parsed[j])
674 {
675diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c
676index f00b184c8..4019164f3 100644
677--- a/grub-core/commands/regexp.c
678+++ b/grub-core/commands/regexp.c
679@@ -116,7 +116,7 @@ grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
680 if (ret)
681 goto fail;
682
683- matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1));
684+ matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches));
685 if (! matches)
686 goto fail;
687
688diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
689index d7fd26b94..47fc8eb99 100644
690--- a/grub-core/commands/search_wrap.c
691+++ b/grub-core/commands/search_wrap.c
692@@ -122,7 +122,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
693 for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
694 nhints++;
695
696- hints = grub_malloc (sizeof (hints[0]) * nhints);
697+ hints = grub_calloc (nhints, sizeof (hints[0]));
698 if (!hints)
699 return grub_errno;
700 j = 0;
701diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
702index c3b578acf..68ca9e0be 100644
703--- a/grub-core/disk/diskfilter.c
704+++ b/grub-core/disk/diskfilter.c
705@@ -1134,7 +1134,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
706 array->lvs->segments->node_count = nmemb;
707 array->lvs->segments->raid_member_size = disk_size;
708 array->lvs->segments->nodes
709- = grub_zalloc (nmemb * sizeof (array->lvs->segments->nodes[0]));
710+ = grub_calloc (nmemb, sizeof (array->lvs->segments->nodes[0]));
711 array->lvs->segments->stripe_size = stripe_size;
712 for (i = 0; i < nmemb; i++)
713 {
714@@ -1226,7 +1226,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
715 grub_partition_t p;
716 for (p = disk->partition; p; p = p->parent)
717 s++;
718- pv->partmaps = xmalloc (s * sizeof (pv->partmaps[0]));
719+ pv->partmaps = xcalloc (s, sizeof (pv->partmaps[0]));
720 s = 0;
721 for (p = disk->partition; p; p = p->parent)
722 pv->partmaps[s++] = xstrdup (p->partmap->name);
723diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
724index f73257e66..03674cb47 100644
725--- a/grub-core/disk/ieee1275/ofdisk.c
726+++ b/grub-core/disk/ieee1275/ofdisk.c
727@@ -297,7 +297,7 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
728 /* Power machines documentation specify 672 as maximum SAS disks in
729 one system. Using a slightly larger value to be safe. */
730 table_size = 768;
731- table = grub_malloc (table_size * sizeof (grub_uint64_t));
732+ table = grub_calloc (table_size, sizeof (grub_uint64_t));
733
734 if (!table)
735 {
736diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
737index 2a22d2d6c..e6323701a 100644
738--- a/grub-core/disk/ldm.c
739+++ b/grub-core/disk/ldm.c
740@@ -323,8 +323,8 @@ make_vg (grub_disk_t disk,
741 lv->segments->type = GRUB_DISKFILTER_MIRROR;
742 lv->segments->node_count = 0;
743 lv->segments->node_alloc = 8;
744- lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes)
745- * lv->segments->node_alloc);
746+ lv->segments->nodes = grub_calloc (lv->segments->node_alloc,
747+ sizeof (*lv->segments->nodes));
748 if (!lv->segments->nodes)
749 goto fail2;
750 ptr = vblk[i].dynamic;
751@@ -543,8 +543,8 @@ make_vg (grub_disk_t disk,
752 {
753 comp->segment_alloc = 8;
754 comp->segment_count = 0;
755- comp->segments = grub_malloc (sizeof (*comp->segments)
756- * comp->segment_alloc);
757+ comp->segments = grub_calloc (comp->segment_alloc,
758+ sizeof (*comp->segments));
759 if (!comp->segments)
760 goto fail2;
761 }
762@@ -590,8 +590,8 @@ make_vg (grub_disk_t disk,
763 }
764 comp->segments->node_count = read_int (ptr + 1, *ptr);
765 comp->segments->node_alloc = comp->segments->node_count;
766- comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes)
767- * comp->segments->node_alloc);
768+ comp->segments->nodes = grub_calloc (comp->segments->node_alloc,
769+ sizeof (*comp->segments->nodes));
770 if (!lv->segments->nodes)
771 goto fail2;
772 }
773@@ -1017,7 +1017,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
774 *nsectors = lv->size;
775 if (*nsectors > max_nsectors)
776 *nsectors = max_nsectors;
777- *sectors = grub_malloc (*nsectors * sizeof (**sectors));
778+ *sectors = grub_calloc (*nsectors, sizeof (**sectors));
779 if (!*sectors)
780 return grub_errno;
781 for (i = 0; i < *nsectors; i++)
782diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
783index 86c50c612..18b3a8bb1 100644
784--- a/grub-core/disk/luks.c
785+++ b/grub-core/disk/luks.c
786@@ -336,7 +336,7 @@ luks_recover_key (grub_disk_t source,
787 && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
788 max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
789
790- split_key = grub_malloc (keysize * max_stripes);
791+ split_key = grub_calloc (keysize, max_stripes);
792 if (!split_key)
793 return grub_errno;
794
795diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
796index 7b265c780..d1df640b3 100644
797--- a/grub-core/disk/lvm.c
798+++ b/grub-core/disk/lvm.c
799@@ -173,7 +173,7 @@ grub_lvm_detect (grub_disk_t disk,
800 first one. */
801
802 /* Allocate buffer space for the circular worst-case scenario. */
803- metadatabuf = grub_malloc (2 * mda_size);
804+ metadatabuf = grub_calloc (2, mda_size);
805 if (! metadatabuf)
806 goto fail;
807
808@@ -426,7 +426,7 @@ grub_lvm_detect (grub_disk_t disk,
809 #endif
810 goto lvs_fail;
811 }
812- lv->segments = grub_zalloc (sizeof (*seg) * lv->segment_count);
813+ lv->segments = grub_calloc (lv->segment_count, sizeof (*seg));
814 seg = lv->segments;
815
816 for (i = 0; i < lv->segment_count; i++)
817@@ -483,8 +483,8 @@ grub_lvm_detect (grub_disk_t disk,
818 if (seg->node_count != 1)
819 seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
820
821- seg->nodes = grub_zalloc (sizeof (*stripe)
822- * seg->node_count);
823+ seg->nodes = grub_calloc (seg->node_count,
824+ sizeof (*stripe));
825 stripe = seg->nodes;
826
827 p = grub_strstr (p, "stripes = [");
828diff --git a/grub-core/disk/xen/xendisk.c b/grub-core/disk/xen/xendisk.c
829index 48476cbbf..d6612eebd 100644
830--- a/grub-core/disk/xen/xendisk.c
831+++ b/grub-core/disk/xen/xendisk.c
832@@ -426,7 +426,7 @@ grub_xendisk_init (void)
833 if (!ctr)
834 return;
835
836- virtdisks = grub_malloc (ctr * sizeof (virtdisks[0]));
837+ virtdisks = grub_calloc (ctr, sizeof (virtdisks[0]));
838 if (!virtdisks)
839 return;
840 if (grub_xenstore_dir ("device/vbd", fill, &ctr))
841diff --git a/grub-core/efiemu/loadcore.c b/grub-core/efiemu/loadcore.c
842index 44085ef81..2b924623f 100644
843--- a/grub-core/efiemu/loadcore.c
844+++ b/grub-core/efiemu/loadcore.c
845@@ -201,7 +201,7 @@ grub_efiemu_count_symbols (const Elf_Ehdr *e)
846
847 grub_efiemu_nelfsyms = (unsigned) s->sh_size / (unsigned) s->sh_entsize;
848 grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *)
849- grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms);
850+ grub_calloc (grub_efiemu_nelfsyms, sizeof (struct grub_efiemu_elf_sym));
851
852 /* Relocators */
853 for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
854diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c
855index 52a032f7b..9b8e0d0ad 100644
856--- a/grub-core/efiemu/mm.c
857+++ b/grub-core/efiemu/mm.c
858@@ -554,11 +554,11 @@ grub_efiemu_mmap_sort_and_uniq (void)
859 /* Initialize variables*/
860 grub_memset (present, 0, sizeof (int) * GRUB_EFI_MAX_MEMORY_TYPE);
861 scanline_events = (struct grub_efiemu_mmap_scan *)
862- grub_malloc (sizeof (struct grub_efiemu_mmap_scan) * 2 * mmap_num);
863+ grub_calloc (mmap_num, sizeof (struct grub_efiemu_mmap_scan) * 2);
864
865 /* Number of chunks can't increase more than by factor of 2 */
866 result = (grub_efi_memory_descriptor_t *)
867- grub_malloc (sizeof (grub_efi_memory_descriptor_t) * 2 * mmap_num);
868+ grub_calloc (mmap_num, sizeof (grub_efi_memory_descriptor_t) * 2);
869 if (!result || !scanline_events)
870 {
871 grub_free (result);
872@@ -660,7 +660,7 @@ grub_efiemu_mm_do_alloc (void)
873
874 /* Preallocate mmap */
875 efiemu_mmap = (grub_efi_memory_descriptor_t *)
876- grub_malloc (mmap_reserved_size * sizeof (grub_efi_memory_descriptor_t));
877+ grub_calloc (mmap_reserved_size, sizeof (grub_efi_memory_descriptor_t));
878 if (!efiemu_mmap)
879 {
880 grub_efiemu_unload ();
881diff --git a/grub-core/font/font.c b/grub-core/font/font.c
882index 85a292557..8e118b315 100644
883--- a/grub-core/font/font.c
884+++ b/grub-core/font/font.c
885@@ -293,8 +293,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
886 font->num_chars = sect_length / FONT_CHAR_INDEX_ENTRY_SIZE;
887
888 /* Allocate the character index array. */
889- font->char_index = grub_malloc (font->num_chars
890- * sizeof (struct char_index_entry));
891+ font->char_index = grub_calloc (font->num_chars, sizeof (struct char_index_entry));
892 if (!font->char_index)
893 return 1;
894 font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
895diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
896index 6b6a2bc91..220b3712f 100644
897--- a/grub-core/fs/affs.c
898+++ b/grub-core/fs/affs.c
899@@ -301,7 +301,7 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
900 return 0;
901 }
902 latin1[symlink_size] = 0;
903- utf8 = grub_malloc (symlink_size * GRUB_MAX_UTF8_PER_LATIN1 + 1);
904+ utf8 = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, symlink_size);
905 if (!utf8)
906 {
907 grub_free (latin1);
908@@ -422,7 +422,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
909 return 1;
910 }
911
912- hashtable = grub_zalloc (data->htsize * sizeof (*hashtable));
913+ hashtable = grub_calloc (data->htsize, sizeof (*hashtable));
914 if (!hashtable)
915 return 1;
916
917@@ -628,7 +628,7 @@ grub_affs_label (grub_device_t device, char **label)
918 len = file.namelen;
919 if (len > sizeof (file.name))
920 len = sizeof (file.name);
921- *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
922+ *label = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, len);
923 if (*label)
924 *grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0';
925 }
926diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
927index 63f9657a6..4b8380439 100644
928--- a/grub-core/fs/btrfs.c
929+++ b/grub-core/fs/btrfs.c
930@@ -415,7 +415,7 @@ lower_bound (struct grub_btrfs_data *data,
931 {
932 desc->allocated = 16;
933 desc->depth = 0;
934- desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated);
935+ desc->data = grub_calloc (desc->allocated, sizeof (desc->data[0]));
936 if (!desc->data)
937 return grub_errno;
938 }
939@@ -754,7 +754,7 @@ raid56_read_retry (struct grub_btrfs_data *data,
940 grub_err_t ret = GRUB_ERR_OUT_OF_MEMORY;
941 grub_uint64_t i, failed_devices;
942
943- buffers = grub_zalloc (sizeof(*buffers) * nstripes);
944+ buffers = grub_calloc (nstripes, sizeof (*buffers));
945 if (!buffers)
946 goto cleanup;
947
948@@ -2167,7 +2167,7 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
949 *nsectors = 64 * 2 - 1;
950 if (*nsectors > max_nsectors)
951 *nsectors = max_nsectors;
952- *sectors = grub_malloc (*nsectors * sizeof (**sectors));
953+ *sectors = grub_calloc (*nsectors, sizeof (**sectors));
954 if (!*sectors)
955 return grub_errno;
956 for (i = 0; i < *nsectors; i++)
957diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
958index ac0a40990..3fe842b4d 100644
959--- a/grub-core/fs/hfs.c
960+++ b/grub-core/fs/hfs.c
961@@ -1360,7 +1360,7 @@ grub_hfs_label (grub_device_t device, char **label)
962 grub_size_t len = data->sblock.volname[0];
963 if (len > sizeof (data->sblock.volname) - 1)
964 len = sizeof (data->sblock.volname) - 1;
965- *label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1);
966+ *label = grub_calloc (MAX_UTF8_PER_MAC_ROMAN + 1, len);
967 if (*label)
968 macroman_to_utf8 (*label, data->sblock.volname + 1,
969 len + 1, 0);
970diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
971index 54786bb1c..dae43becc 100644
972--- a/grub-core/fs/hfsplus.c
973+++ b/grub-core/fs/hfsplus.c
974@@ -720,7 +720,7 @@ list_nodes (void *record, void *hook_arg)
975 if (! filename)
976 return 0;
977
978- keyname = grub_malloc (grub_be_to_cpu16 (catkey->namelen) * sizeof (*keyname));
979+ keyname = grub_calloc (grub_be_to_cpu16 (catkey->namelen), sizeof (*keyname));
980 if (!keyname)
981 {
982 grub_free (filename);
983@@ -1007,7 +1007,7 @@ grub_hfsplus_label (grub_device_t device, char **label)
984 grub_hfsplus_btree_recptr (&data->catalog_tree, node, ptr);
985
986 label_len = grub_be_to_cpu16 (catkey->namelen);
987- label_name = grub_malloc (label_len * sizeof (*label_name));
988+ label_name = grub_calloc (label_len, sizeof (*label_name));
989 if (!label_name)
990 {
991 grub_free (node);
992@@ -1029,7 +1029,7 @@ grub_hfsplus_label (grub_device_t device, char **label)
993 }
994 }
995
996- *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1);
997+ *label = grub_calloc (label_len, GRUB_MAX_UTF8_PER_UTF16 + 1);
998 if (! *label)
999 {
1000 grub_free (label_name);
1001diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
1002index 49c0c632b..4f1b52a55 100644
1003--- a/grub-core/fs/iso9660.c
1004+++ b/grub-core/fs/iso9660.c
1005@@ -331,7 +331,7 @@ grub_iso9660_convert_string (grub_uint8_t *us, int len)
1006 int i;
1007 grub_uint16_t t[MAX_NAMELEN / 2 + 1];
1008
1009- p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1);
1010+ p = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1);
1011 if (! p)
1012 return NULL;
1013
1014diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
1015index fc4e1f678..2f34f76da 100644
1016--- a/grub-core/fs/ntfs.c
1017+++ b/grub-core/fs/ntfs.c
1018@@ -556,8 +556,8 @@ get_utf8 (grub_uint8_t *in, grub_size_t len)
1019 grub_uint16_t *tmp;
1020 grub_size_t i;
1021
1022- buf = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1);
1023- tmp = grub_malloc (len * sizeof (tmp[0]));
1024+ buf = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1);
1025+ tmp = grub_calloc (len, sizeof (tmp[0]));
1026 if (!buf || !tmp)
1027 {
1028 grub_free (buf);
1029diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
1030index 50c1fe72f..90f7fb379 100644
1031--- a/grub-core/fs/sfs.c
1032+++ b/grub-core/fs/sfs.c
1033@@ -266,7 +266,7 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
1034 node->next_extent = node->block;
1035 node->cache_size = 0;
1036
1037- node->cache = grub_malloc (sizeof (node->cache[0]) * cache_size);
1038+ node->cache = grub_calloc (cache_size, sizeof (node->cache[0]));
1039 if (!node->cache)
1040 {
1041 grub_errno = 0;
1042diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c
1043index 7d63e0c99..c551ed6b5 100644
1044--- a/grub-core/fs/tar.c
1045+++ b/grub-core/fs/tar.c
1046@@ -120,7 +120,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name,
1047 if (data->linkname_alloc < linksize + 1)
1048 {
1049 char *n;
1050- n = grub_malloc (2 * (linksize + 1));
1051+ n = grub_calloc (2, linksize + 1);
1052 if (!n)
1053 return grub_errno;
1054 grub_free (data->linkname);
1055diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
1056index dc8b6e2d1..a83761674 100644
1057--- a/grub-core/fs/udf.c
1058+++ b/grub-core/fs/udf.c
1059@@ -873,7 +873,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
1060 {
1061 unsigned i;
1062 utf16len = sz - 1;
1063- utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
1064+ utf16 = grub_calloc (utf16len, sizeof (utf16[0]));
1065 if (!utf16)
1066 return NULL;
1067 for (i = 0; i < utf16len; i++)
1068@@ -883,7 +883,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
1069 {
1070 unsigned i;
1071 utf16len = (sz - 1) / 2;
1072- utf16 = grub_malloc (utf16len * sizeof (utf16[0]));
1073+ utf16 = grub_calloc (utf16len, sizeof (utf16[0]));
1074 if (!utf16)
1075 return NULL;
1076 for (i = 0; i < utf16len; i++)
1077diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
1078index 2f72e42bf..381dde556 100644
1079--- a/grub-core/fs/zfs/zfs.c
1080+++ b/grub-core/fs/zfs/zfs.c
1081@@ -3325,7 +3325,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol,
1082 }
1083 subvol->nkeys = 0;
1084 zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data);
1085- subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0]));
1086+ subvol->keyring = grub_calloc (subvol->nkeys, sizeof (subvol->keyring[0]));
1087 if (!subvol->keyring)
1088 {
1089 grub_free (fsname);
1090@@ -4336,7 +4336,7 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)),
1091 *nsectors = (VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS);
1092 if (*nsectors > max_nsectors)
1093 *nsectors = max_nsectors;
1094- *sectors = grub_malloc (*nsectors * sizeof (**sectors));
1095+ *sectors = grub_calloc (*nsectors, sizeof (**sectors));
1096 if (!*sectors)
1097 return grub_errno;
1098 for (i = 0; i < *nsectors; i++)
1099diff --git a/grub-core/gfxmenu/gui_string_util.c b/grub-core/gfxmenu/gui_string_util.c
1100index a9a415e31..ba1e1eab3 100644
1101--- a/grub-core/gfxmenu/gui_string_util.c
1102+++ b/grub-core/gfxmenu/gui_string_util.c
1103@@ -55,7 +55,7 @@ canonicalize_path (const char *path)
1104 if (*p == '/')
1105 components++;
1106
1107- char **path_array = grub_malloc (components * sizeof (*path_array));
1108+ char **path_array = grub_calloc (components, sizeof (*path_array));
1109 if (! path_array)
1110 return 0;
1111
1112diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c
1113index b60602889..470597ded 100644
1114--- a/grub-core/gfxmenu/widget-box.c
1115+++ b/grub-core/gfxmenu/widget-box.c
1116@@ -303,10 +303,10 @@ grub_gfxmenu_create_box (const char *pixmaps_prefix,
1117 box->content_height = 0;
1118 box->raw_pixmaps =
1119 (struct grub_video_bitmap **)
1120- grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *));
1121+ grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *));
1122 box->scaled_pixmaps =
1123 (struct grub_video_bitmap **)
1124- grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *));
1125+ grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *));
1126
1127 /* Initialize all pixmap pointers to NULL so that proper destruction can
1128 be performed if an error is encountered partway through construction. */
1129diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
1130index 6208a9763..43d98a7bd 100644
1131--- a/grub-core/io/gzio.c
1132+++ b/grub-core/io/gzio.c
1133@@ -554,7 +554,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */
1134 z = 1 << j; /* table entries for j-bit table */
1135
1136 /* allocate and link in new table */
1137- q = (struct huft *) grub_zalloc ((z + 1) * sizeof (struct huft));
1138+ q = (struct huft *) grub_calloc (z + 1, sizeof (struct huft));
1139 if (! q)
1140 {
1141 if (h)
1142diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
1143index 96204e39b..ad170c7ce 100644
1144--- a/grub-core/kern/efi/efi.c
1145+++ b/grub-core/kern/efi/efi.c
1146@@ -202,7 +202,7 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
1147
1148 len = grub_strlen (var);
1149 len16 = len * GRUB_MAX_UTF16_PER_UTF8;
1150- var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
1151+ var16 = grub_calloc (len16 + 1, sizeof (var16[0]));
1152 if (!var16)
1153 return grub_errno;
1154 len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
1155@@ -237,7 +237,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
1156
1157 len = grub_strlen (var);
1158 len16 = len * GRUB_MAX_UTF16_PER_UTF8;
1159- var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
1160+ var16 = grub_calloc (len16 + 1, sizeof (var16[0]));
1161 if (!var16)
1162 return NULL;
1163 len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
1164@@ -411,7 +411,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
1165 while (len > 0 && fp->path_name[len - 1] == 0)
1166 len--;
1167
1168- dup_name = grub_malloc (len * sizeof (*dup_name));
1169+ dup_name = grub_calloc (len, sizeof (*dup_name));
1170 if (!dup_name)
1171 {
1172 grub_free (name);
1173diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c
1174index 8ac523953..f90b6c9ce 100644
1175--- a/grub-core/kern/emu/hostdisk.c
1176+++ b/grub-core/kern/emu/hostdisk.c
1177@@ -627,7 +627,7 @@ static char *
1178 grub_util_path_concat_real (size_t n, int ext, va_list ap)
1179 {
1180 size_t totlen = 0;
1181- char **l = xmalloc ((n + ext) * sizeof (l[0]));
1182+ char **l = xcalloc (n + ext, sizeof (l[0]));
1183 char *r, *p, *pi;
1184 size_t i;
1185 int first = 1;
1186diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c
1187index 2b85f4950..f90be6566 100644
1188--- a/grub-core/kern/fs.c
1189+++ b/grub-core/kern/fs.c
1190@@ -151,7 +151,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name)
1191 while (p);
1192
1193 /* Allocate a block list. */
1194- blocks = grub_zalloc (sizeof (struct grub_fs_block) * (num + 1));
1195+ blocks = grub_calloc (num + 1, sizeof (struct grub_fs_block));
1196 if (! blocks)
1197 return 0;
1198
1199diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
1200index 18cad5803..83c068d61 100644
1201--- a/grub-core/kern/misc.c
1202+++ b/grub-core/kern/misc.c
1203@@ -691,7 +691,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
1204 args->ptr = args->prealloc;
1205 else
1206 {
1207- args->ptr = grub_malloc (args->count * sizeof (args->ptr[0]));
1208+ args->ptr = grub_calloc (args->count, sizeof (args->ptr[0]));
1209 if (!args->ptr)
1210 {
1211 grub_errno = GRUB_ERR_NONE;
1212diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
1213index 78175aac2..619db3122 100644
1214--- a/grub-core/kern/parser.c
1215+++ b/grub-core/kern/parser.c
1216@@ -213,7 +213,7 @@ grub_parser_split_cmdline (const char *cmdline,
1217 return grub_errno;
1218 grub_memcpy (args, buffer, bp - buffer);
1219
1220- *argv = grub_malloc (sizeof (char *) * (*argc + 1));
1221+ *argv = grub_calloc (*argc + 1, sizeof (char *));
1222 if (!*argv)
1223 {
1224 grub_free (args);
1225diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c
1226index be4816fe6..aac8f9ae1 100644
1227--- a/grub-core/kern/uboot/uboot.c
1228+++ b/grub-core/kern/uboot/uboot.c
1229@@ -133,7 +133,7 @@ grub_uboot_dev_enum (void)
1230 return num_devices;
1231
1232 max_devices = 2;
1233- enum_devices = grub_malloc (sizeof(struct device_info) * max_devices);
1234+ enum_devices = grub_calloc (max_devices, sizeof(struct device_info));
1235 if (!enum_devices)
1236 return 0;
1237
1238diff --git a/grub-core/lib/libgcrypt/cipher/ac.c b/grub-core/lib/libgcrypt/cipher/ac.c
1239index f5e946a2d..63f6fcd11 100644
1240--- a/grub-core/lib/libgcrypt/cipher/ac.c
1241+++ b/grub-core/lib/libgcrypt/cipher/ac.c
1242@@ -185,7 +185,7 @@ ac_data_mpi_copy (gcry_ac_mpi_t *data_mpis, unsigned int data_mpis_n,
1243 gcry_mpi_t mpi;
1244 char *label;
1245
1246- data_mpis_new = gcry_malloc (sizeof (*data_mpis_new) * data_mpis_n);
1247+ data_mpis_new = gcry_calloc (data_mpis_n, sizeof (*data_mpis_new));
1248 if (! data_mpis_new)
1249 {
1250 err = gcry_error_from_errno (errno);
1251@@ -572,7 +572,7 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp,
1252 }
1253
1254 /* Add MPI list. */
1255- arg_list = gcry_malloc (sizeof (*arg_list) * (data_n + 1));
1256+ arg_list = gcry_calloc (data_n + 1, sizeof (*arg_list));
1257 if (! arg_list)
1258 {
1259 err = gcry_error_from_errno (errno);
1260@@ -1283,7 +1283,7 @@ ac_data_construct (const char *identifier, int include_flags,
1261 /* We build a list of arguments to pass to
1262 gcry_sexp_build_array(). */
1263 data_length = _gcry_ac_data_length (data);
1264- arg_list = gcry_malloc (sizeof (*arg_list) * (data_length * 2));
1265+ arg_list = gcry_calloc (data_length, sizeof (*arg_list) * 2);
1266 if (! arg_list)
1267 {
1268 err = gcry_error_from_errno (errno);
1269@@ -1593,7 +1593,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits,
1270 arg_list_n += 2;
1271
1272 /* Allocate list. */
1273- arg_list = gcry_malloc (sizeof (*arg_list) * arg_list_n);
1274+ arg_list = gcry_calloc (arg_list_n, sizeof (*arg_list));
1275 if (! arg_list)
1276 {
1277 err = gcry_error_from_errno (errno);
1278diff --git a/grub-core/lib/libgcrypt/cipher/primegen.c b/grub-core/lib/libgcrypt/cipher/primegen.c
1279index 2788e349f..b12e79b19 100644
1280--- a/grub-core/lib/libgcrypt/cipher/primegen.c
1281+++ b/grub-core/lib/libgcrypt/cipher/primegen.c
1282@@ -383,7 +383,7 @@ prime_generate_internal (int need_q_factor,
1283 }
1284
1285 /* Allocate an array to track pool usage. */
1286- pool_in_use = gcry_malloc (n * sizeof *pool_in_use);
1287+ pool_in_use = gcry_calloc (n, sizeof *pool_in_use);
1288 if (!pool_in_use)
1289 {
1290 err = gpg_err_code_from_errno (errno);
1291@@ -765,7 +765,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel,
1292 if (nbits < 16)
1293 log_fatal ("can't generate a prime with less than %d bits\n", 16);
1294
1295- mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods );
1296+ mods = gcry_xcalloc( no_of_small_prime_numbers, sizeof *mods);
1297 /* Make nbits fit into gcry_mpi_t implementation. */
1298 val_2 = mpi_alloc_set_ui( 2 );
1299 val_3 = mpi_alloc_set_ui( 3);
1300diff --git a/grub-core/lib/libgcrypt/cipher/pubkey.c b/grub-core/lib/libgcrypt/cipher/pubkey.c
1301index 910982141..ca087ad75 100644
1302--- a/grub-core/lib/libgcrypt/cipher/pubkey.c
1303+++ b/grub-core/lib/libgcrypt/cipher/pubkey.c
1304@@ -2941,7 +2941,7 @@ gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
1305 * array to a format string, so we have to do it this way :-(. */
1306 /* FIXME: There is now such a format specifier, so we can
1307 change the code to be more clear. */
1308- arg_list = malloc (nelem * sizeof *arg_list);
1309+ arg_list = calloc (nelem, sizeof *arg_list);
1310 if (!arg_list)
1311 {
1312 rc = gpg_err_code_from_syserror ();
1313@@ -3233,7 +3233,7 @@ gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
1314 }
1315 strcpy (p, "))");
1316
1317- arg_list = malloc (nelem * sizeof *arg_list);
1318+ arg_list = calloc (nelem, sizeof *arg_list);
1319 if (!arg_list)
1320 {
1321 rc = gpg_err_code_from_syserror ();
1322diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c
1323index 659be0b7f..7d5e7c05a 100644
1324--- a/grub-core/lib/priority_queue.c
1325+++ b/grub-core/lib/priority_queue.c
1326@@ -92,7 +92,7 @@ grub_priority_queue_new (grub_size_t elsize,
1327 {
1328 struct grub_priority_queue *ret;
1329 void *els;
1330- els = grub_malloc (elsize * 8);
1331+ els = grub_calloc (8, elsize);
1332 if (!els)
1333 return 0;
1334 ret = (struct grub_priority_queue *) grub_malloc (sizeof (*ret));
1335diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c
1336index ee9fa7b4f..467305b46 100644
1337--- a/grub-core/lib/reed_solomon.c
1338+++ b/grub-core/lib/reed_solomon.c
1339@@ -20,6 +20,7 @@
1340 #include <stdio.h>
1341 #include <string.h>
1342 #include <stdlib.h>
1343+#define xcalloc calloc
1344 #define xmalloc malloc
1345 #define grub_memset memset
1346 #define grub_memcpy memcpy
1347@@ -158,11 +159,9 @@ rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs)
1348 gf_single_t *rs_polynomial;
1349 int i, j;
1350 gf_single_t *m;
1351- m = xmalloc ((s + rs) * sizeof (gf_single_t));
1352+ m = xcalloc (s + rs, sizeof (gf_single_t));
1353 grub_memcpy (m, data, s * sizeof (gf_single_t));
1354- grub_memset (m + s, 0, rs * sizeof (gf_single_t));
1355- rs_polynomial = xmalloc ((rs + 1) * sizeof (gf_single_t));
1356- grub_memset (rs_polynomial, 0, (rs + 1) * sizeof (gf_single_t));
1357+ rs_polynomial = xcalloc (rs + 1, sizeof (gf_single_t));
1358 rs_polynomial[rs] = 1;
1359 /* Multiply with X - a^r */
1360 for (j = 0; j < rs; j++)
1361diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
1362index ea3ebc719..5847aac36 100644
1363--- a/grub-core/lib/relocator.c
1364+++ b/grub-core/lib/relocator.c
1365@@ -495,9 +495,9 @@ malloc_in_range (struct grub_relocator *rel,
1366 }
1367 #endif
1368
1369- eventt = grub_malloc (maxevents * sizeof (events[0]));
1370+ eventt = grub_calloc (maxevents, sizeof (events[0]));
1371 counter = grub_malloc ((DIGITSORT_MASK + 2) * sizeof (counter[0]));
1372- events = grub_malloc (maxevents * sizeof (events[0]));
1373+ events = grub_calloc (maxevents, sizeof (events[0]));
1374 if (!events || !eventt || !counter)
1375 {
1376 grub_dprintf ("relocator", "events or counter allocation failed %d\n",
1377@@ -963,7 +963,7 @@ malloc_in_range (struct grub_relocator *rel,
1378 #endif
1379 unsigned cural = 0;
1380 int oom = 0;
1381- res->subchunks = grub_malloc (sizeof (res->subchunks[0]) * nallocs);
1382+ res->subchunks = grub_calloc (nallocs, sizeof (res->subchunks[0]));
1383 if (!res->subchunks)
1384 oom = 1;
1385 res->nsubchunks = nallocs;
1386@@ -1562,8 +1562,8 @@ grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr,
1387 count[(chunk->src & 0xff) + 1]++;
1388 }
1389 }
1390- from = grub_malloc (nchunks * sizeof (sorted[0]));
1391- to = grub_malloc (nchunks * sizeof (sorted[0]));
1392+ from = grub_calloc (nchunks, sizeof (sorted[0]));
1393+ to = grub_calloc (nchunks, sizeof (sorted[0]));
1394 if (!from || !to)
1395 {
1396 grub_free (from);
1397diff --git a/grub-core/lib/zstd/fse_decompress.c b/grub-core/lib/zstd/fse_decompress.c
1398index 72bbead5b..2227b84bc 100644
1399--- a/grub-core/lib/zstd/fse_decompress.c
1400+++ b/grub-core/lib/zstd/fse_decompress.c
1401@@ -82,7 +82,7 @@
1402 FSE_DTable* FSE_createDTable (unsigned tableLog)
1403 {
1404 if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
1405- return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
1406+ return (FSE_DTable*)calloc( FSE_DTABLE_SIZE_U32(tableLog), sizeof (U32) );
1407 }
1408
1409 void FSE_freeDTable (FSE_DTable* dt)
1410diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
1411index 092e8e307..979d425df 100644
1412--- a/grub-core/loader/arm/linux.c
1413+++ b/grub-core/loader/arm/linux.c
1414@@ -82,7 +82,7 @@ linux_prepare_atag (void *target_atag)
1415
1416 /* some place for cmdline, initrd and terminator. */
1417 tmp_size = get_atag_size (atag_orig) + 20 + (arg_size) / 4;
1418- tmp_atag = grub_malloc (tmp_size * sizeof (grub_uint32_t));
1419+ tmp_atag = grub_calloc (tmp_size, sizeof (grub_uint32_t));
1420 if (!tmp_atag)
1421 return grub_errno;
1422
1423diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
1424index cd92ea3f2..daf8c6b54 100644
1425--- a/grub-core/loader/efi/chainloader.c
1426+++ b/grub-core/loader/efi/chainloader.c
1427@@ -116,7 +116,7 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
1428 fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
1429 fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
1430
1431- path_name = grub_malloc (len * GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
1432+ path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
1433 if (!path_name)
1434 return;
1435
1436diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c
1437index af6741d15..a8d8bf7da 100644
1438--- a/grub-core/loader/i386/bsdXX.c
1439+++ b/grub-core/loader/i386/bsdXX.c
1440@@ -48,7 +48,7 @@ read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
1441 if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
1442 return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
1443
1444- *shdr = grub_malloc ((grub_uint32_t) e->e_shnum * e->e_shentsize);
1445+ *shdr = grub_calloc (e->e_shnum, e->e_shentsize);
1446 if (! *shdr)
1447 return grub_errno;
1448
1449diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
1450index e64ed08f5..b7d176b5d 100644
1451--- a/grub-core/loader/i386/xnu.c
1452+++ b/grub-core/loader/i386/xnu.c
1453@@ -295,7 +295,7 @@ grub_xnu_devprop_add_property_utf8 (struct grub_xnu_devprop_device_descriptor *d
1454 return grub_errno;
1455
1456 len = grub_strlen (name);
1457- utf16 = grub_malloc (sizeof (grub_uint16_t) * len);
1458+ utf16 = grub_calloc (len, sizeof (grub_uint16_t));
1459 if (!utf16)
1460 {
1461 grub_free (utf8);
1462@@ -331,7 +331,7 @@ grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor *
1463 grub_uint16_t *utf16;
1464 grub_err_t err;
1465
1466- utf16 = grub_malloc (sizeof (grub_uint16_t) * namelen);
1467+ utf16 = grub_calloc (namelen, sizeof (grub_uint16_t));
1468 if (!utf16)
1469 return grub_errno;
1470 grub_memcpy (utf16, name, sizeof (grub_uint16_t) * namelen);
1471diff --git a/grub-core/loader/macho.c b/grub-core/loader/macho.c
1472index 085f9c689..05710c48e 100644
1473--- a/grub-core/loader/macho.c
1474+++ b/grub-core/loader/macho.c
1475@@ -97,7 +97,7 @@ grub_macho_file (grub_file_t file, const char *filename, int is_64bit)
1476 if (grub_file_seek (macho->file, sizeof (struct grub_macho_fat_header))
1477 == (grub_off_t) -1)
1478 goto fail;
1479- archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs);
1480+ archs = grub_calloc (narchs, sizeof (struct grub_macho_fat_arch));
1481 if (!archs)
1482 goto fail;
1483 if (grub_file_read (macho->file, archs,
1484diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
1485index 70cd1db51..cc6853692 100644
1486--- a/grub-core/loader/multiboot_elfxx.c
1487+++ b/grub-core/loader/multiboot_elfxx.c
1488@@ -217,7 +217,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
1489 {
1490 grub_uint8_t *shdr, *shdrptr;
1491
1492- shdr = grub_malloc ((grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize);
1493+ shdr = grub_calloc (ehdr->e_shnum, ehdr->e_shentsize);
1494 if (!shdr)
1495 return grub_errno;
1496
1497diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
1498index 7f74d1d6f..77d7060e1 100644
1499--- a/grub-core/loader/xnu.c
1500+++ b/grub-core/loader/xnu.c
1501@@ -800,7 +800,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)),
1502 if (grub_be_to_cpu32 (head.magic) == GRUB_MACHO_FAT_MAGIC)
1503 {
1504 narchs = grub_be_to_cpu32 (head.nfat_arch);
1505- archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs);
1506+ archs = grub_calloc (narchs, sizeof (struct grub_macho_fat_arch));
1507 if (! archs)
1508 {
1509 grub_file_close (file);
1510diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c
1511index 6a31cbae3..57b4e9a72 100644
1512--- a/grub-core/mmap/mmap.c
1513+++ b/grub-core/mmap/mmap.c
1514@@ -143,9 +143,9 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
1515
1516 /* Initialize variables. */
1517 ctx.scanline_events = (struct grub_mmap_scan *)
1518- grub_malloc (sizeof (struct grub_mmap_scan) * 2 * mmap_num);
1519+ grub_calloc (mmap_num, sizeof (struct grub_mmap_scan) * 2);
1520
1521- present = grub_zalloc (sizeof (present[0]) * current_priority);
1522+ present = grub_calloc (current_priority, sizeof (present[0]));
1523
1524 if (! ctx.scanline_events || !present)
1525 {
1526diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
1527index 558d97ba1..dd0ffcdae 100644
1528--- a/grub-core/net/bootp.c
1529+++ b/grub-core/net/bootp.c
1530@@ -1559,7 +1559,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
1531 if (ncards == 0)
1532 return grub_error (GRUB_ERR_NET_NO_CARD, N_("no network card found"));
1533
1534- ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
1535+ ifaces = grub_calloc (ncards, sizeof (ifaces[0]));
1536 if (!ifaces)
1537 return grub_errno;
1538
1539diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
1540index 5d9afe093..e332d5eb4 100644
1541--- a/grub-core/net/dns.c
1542+++ b/grub-core/net/dns.c
1543@@ -285,8 +285,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
1544 ptr++;
1545 ptr += 4;
1546 }
1547- *data->addresses = grub_malloc (sizeof ((*data->addresses)[0])
1548- * grub_be_to_cpu16 (head->ancount));
1549+ *data->addresses = grub_calloc (grub_be_to_cpu16 (head->ancount),
1550+ sizeof ((*data->addresses)[0]));
1551 if (!*data->addresses)
1552 {
1553 grub_errno = GRUB_ERR_NONE;
1554@@ -406,8 +406,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
1555 dns_cache[h].addresses = 0;
1556 dns_cache[h].name = grub_strdup (data->oname);
1557 dns_cache[h].naddresses = *data->naddresses;
1558- dns_cache[h].addresses = grub_malloc (*data->naddresses
1559- * sizeof (dns_cache[h].addresses[0]));
1560+ dns_cache[h].addresses = grub_calloc (*data->naddresses,
1561+ sizeof (dns_cache[h].addresses[0]));
1562 dns_cache[h].limit_time = grub_get_time_ms () + 1000 * ttl_all;
1563 if (!dns_cache[h].addresses || !dns_cache[h].name)
1564 {
1565@@ -479,7 +479,7 @@ grub_net_dns_lookup (const char *name,
1566 }
1567 }
1568
1569- sockets = grub_malloc (sizeof (sockets[0]) * n_servers);
1570+ sockets = grub_calloc (n_servers, sizeof (sockets[0]));
1571 if (!sockets)
1572 return grub_errno;
1573
1574diff --git a/grub-core/net/net.c b/grub-core/net/net.c
1575index b917a75d5..fed7bc57c 100644
1576--- a/grub-core/net/net.c
1577+++ b/grub-core/net/net.c
1578@@ -333,8 +333,8 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
1579 ncards++;
1580 }
1581
1582- ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
1583- slaacs = grub_zalloc (ncards * sizeof (slaacs[0]));
1584+ ifaces = grub_calloc (ncards, sizeof (ifaces[0]));
1585+ slaacs = grub_calloc (ncards, sizeof (slaacs[0]));
1586 if (!ifaces || !slaacs)
1587 {
1588 grub_free (ifaces);
1589diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
1590index b0ab47d73..d57fb72fa 100644
1591--- a/grub-core/normal/charset.c
1592+++ b/grub-core/normal/charset.c
1593@@ -203,7 +203,7 @@ grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
1594 {
1595 grub_size_t msg_len = grub_strlen (msg);
1596
1597- *unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t));
1598+ *unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t));
1599
1600 if (!*unicode_msg)
1601 return -1;
1602@@ -488,7 +488,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
1603 }
1604 else
1605 {
1606- n = grub_malloc (sizeof (n[0]) * (out->ncomb + 1));
1607+ n = grub_calloc (out->ncomb + 1, sizeof (n[0]));
1608 if (!n)
1609 {
1610 grub_errno = GRUB_ERR_NONE;
1611@@ -842,7 +842,7 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical,
1612 } \
1613 }
1614
1615- visual = grub_malloc (sizeof (visual[0]) * logical_len);
1616+ visual = grub_calloc (logical_len, sizeof (visual[0]));
1617 if (!visual)
1618 return -1;
1619
1620@@ -1165,8 +1165,8 @@ grub_bidi_logical_to_visual (const grub_uint32_t *logical,
1621 {
1622 const grub_uint32_t *line_start = logical, *ptr;
1623 struct grub_unicode_glyph *visual_ptr;
1624- *visual_out = visual_ptr = grub_malloc (3 * sizeof (visual_ptr[0])
1625- * (logical_len + 2));
1626+ *visual_out = visual_ptr = grub_calloc (logical_len + 2,
1627+ 3 * sizeof (visual_ptr[0]));
1628 if (!visual_ptr)
1629 return -1;
1630 for (ptr = logical; ptr <= logical + logical_len; ptr++)
1631diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c
1632index c037d5050..c57242e2e 100644
1633--- a/grub-core/normal/cmdline.c
1634+++ b/grub-core/normal/cmdline.c
1635@@ -41,7 +41,7 @@ grub_err_t
1636 grub_set_history (int newsize)
1637 {
1638 grub_uint32_t **old_hist_lines = hist_lines;
1639- hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize);
1640+ hist_lines = grub_calloc (newsize, sizeof (grub_uint32_t *));
1641
1642 /* Copy the old lines into the new buffer. */
1643 if (old_hist_lines)
1644@@ -114,7 +114,7 @@ static void
1645 grub_history_set (int pos, grub_uint32_t *s, grub_size_t len)
1646 {
1647 grub_free (hist_lines[pos]);
1648- hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t));
1649+ hist_lines[pos] = grub_calloc (len + 1, sizeof (grub_uint32_t));
1650 if (!hist_lines[pos])
1651 {
1652 grub_print_error ();
1653@@ -349,7 +349,7 @@ grub_cmdline_get (const char *prompt_translated)
1654 char *ret;
1655 unsigned nterms;
1656
1657- buf = grub_malloc (max_len * sizeof (grub_uint32_t));
1658+ buf = grub_calloc (max_len, sizeof (grub_uint32_t));
1659 if (!buf)
1660 return 0;
1661
1662@@ -377,7 +377,7 @@ grub_cmdline_get (const char *prompt_translated)
1663 FOR_ACTIVE_TERM_OUTPUTS(cur)
1664 nterms++;
1665
1666- cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms);
1667+ cl_terms = grub_calloc (nterms, sizeof (cl_terms[0]));
1668 if (!cl_terms)
1669 {
1670 grub_free (buf);
1671@@ -385,7 +385,7 @@ grub_cmdline_get (const char *prompt_translated)
1672 }
1673 cl_term_cur = cl_terms;
1674
1675- unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t));
1676+ unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t));
1677 if (!unicode_msg)
1678 {
1679 grub_free (buf);
1680@@ -495,7 +495,7 @@ grub_cmdline_get (const char *prompt_translated)
1681 grub_uint32_t *insert;
1682
1683 insertlen = grub_strlen (insertu8);
1684- insert = grub_malloc ((insertlen + 1) * sizeof (grub_uint32_t));
1685+ insert = grub_calloc (insertlen + 1, sizeof (grub_uint32_t));
1686 if (!insert)
1687 {
1688 grub_free (insertu8);
1689@@ -602,7 +602,7 @@ grub_cmdline_get (const char *prompt_translated)
1690
1691 grub_free (kill_buf);
1692
1693- kill_buf = grub_malloc ((n + 1) * sizeof(grub_uint32_t));
1694+ kill_buf = grub_calloc (n + 1, sizeof (grub_uint32_t));
1695 if (grub_errno)
1696 {
1697 grub_print_error ();
1698diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
1699index cdf3590a3..1993995be 100644
1700--- a/grub-core/normal/menu_entry.c
1701+++ b/grub-core/normal/menu_entry.c
1702@@ -95,8 +95,8 @@ init_line (struct screen *screen, struct line *linep)
1703 {
1704 linep->len = 0;
1705 linep->max_len = 80;
1706- linep->buf = grub_malloc ((linep->max_len + 1) * sizeof (linep->buf[0]));
1707- linep->pos = grub_zalloc (screen->nterms * sizeof (linep->pos[0]));
1708+ linep->buf = grub_calloc (linep->max_len + 1, sizeof (linep->buf[0]));
1709+ linep->pos = grub_calloc (screen->nterms, sizeof (linep->pos[0]));
1710 if (! linep->buf || !linep->pos)
1711 {
1712 grub_free (linep->buf);
1713@@ -287,7 +287,7 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen,
1714 pos = linep->pos + (term_screen - screen->terms);
1715
1716 if (!*pos)
1717- *pos = grub_zalloc ((linep->len + 1) * sizeof (**pos));
1718+ *pos = grub_calloc (linep->len + 1, sizeof (**pos));
1719
1720 if (i == region_start || linep == screen->lines + screen->line
1721 || (i > region_start && mode == ALL_LINES))
1722@@ -471,7 +471,7 @@ insert_string (struct screen *screen, const char *s, int update)
1723
1724 /* Insert the string. */
1725 current_linep = screen->lines + screen->line;
1726- unicode_msg = grub_malloc ((p - s) * sizeof (grub_uint32_t));
1727+ unicode_msg = grub_calloc (p - s, sizeof (grub_uint32_t));
1728
1729 if (!unicode_msg)
1730 return 0;
1731@@ -1023,7 +1023,7 @@ complete (struct screen *screen, int continuous, int update)
1732 if (completion_buffer.buf)
1733 {
1734 buflen = grub_strlen (completion_buffer.buf);
1735- ucs4 = grub_malloc (sizeof (grub_uint32_t) * (buflen + 1));
1736+ ucs4 = grub_calloc (buflen + 1, sizeof (grub_uint32_t));
1737
1738 if (!ucs4)
1739 {
1740@@ -1268,7 +1268,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
1741 for (i = 0; i < (unsigned) screen->num_lines; i++)
1742 {
1743 grub_free (screen->lines[i].pos);
1744- screen->lines[i].pos = grub_zalloc (screen->nterms * sizeof (screen->lines[i].pos[0]));
1745+ screen->lines[i].pos = grub_calloc (screen->nterms, sizeof (screen->lines[i].pos[0]));
1746 if (! screen->lines[i].pos)
1747 {
1748 grub_print_error ();
1749@@ -1278,7 +1278,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
1750 }
1751 }
1752
1753- screen->terms = grub_zalloc (screen->nterms * sizeof (screen->terms[0]));
1754+ screen->terms = grub_calloc (screen->nterms, sizeof (screen->terms[0]));
1755 if (!screen->terms)
1756 {
1757 grub_print_error ();
1758diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c
1759index e22bb91f6..18240e76c 100644
1760--- a/grub-core/normal/menu_text.c
1761+++ b/grub-core/normal/menu_text.c
1762@@ -78,7 +78,7 @@ grub_print_message_indented_real (const char *msg, int margin_left,
1763 grub_size_t msg_len = grub_strlen (msg) + 2;
1764 int ret = 0;
1765
1766- unicode_msg = grub_malloc (msg_len * sizeof (grub_uint32_t));
1767+ unicode_msg = grub_calloc (msg_len, sizeof (grub_uint32_t));
1768
1769 if (!unicode_msg)
1770 return 0;
1771@@ -211,7 +211,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry,
1772
1773 title = entry ? entry->title : "";
1774 title_len = grub_strlen (title);
1775- unicode_title = grub_malloc (title_len * sizeof (*unicode_title));
1776+ unicode_title = grub_calloc (title_len, sizeof (*unicode_title));
1777 if (! unicode_title)
1778 /* XXX How to show this error? */
1779 return;
1780diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c
1781index a1e5c5a0d..cc8c173b6 100644
1782--- a/grub-core/normal/term.c
1783+++ b/grub-core/normal/term.c
1784@@ -264,7 +264,7 @@ grub_term_save_pos (void)
1785 FOR_ACTIVE_TERM_OUTPUTS(cur)
1786 cnt++;
1787
1788- ret = grub_malloc (cnt * sizeof (ret[0]));
1789+ ret = grub_calloc (cnt, sizeof (ret[0]));
1790 if (!ret)
1791 return NULL;
1792
1793@@ -1013,7 +1013,7 @@ grub_xnputs (const char *str, grub_size_t msg_len)
1794
1795 grub_error_push ();
1796
1797- unicode_str = grub_malloc (msg_len * sizeof (grub_uint32_t));
1798+ unicode_str = grub_calloc (msg_len, sizeof (grub_uint32_t));
1799
1800 grub_error_pop ();
1801
1802diff --git a/grub-core/osdep/linux/getroot.c b/grub-core/osdep/linux/getroot.c
1803index 7adc0f30e..a5bd0752f 100644
1804--- a/grub-core/osdep/linux/getroot.c
1805+++ b/grub-core/osdep/linux/getroot.c
1806@@ -168,7 +168,7 @@ grub_util_raid_getmembers (const char *name, int bootable)
1807 if (ret != 0)
1808 grub_util_error (_("ioctl GET_ARRAY_INFO error: %s"), strerror (errno));
1809
1810- devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *));
1811+ devicelist = xcalloc (info.nr_disks + 1, sizeof (char *));
1812
1813 for (i = 0, j = 0; j < info.nr_disks; i++)
1814 {
1815@@ -241,7 +241,7 @@ grub_find_root_devices_from_btrfs (const char *dir)
1816 return NULL;
1817 }
1818
1819- ret = xmalloc ((fsi.num_devices + 1) * sizeof (ret[0]));
1820+ ret = xcalloc (fsi.num_devices + 1, sizeof (ret[0]));
1821
1822 for (i = 1; i <= fsi.max_id && j < fsi.num_devices; i++)
1823 {
1824@@ -396,7 +396,7 @@ grub_find_root_devices_from_mountinfo (const char *dir, char **relroot)
1825 if (relroot)
1826 *relroot = NULL;
1827
1828- entries = xmalloc (entry_max * sizeof (*entries));
1829+ entries = xcalloc (entry_max, sizeof (*entries));
1830
1831 again:
1832 fp = grub_util_fopen ("/proc/self/mountinfo", "r");
1833diff --git a/grub-core/osdep/windows/getroot.c b/grub-core/osdep/windows/getroot.c
1834index 661d95461..eada663b2 100644
1835--- a/grub-core/osdep/windows/getroot.c
1836+++ b/grub-core/osdep/windows/getroot.c
1837@@ -59,7 +59,7 @@ grub_get_mount_point (const TCHAR *path)
1838
1839 for (ptr = path; *ptr; ptr++);
1840 allocsize = (ptr - path + 10) * 2;
1841- out = xmalloc (allocsize * sizeof (out[0]));
1842+ out = xcalloc (allocsize, sizeof (out[0]));
1843
1844 /* When pointing to EFI system partition GetVolumePathName fails
1845 for ESP root and returns abberant information for everything
1846diff --git a/grub-core/osdep/windows/hostdisk.c b/grub-core/osdep/windows/hostdisk.c
1847index 355100789..0be327394 100644
1848--- a/grub-core/osdep/windows/hostdisk.c
1849+++ b/grub-core/osdep/windows/hostdisk.c
1850@@ -111,7 +111,7 @@ grub_util_get_windows_path_real (const char *path)
1851
1852 while (1)
1853 {
1854- fpa = xmalloc (alloc * sizeof (fpa[0]));
1855+ fpa = xcalloc (alloc, sizeof (fpa[0]));
1856
1857 len = GetFullPathName (tpath, alloc, fpa, NULL);
1858 if (len >= alloc)
1859@@ -399,7 +399,7 @@ grub_util_fd_opendir (const char *name)
1860 for (l = 0; name_windows[l]; l++);
1861 for (l--; l >= 0 && (name_windows[l] == '\\' || name_windows[l] == '/'); l--);
1862 l++;
1863- pattern = xmalloc ((l + 3) * sizeof (pattern[0]));
1864+ pattern = xcalloc (l + 3, sizeof (pattern[0]));
1865 memcpy (pattern, name_windows, l * sizeof (pattern[0]));
1866 pattern[l] = '\\';
1867 pattern[l + 1] = '*';
1868diff --git a/grub-core/osdep/windows/init.c b/grub-core/osdep/windows/init.c
1869index e8ffd62c6..6297de632 100644
1870--- a/grub-core/osdep/windows/init.c
1871+++ b/grub-core/osdep/windows/init.c
1872@@ -161,7 +161,7 @@ grub_util_host_init (int *argc __attribute__ ((unused)),
1873 LPWSTR *targv;
1874
1875 targv = CommandLineToArgvW (tcmdline, argc);
1876- *argv = xmalloc ((*argc + 1) * sizeof (argv[0]));
1877+ *argv = xcalloc (*argc + 1, sizeof (argv[0]));
1878
1879 for (i = 0; i < *argc; i++)
1880 (*argv)[i] = grub_util_tchar_to_utf8 (targv[i]);
1881diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
1882index e19a3d9a8..cb626c8c3 100644
1883--- a/grub-core/osdep/windows/platform.c
1884+++ b/grub-core/osdep/windows/platform.c
1885@@ -231,8 +231,8 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
1886 grub_util_error ("%s", _("no EFI routines are available when running in BIOS mode"));
1887
1888 distrib8_len = grub_strlen (efi_distributor);
1889- distributor16 = xmalloc ((distrib8_len + 1) * GRUB_MAX_UTF16_PER_UTF8
1890- * sizeof (grub_uint16_t));
1891+ distributor16 = xcalloc (distrib8_len + 1,
1892+ GRUB_MAX_UTF16_PER_UTF8 * sizeof (grub_uint16_t));
1893 distrib16_len = grub_utf8_to_utf16 (distributor16, distrib8_len * GRUB_MAX_UTF16_PER_UTF8,
1894 (const grub_uint8_t *) efi_distributor,
1895 distrib8_len, 0);
1896diff --git a/grub-core/osdep/windows/relpath.c b/grub-core/osdep/windows/relpath.c
1897index cb0861744..478e8ef14 100644
1898--- a/grub-core/osdep/windows/relpath.c
1899+++ b/grub-core/osdep/windows/relpath.c
1900@@ -72,7 +72,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
1901 if (dirwindows[0] && dirwindows[1] == ':')
1902 offset = 2;
1903 }
1904- ret = xmalloc (sizeof (ret[0]) * (flen - offset + 2));
1905+ ret = xcalloc (flen - offset + 2, sizeof (ret[0]));
1906 if (dirwindows[offset] != '\\'
1907 && dirwindows[offset] != '/'
1908 && dirwindows[offset])
1909diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c
1910index 103f6796f..72a2e37cd 100644
1911--- a/grub-core/partmap/gpt.c
1912+++ b/grub-core/partmap/gpt.c
1913@@ -199,7 +199,7 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
1914 *nsectors = ctx.len;
1915 if (*nsectors > max_nsectors)
1916 *nsectors = max_nsectors;
1917- *sectors = grub_malloc (*nsectors * sizeof (**sectors));
1918+ *sectors = grub_calloc (*nsectors, sizeof (**sectors));
1919 if (!*sectors)
1920 return grub_errno;
1921 for (i = 0; i < *nsectors; i++)
1922diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c
1923index 7b8e45076..ee3f24982 100644
1924--- a/grub-core/partmap/msdos.c
1925+++ b/grub-core/partmap/msdos.c
1926@@ -337,7 +337,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
1927 avail_nsectors = *nsectors;
1928 if (*nsectors > max_nsectors)
1929 *nsectors = max_nsectors;
1930- *sectors = grub_malloc (*nsectors * sizeof (**sectors));
1931+ *sectors = grub_calloc (*nsectors, sizeof (**sectors));
1932 if (!*sectors)
1933 return grub_errno;
1934 for (i = 0; i < *nsectors; i++)
1935diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
1936index ee299fd0e..c8d6806fe 100644
1937--- a/grub-core/script/execute.c
1938+++ b/grub-core/script/execute.c
1939@@ -553,7 +553,7 @@ gettext_append (struct grub_script_argv *result, const char *orig_str)
1940 for (iptr = orig_str; *iptr; iptr++)
1941 if (*iptr == '$')
1942 dollar_cnt++;
1943- ctx.allowed_strings = grub_malloc (sizeof (ctx.allowed_strings[0]) * dollar_cnt);
1944+ ctx.allowed_strings = grub_calloc (dollar_cnt, sizeof (ctx.allowed_strings[0]));
1945
1946 if (parse_string (orig_str, gettext_save_allow, &ctx, 0))
1947 goto fail;
1948diff --git a/grub-core/tests/fake_input.c b/grub-core/tests/fake_input.c
1949index 2d6085298..b5eb516be 100644
1950--- a/grub-core/tests/fake_input.c
1951+++ b/grub-core/tests/fake_input.c
1952@@ -49,7 +49,7 @@ grub_terminal_input_fake_sequence (int *seq_in, int nseq_in)
1953 saved = grub_term_inputs;
1954 if (seq)
1955 grub_free (seq);
1956- seq = grub_malloc (nseq_in * sizeof (seq[0]));
1957+ seq = grub_calloc (nseq_in, sizeof (seq[0]));
1958 if (!seq)
1959 return;
1960
1961diff --git a/grub-core/tests/video_checksum.c b/grub-core/tests/video_checksum.c
1962index 74d5b65e5..44d081069 100644
1963--- a/grub-core/tests/video_checksum.c
1964+++ b/grub-core/tests/video_checksum.c
1965@@ -336,7 +336,7 @@ grub_video_capture_write_bmp (const char *fname,
1966 {
1967 case 4:
1968 {
1969- grub_uint8_t *buffer = xmalloc (mode_info->width * 3);
1970+ grub_uint8_t *buffer = xcalloc (3, mode_info->width);
1971 grub_uint32_t rmask = ((1 << mode_info->red_mask_size) - 1);
1972 grub_uint32_t gmask = ((1 << mode_info->green_mask_size) - 1);
1973 grub_uint32_t bmask = ((1 << mode_info->blue_mask_size) - 1);
1974@@ -367,7 +367,7 @@ grub_video_capture_write_bmp (const char *fname,
1975 }
1976 case 3:
1977 {
1978- grub_uint8_t *buffer = xmalloc (mode_info->width * 3);
1979+ grub_uint8_t *buffer = xcalloc (3, mode_info->width);
1980 grub_uint32_t rmask = ((1 << mode_info->red_mask_size) - 1);
1981 grub_uint32_t gmask = ((1 << mode_info->green_mask_size) - 1);
1982 grub_uint32_t bmask = ((1 << mode_info->blue_mask_size) - 1);
1983@@ -407,7 +407,7 @@ grub_video_capture_write_bmp (const char *fname,
1984 }
1985 case 2:
1986 {
1987- grub_uint8_t *buffer = xmalloc (mode_info->width * 3);
1988+ grub_uint8_t *buffer = xcalloc (3, mode_info->width);
1989 grub_uint16_t rmask = ((1 << mode_info->red_mask_size) - 1);
1990 grub_uint16_t gmask = ((1 << mode_info->green_mask_size) - 1);
1991 grub_uint16_t bmask = ((1 << mode_info->blue_mask_size) - 1);
1992diff --git a/grub-core/video/capture.c b/grub-core/video/capture.c
1993index 4f83c7441..4d3195e01 100644
1994--- a/grub-core/video/capture.c
1995+++ b/grub-core/video/capture.c
1996@@ -89,7 +89,7 @@ grub_video_capture_start (const struct grub_video_mode_info *mode_info,
1997 framebuffer.mode_info = *mode_info;
1998 framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
1999
2000- framebuffer.ptr = grub_malloc (framebuffer.mode_info.height * framebuffer.mode_info.pitch);
2001+ framebuffer.ptr = grub_calloc (framebuffer.mode_info.height, framebuffer.mode_info.pitch);
2002 if (!framebuffer.ptr)
2003 return grub_errno;
2004
2005diff --git a/grub-core/video/emu/sdl.c b/grub-core/video/emu/sdl.c
2006index a2f639f66..0ebab6f57 100644
2007--- a/grub-core/video/emu/sdl.c
2008+++ b/grub-core/video/emu/sdl.c
2009@@ -172,7 +172,7 @@ grub_video_sdl_set_palette (unsigned int start, unsigned int count,
2010 if (start + count > mode_info.number_of_colors)
2011 count = mode_info.number_of_colors - start;
2012
2013- tmp = grub_malloc (count * sizeof (tmp[0]));
2014+ tmp = grub_calloc (count, sizeof (tmp[0]));
2015 for (i = 0; i < count; i++)
2016 {
2017 tmp[i].r = palette_data[i].r;
2018diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c
2019index 01f47112d..b2f776c99 100644
2020--- a/grub-core/video/i386/pc/vga.c
2021+++ b/grub-core/video/i386/pc/vga.c
2022@@ -127,7 +127,7 @@ grub_video_vga_setup (unsigned int width, unsigned int height,
2023
2024 vga_height = height ? : 480;
2025
2026- framebuffer.temporary_buffer = grub_malloc (vga_height * VGA_WIDTH);
2027+ framebuffer.temporary_buffer = grub_calloc (vga_height, VGA_WIDTH);
2028 framebuffer.front_page = 0;
2029 framebuffer.back_page = 0;
2030 if (!framebuffer.temporary_buffer)
2031diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
2032index 777e71334..61bd64537 100644
2033--- a/grub-core/video/readers/png.c
2034+++ b/grub-core/video/readers/png.c
2035@@ -309,7 +309,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
2036 if (data->is_16bit || data->is_gray || data->is_palette)
2037 #endif
2038 {
2039- data->image_data = grub_malloc (data->image_height * data->row_bytes);
2040+ data->image_data = grub_calloc (data->image_height, data->row_bytes);
2041 if (grub_errno)
2042 return grub_errno;
2043
2044diff --git a/include/grub/unicode.h b/include/grub/unicode.h
2045index a0403e91f..4de986a85 100644
2046--- a/include/grub/unicode.h
2047+++ b/include/grub/unicode.h
2048@@ -293,7 +293,7 @@ grub_unicode_glyph_dup (const struct grub_unicode_glyph *in)
2049 grub_memcpy (out, in, sizeof (*in));
2050 if (in->ncomb > ARRAY_SIZE (out->combining_inline))
2051 {
2052- out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0]));
2053+ out->combining_ptr = grub_calloc (in->ncomb, sizeof (out->combining_ptr[0]));
2054 if (!out->combining_ptr)
2055 {
2056 grub_free (out);
2057@@ -315,7 +315,7 @@ grub_unicode_set_glyph (struct grub_unicode_glyph *out,
2058 grub_memcpy (out, in, sizeof (*in));
2059 if (in->ncomb > ARRAY_SIZE (out->combining_inline))
2060 {
2061- out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0]));
2062+ out->combining_ptr = grub_calloc (in->ncomb, sizeof (out->combining_ptr[0]));
2063 if (!out->combining_ptr)
2064 return;
2065 grub_memcpy (out->combining_ptr, in->combining_ptr,
2066diff --git a/util/getroot.c b/util/getroot.c
2067index cdd41153c..6ae35ecaa 100644
2068--- a/util/getroot.c
2069+++ b/util/getroot.c
2070@@ -200,7 +200,7 @@ make_device_name (const char *drive)
2071 char *ret, *ptr;
2072 const char *iptr;
2073
2074- ret = xmalloc (strlen (drive) * 2);
2075+ ret = xcalloc (2, strlen (drive));
2076 ptr = ret;
2077 for (iptr = drive; *iptr; iptr++)
2078 {
2079diff --git a/util/grub-file.c b/util/grub-file.c
2080index 50c18b683..b2e7dd69f 100644
2081--- a/util/grub-file.c
2082+++ b/util/grub-file.c
2083@@ -54,7 +54,7 @@ main (int argc, char *argv[])
2084
2085 grub_util_host_init (&argc, &argv);
2086
2087- argv2 = xmalloc (argc * sizeof (argv2[0]));
2088+ argv2 = xcalloc (argc, sizeof (argv2[0]));
2089
2090 if (argc == 2 && strcmp (argv[1], "--version") == 0)
2091 {
2092diff --git a/util/grub-fstest.c b/util/grub-fstest.c
2093index f14e02d97..57246af7c 100644
2094--- a/util/grub-fstest.c
2095+++ b/util/grub-fstest.c
2096@@ -650,7 +650,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
2097 if (args_count < num_disks)
2098 {
2099 if (args_count == 0)
2100- images = xmalloc (num_disks * sizeof (images[0]));
2101+ images = xcalloc (num_disks, sizeof (images[0]));
2102 images[args_count] = grub_canonicalize_file_name (arg);
2103 args_count++;
2104 return 0;
2105@@ -734,7 +734,7 @@ main (int argc, char *argv[])
2106
2107 grub_util_host_init (&argc, &argv);
2108
2109- args = xmalloc (argc * sizeof (args[0]));
2110+ args = xcalloc (argc, sizeof (args[0]));
2111
2112 argp_parse (&argp, argc, argv, 0, 0, 0);
2113
2114diff --git a/util/grub-install-common.c b/util/grub-install-common.c
2115index fdfe2c7ea..447504d3f 100644
2116--- a/util/grub-install-common.c
2117+++ b/util/grub-install-common.c
2118@@ -286,7 +286,7 @@ handle_install_list (struct install_list *il, const char *val,
2119 il->n_entries++;
2120 }
2121 il->n_alloc = il->n_entries + 1;
2122- il->entries = xmalloc (il->n_alloc * sizeof (il->entries[0]));
2123+ il->entries = xcalloc (il->n_alloc, sizeof (il->entries[0]));
2124 ptr = val;
2125 for (ce = il->entries; ; ce++)
2126 {
2127diff --git a/util/grub-install.c b/util/grub-install.c
2128index 666cef3d2..bd6d8dbb3 100644
2129--- a/util/grub-install.c
2130+++ b/util/grub-install.c
2131@@ -655,7 +655,7 @@ device_map_check_duplicates (const char *dev_map)
2132 if (! fp)
2133 return;
2134
2135- d = xmalloc (alloced * sizeof (d[0]));
2136+ d = xcalloc (alloced, sizeof (d[0]));
2137
2138 while (fgets (buf, sizeof (buf), fp))
2139 {
2140@@ -1374,7 +1374,7 @@ main (int argc, char *argv[])
2141 ndev++;
2142 }
2143
2144- grub_drives = xmalloc (sizeof (grub_drives[0]) * (ndev + 1));
2145+ grub_drives = xcalloc (ndev + 1, sizeof (grub_drives[0]));
2146
2147 for (curdev = grub_devices, curdrive = grub_drives; *curdev; curdev++,
2148 curdrive++)
2149diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
2150index bc087c2b5..d97d0e7be 100644
2151--- a/util/grub-mkimagexx.c
2152+++ b/util/grub-mkimagexx.c
2153@@ -2294,10 +2294,8 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
2154 + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
2155 smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
2156
2157- smd.addrs = xmalloc (sizeof (*smd.addrs) * smd.num_sections);
2158- memset (smd.addrs, 0, sizeof (*smd.addrs) * smd.num_sections);
2159- smd.vaddrs = xmalloc (sizeof (*smd.vaddrs) * smd.num_sections);
2160- memset (smd.vaddrs, 0, sizeof (*smd.vaddrs) * smd.num_sections);
2161+ smd.addrs = xcalloc (smd.num_sections, sizeof (*smd.addrs));
2162+ smd.vaddrs = xcalloc (smd.num_sections, sizeof (*smd.vaddrs));
2163
2164 SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
2165
2166diff --git a/util/grub-mkrescue.c b/util/grub-mkrescue.c
2167index 45d6140d3..cb972f120 100644
2168--- a/util/grub-mkrescue.c
2169+++ b/util/grub-mkrescue.c
2170@@ -441,8 +441,8 @@ main (int argc, char *argv[])
2171 xorriso = xstrdup ("xorriso");
2172 label_font = grub_util_path_concat (2, pkgdatadir, "unicode.pf2");
2173
2174- argp_argv = xmalloc (sizeof (argp_argv[0]) * argc);
2175- xorriso_tail_argv = xmalloc (sizeof (argp_argv[0]) * argc);
2176+ argp_argv = xcalloc (argc, sizeof (argp_argv[0]));
2177+ xorriso_tail_argv = xcalloc (argc, sizeof (argp_argv[0]));
2178
2179 xorriso_tail_argc = 0;
2180 /* Program name */
2181diff --git a/util/grub-mkstandalone.c b/util/grub-mkstandalone.c
2182index 4907d44c0..edf309717 100644
2183--- a/util/grub-mkstandalone.c
2184+++ b/util/grub-mkstandalone.c
2185@@ -296,7 +296,7 @@ main (int argc, char *argv[])
2186 grub_util_host_init (&argc, &argv);
2187 grub_util_disable_fd_syncs ();
2188
2189- files = xmalloc ((argc + 1) * sizeof (files[0]));
2190+ files = xcalloc (argc + 1, sizeof (files[0]));
2191
2192 argp_parse (&argp, argc, argv, 0, 0, 0);
2193
2194diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c
2195index 0d4084a10..11331294f 100644
2196--- a/util/grub-pe2elf.c
2197+++ b/util/grub-pe2elf.c
2198@@ -100,9 +100,9 @@ write_section_data (FILE* fp, const char *name, char *image,
2199 char *pe_strtab = (image + pe_chdr->symtab_offset
2200 + pe_chdr->num_symbols * sizeof (struct grub_pe32_symbol));
2201
2202- section_map = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (int));
2203+ section_map = xcalloc (2 * pe_chdr->num_sections + 5, sizeof (int));
2204 section_map[0] = 0;
2205- shdr = xmalloc ((2 * pe_chdr->num_sections + 5) * sizeof (shdr[0]));
2206+ shdr = xcalloc (2 * pe_chdr->num_sections + 5, sizeof (shdr[0]));
2207 idx = 1;
2208 idx_reloc = pe_chdr->num_sections + 1;
2209
2210@@ -233,7 +233,7 @@ write_reloc_section (FILE* fp, const char *name, char *image,
2211
2212 pe_sec = pe_shdr + shdr[i].sh_link;
2213 pe_rel = (struct grub_pe32_reloc *) (image + pe_sec->relocations_offset);
2214- rel = (elf_reloc_t *) xmalloc (pe_sec->num_relocations * sizeof (elf_reloc_t));
2215+ rel = (elf_reloc_t *) xcalloc (pe_sec->num_relocations, sizeof (elf_reloc_t));
2216 num_rels = 0;
2217 modified = 0;
2218
2219@@ -365,12 +365,10 @@ write_symbol_table (FILE* fp, const char *name, char *image,
2220 pe_symtab = (struct grub_pe32_symbol *) (image + pe_chdr->symtab_offset);
2221 pe_strtab = (char *) (pe_symtab + pe_chdr->num_symbols);
2222
2223- symtab = (Elf_Sym *) xmalloc ((pe_chdr->num_symbols + 1) *
2224- sizeof (Elf_Sym));
2225- memset (symtab, 0, (pe_chdr->num_symbols + 1) * sizeof (Elf_Sym));
2226+ symtab = (Elf_Sym *) xcalloc (pe_chdr->num_symbols + 1, sizeof (Elf_Sym));
2227 num_syms = 1;
2228
2229- symtab_map = (int *) xmalloc (pe_chdr->num_symbols * sizeof (int));
2230+ symtab_map = (int *) xcalloc (pe_chdr->num_symbols, sizeof (int));
2231
2232 for (i = 0; i < (int) pe_chdr->num_symbols;
2233 i += pe_symtab->num_aux + 1, pe_symtab += pe_symtab->num_aux + 1)
2234diff --git a/util/grub-probe.c b/util/grub-probe.c
2235index 81d27eead..cbe6ed94c 100644
2236--- a/util/grub-probe.c
2237+++ b/util/grub-probe.c
2238@@ -361,8 +361,8 @@ probe (const char *path, char **device_names, char delim)
2239 grub_util_pull_device (*curdev);
2240 ndev++;
2241 }
2242-
2243- drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1));
2244+
2245+ drives_names = xcalloc (ndev + 1, sizeof (drives_names[0]));
2246
2247 for (curdev = device_names, curdrive = drives_names; *curdev; curdev++,
2248 curdrive++)
2249
2250From d84e89f4734711d8ff3c84b6c58985c824b4d889 Mon Sep 17 00:00:00 2001
2251From: Peter Jones <pjones@redhat.com>
2252Date: Mon, 15 Jun 2020 12:28:27 -0400
2253Subject: malloc: Use overflow checking primitives where we do
2254 complex allocations
2255
2256This attempts to fix the places where we do the following where
2257arithmetic_expr may include unvalidated data:
2258
2259 X = grub_malloc(arithmetic_expr);
2260
2261It accomplishes this by doing the arithmetic ahead of time using grub_add(),
2262grub_sub(), grub_mul() and testing for overflow before proceeding.
2263
2264Among other issues, this fixes:
2265 - allocation of integer overflow in grub_video_bitmap_create()
2266 reported by Chris Coulson,
2267 - allocation of integer overflow in grub_png_decode_image_header()
2268 reported by Chris Coulson,
2269 - allocation of integer overflow in grub_squash_read_symlink()
2270 reported by Chris Coulson,
2271 - allocation of integer overflow in grub_ext2_read_symlink()
2272 reported by Chris Coulson,
2273 - allocation of integer overflow in read_section_as_string()
2274 reported by Chris Coulson.
2275
2276Fixes: CVE-2020-14309, CVE-2020-14310, CVE-2020-14311
2277
2278Signed-off-by: Peter Jones <pjones@redhat.com>
2279Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2280---
2281 grub-core/commands/legacycfg.c | 29 +++++++++++++++----
2282 grub-core/commands/wildcard.c | 36 ++++++++++++++++++++----
2283 grub-core/disk/ldm.c | 32 +++++++++++++++------
2284 grub-core/font/font.c | 7 ++++-
2285 grub-core/fs/btrfs.c | 28 +++++++++++++------
2286 grub-core/fs/ext2.c | 10 ++++++-
2287 grub-core/fs/iso9660.c | 51 ++++++++++++++++++++++++----------
2288 grub-core/fs/sfs.c | 27 ++++++++++++++----
2289 grub-core/fs/squash4.c | 45 ++++++++++++++++++++++--------
2290 grub-core/fs/udf.c | 41 +++++++++++++++++----------
2291 grub-core/fs/xfs.c | 11 +++++---
2292 grub-core/fs/zfs/zfs.c | 22 ++++++++++-----
2293 grub-core/fs/zfs/zfscrypt.c | 7 ++++-
2294 grub-core/lib/arg.c | 20 +++++++++++--
2295 grub-core/loader/i386/bsd.c | 8 +++++-
2296 grub-core/net/dns.c | 9 +++++-
2297 grub-core/normal/charset.c | 10 +++++--
2298 grub-core/normal/cmdline.c | 14 ++++++++--
2299 grub-core/normal/menu_entry.c | 13 +++++++--
2300 grub-core/script/argv.c | 16 +++++++++--
2301 grub-core/script/lexer.c | 21 ++++++++++++--
2302 grub-core/video/bitmap.c | 25 +++++++++++------
2303 grub-core/video/readers/png.c | 13 +++++++--
2304 23 files changed, 382 insertions(+), 113 deletions(-)
2305
2306diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
2307index 5e3ec0d5e..cc5971f4d 100644
2308--- a/grub-core/commands/legacycfg.c
2309+++ b/grub-core/commands/legacycfg.c
2310@@ -32,6 +32,7 @@
2311 #include <grub/auth.h>
2312 #include <grub/disk.h>
2313 #include <grub/partition.h>
2314+#include <grub/safemath.h>
2315
2316 GRUB_MOD_LICENSE ("GPLv3+");
2317
2318@@ -104,13 +105,22 @@ legacy_file (const char *filename)
2319 if (newsuffix)
2320 {
2321 char *t;
2322-
2323+ grub_size_t sz;
2324+
2325+ if (grub_add (grub_strlen (suffix), grub_strlen (newsuffix), &sz) ||
2326+ grub_add (sz, 1, &sz))
2327+ {
2328+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
2329+ goto fail_0;
2330+ }
2331+
2332 t = suffix;
2333- suffix = grub_realloc (suffix, grub_strlen (suffix)
2334- + grub_strlen (newsuffix) + 1);
2335+ suffix = grub_realloc (suffix, sz);
2336 if (!suffix)
2337 {
2338 grub_free (t);
2339+
2340+ fail_0:
2341 grub_free (entrysrc);
2342 grub_free (parsed);
2343 grub_free (newsuffix);
2344@@ -154,13 +164,22 @@ legacy_file (const char *filename)
2345 else
2346 {
2347 char *t;
2348+ grub_size_t sz;
2349+
2350+ if (grub_add (grub_strlen (entrysrc), grub_strlen (parsed), &sz) ||
2351+ grub_add (sz, 1, &sz))
2352+ {
2353+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
2354+ goto fail_1;
2355+ }
2356
2357 t = entrysrc;
2358- entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
2359- + grub_strlen (parsed) + 1);
2360+ entrysrc = grub_realloc (entrysrc, sz);
2361 if (!entrysrc)
2362 {
2363 grub_free (t);
2364+
2365+ fail_1:
2366 grub_free (parsed);
2367 grub_free (suffix);
2368 return grub_errno;
2369diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c
2370index 4a106ca04..cc3290311 100644
2371--- a/grub-core/commands/wildcard.c
2372+++ b/grub-core/commands/wildcard.c
2373@@ -23,6 +23,7 @@
2374 #include <grub/file.h>
2375 #include <grub/device.h>
2376 #include <grub/script_sh.h>
2377+#include <grub/safemath.h>
2378
2379 #include <regex.h>
2380
2381@@ -48,6 +49,7 @@ merge (char **dest, char **ps)
2382 int i;
2383 int j;
2384 char **p;
2385+ grub_size_t sz;
2386
2387 if (! dest)
2388 return ps;
2389@@ -60,7 +62,12 @@ merge (char **dest, char **ps)
2390 for (j = 0; ps[j]; j++)
2391 ;
2392
2393- p = grub_realloc (dest, sizeof (char*) * (i + j + 1));
2394+ if (grub_add (i, j, &sz) ||
2395+ grub_add (sz, 1, &sz) ||
2396+ grub_mul (sz, sizeof (char *), &sz))
2397+ return dest;
2398+
2399+ p = grub_realloc (dest, sz);
2400 if (! p)
2401 {
2402 grub_free (dest);
2403@@ -115,8 +122,15 @@ make_regex (const char *start, const char *end, regex_t *regexp)
2404 char ch;
2405 int i = 0;
2406 unsigned len = end - start;
2407- char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */
2408+ char *buffer;
2409+ grub_size_t sz;
2410
2411+ /* Worst case size is (len * 2 + 2 + 1). */
2412+ if (grub_mul (len, 2, &sz) ||
2413+ grub_add (sz, 3, &sz))
2414+ return 1;
2415+
2416+ buffer = grub_malloc (sz);
2417 if (! buffer)
2418 return 1;
2419
2420@@ -226,6 +240,7 @@ match_devices_iter (const char *name, void *data)
2421 struct match_devices_ctx *ctx = data;
2422 char **t;
2423 char *buffer;
2424+ grub_size_t sz;
2425
2426 /* skip partitions if asked to. */
2427 if (ctx->noparts && grub_strchr (name, ','))
2428@@ -239,11 +254,16 @@ match_devices_iter (const char *name, void *data)
2429 if (regexec (ctx->regexp, buffer, 0, 0, 0))
2430 {
2431 grub_dprintf ("expand", "not matched\n");
2432+ fail:
2433 grub_free (buffer);
2434 return 0;
2435 }
2436
2437- t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
2438+ if (grub_add (ctx->ndev, 2, &sz) ||
2439+ grub_mul (sz, sizeof (char *), &sz))
2440+ goto fail;
2441+
2442+ t = grub_realloc (ctx->devs, sz);
2443 if (! t)
2444 {
2445 grub_free (buffer);
2446@@ -300,6 +320,7 @@ match_files_iter (const char *name,
2447 struct match_files_ctx *ctx = data;
2448 char **t;
2449 char *buffer;
2450+ grub_size_t sz;
2451
2452 /* skip . and .. names */
2453 if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
2454@@ -315,9 +336,14 @@ match_files_iter (const char *name,
2455 if (! buffer)
2456 return 1;
2457
2458- t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2));
2459- if (! t)
2460+ if (grub_add (ctx->nfile, 2, &sz) ||
2461+ grub_mul (sz, sizeof (char *), &sz))
2462+ goto fail;
2463+
2464+ t = grub_realloc (ctx->files, sz);
2465+ if (!t)
2466 {
2467+ fail:
2468 grub_free (buffer);
2469 return 1;
2470 }
2471diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
2472index e6323701a..58f8a53e1 100644
2473--- a/grub-core/disk/ldm.c
2474+++ b/grub-core/disk/ldm.c
2475@@ -25,6 +25,7 @@
2476 #include <grub/msdos_partition.h>
2477 #include <grub/gpt_partition.h>
2478 #include <grub/i18n.h>
2479+#include <grub/safemath.h>
2480
2481 #ifdef GRUB_UTIL
2482 #include <grub/emu/misc.h>
2483@@ -289,6 +290,7 @@ make_vg (grub_disk_t disk,
2484 struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
2485 / sizeof (struct grub_ldm_vblk)];
2486 unsigned i;
2487+ grub_size_t sz;
2488 err = grub_disk_read (disk, cursec, 0,
2489 sizeof(vblk), &vblk);
2490 if (err)
2491@@ -350,7 +352,13 @@ make_vg (grub_disk_t disk,
2492 grub_free (lv);
2493 goto fail2;
2494 }
2495- lv->name = grub_malloc (*ptr + 1);
2496+ if (grub_add (*ptr, 1, &sz))
2497+ {
2498+ grub_free (lv->internal_id);
2499+ grub_free (lv);
2500+ goto fail2;
2501+ }
2502+ lv->name = grub_malloc (sz);
2503 if (!lv->name)
2504 {
2505 grub_free (lv->internal_id);
2506@@ -599,10 +607,13 @@ make_vg (grub_disk_t disk,
2507 if (lv->segments->node_alloc == lv->segments->node_count)
2508 {
2509 void *t;
2510- lv->segments->node_alloc *= 2;
2511- t = grub_realloc (lv->segments->nodes,
2512- sizeof (*lv->segments->nodes)
2513- * lv->segments->node_alloc);
2514+ grub_size_t sz;
2515+
2516+ if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) ||
2517+ grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz))
2518+ goto fail2;
2519+
2520+ t = grub_realloc (lv->segments->nodes, sz);
2521 if (!t)
2522 goto fail2;
2523 lv->segments->nodes = t;
2524@@ -723,10 +734,13 @@ make_vg (grub_disk_t disk,
2525 if (comp->segment_alloc == comp->segment_count)
2526 {
2527 void *t;
2528- comp->segment_alloc *= 2;
2529- t = grub_realloc (comp->segments,
2530- comp->segment_alloc
2531- * sizeof (*comp->segments));
2532+ grub_size_t sz;
2533+
2534+ if (grub_mul (comp->segment_alloc, 2, &comp->segment_alloc) ||
2535+ grub_mul (comp->segment_alloc, sizeof (*comp->segments), &sz))
2536+ goto fail2;
2537+
2538+ t = grub_realloc (comp->segments, sz);
2539 if (!t)
2540 goto fail2;
2541 comp->segments = t;
2542diff --git a/grub-core/font/font.c b/grub-core/font/font.c
2543index 8e118b315..5edb477ac 100644
2544--- a/grub-core/font/font.c
2545+++ b/grub-core/font/font.c
2546@@ -30,6 +30,7 @@
2547 #include <grub/unicode.h>
2548 #include <grub/fontformat.h>
2549 #include <grub/env.h>
2550+#include <grub/safemath.h>
2551
2552 GRUB_MOD_LICENSE ("GPLv3+");
2553
2554@@ -360,9 +361,13 @@ static char *
2555 read_section_as_string (struct font_file_section *section)
2556 {
2557 char *str;
2558+ grub_size_t sz;
2559 grub_ssize_t ret;
2560
2561- str = grub_malloc (section->length + 1);
2562+ if (grub_add (section->length, 1, &sz))
2563+ return NULL;
2564+
2565+ str = grub_malloc (sz);
2566 if (!str)
2567 return 0;
2568
2569diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
2570index 4b8380439..27339bdb3 100644
2571--- a/grub-core/fs/btrfs.c
2572+++ b/grub-core/fs/btrfs.c
2573@@ -40,6 +40,7 @@
2574 #include <grub/btrfs.h>
2575 #include <grub/crypto.h>
2576 #include <grub/diskfilter.h>
2577+#include <grub/safemath.h>
2578
2579 GRUB_MOD_LICENSE ("GPLv3+");
2580
2581@@ -331,9 +332,13 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc,
2582 if (desc->allocated < desc->depth)
2583 {
2584 void *newdata;
2585- desc->allocated *= 2;
2586- newdata = grub_realloc (desc->data, sizeof (desc->data[0])
2587- * desc->allocated);
2588+ grub_size_t sz;
2589+
2590+ if (grub_mul (desc->allocated, 2, &desc->allocated) ||
2591+ grub_mul (desc->allocated, sizeof (desc->data[0]), &sz))
2592+ return GRUB_ERR_OUT_OF_RANGE;
2593+
2594+ newdata = grub_realloc (desc->data, sz);
2595 if (!newdata)
2596 return grub_errno;
2597 desc->data = newdata;
2598@@ -624,16 +629,21 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id)
2599 if (data->n_devices_attached > data->n_devices_allocated)
2600 {
2601 void *tmp;
2602- data->n_devices_allocated = 2 * data->n_devices_attached + 1;
2603- data->devices_attached
2604- = grub_realloc (tmp = data->devices_attached,
2605- data->n_devices_allocated
2606- * sizeof (data->devices_attached[0]));
2607+ grub_size_t sz;
2608+
2609+ if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) ||
2610+ grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) ||
2611+ grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz))
2612+ goto fail;
2613+
2614+ data->devices_attached = grub_realloc (tmp = data->devices_attached, sz);
2615 if (!data->devices_attached)
2616 {
2617+ data->devices_attached = tmp;
2618+
2619+ fail:
2620 if (ctx.dev_found)
2621 grub_device_close (ctx.dev_found);
2622- data->devices_attached = tmp;
2623 return NULL;
2624 }
2625 }
2626diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
2627index 9b389802a..ac33bcd68 100644
2628--- a/grub-core/fs/ext2.c
2629+++ b/grub-core/fs/ext2.c
2630@@ -46,6 +46,7 @@
2631 #include <grub/dl.h>
2632 #include <grub/types.h>
2633 #include <grub/fshelp.h>
2634+#include <grub/safemath.h>
2635
2636 GRUB_MOD_LICENSE ("GPLv3+");
2637
2638@@ -703,6 +704,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
2639 {
2640 char *symlink;
2641 struct grub_fshelp_node *diro = node;
2642+ grub_size_t sz;
2643
2644 if (! diro->inode_read)
2645 {
2646@@ -717,7 +719,13 @@ grub_ext2_read_symlink (grub_fshelp_node_t node)
2647 }
2648 }
2649
2650- symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
2651+ if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz))
2652+ {
2653+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
2654+ return NULL;
2655+ }
2656+
2657+ symlink = grub_malloc (sz);
2658 if (! symlink)
2659 return 0;
2660
2661diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
2662index 4f1b52a55..7ba5b300b 100644
2663--- a/grub-core/fs/iso9660.c
2664+++ b/grub-core/fs/iso9660.c
2665@@ -28,6 +28,7 @@
2666 #include <grub/fshelp.h>
2667 #include <grub/charset.h>
2668 #include <grub/datetime.h>
2669+#include <grub/safemath.h>
2670
2671 GRUB_MOD_LICENSE ("GPLv3+");
2672
2673@@ -531,8 +532,13 @@ add_part (struct iterate_dir_ctx *ctx,
2674 int len2)
2675 {
2676 int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;
2677+ grub_size_t sz;
2678
2679- ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1);
2680+ if (grub_add (size, len2, &sz) ||
2681+ grub_add (sz, 1, &sz))
2682+ return;
2683+
2684+ ctx->symlink = grub_realloc (ctx->symlink, sz);
2685 if (! ctx->symlink)
2686 return;
2687
2688@@ -560,17 +566,24 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
2689 {
2690 grub_size_t off = 0, csize = 1;
2691 char *old;
2692+ grub_size_t sz;
2693+
2694 csize = entry->len - 5;
2695 old = ctx->filename;
2696 if (ctx->filename_alloc)
2697 {
2698 off = grub_strlen (ctx->filename);
2699- ctx->filename = grub_realloc (ctx->filename, csize + off + 1);
2700+ if (grub_add (csize, off, &sz) ||
2701+ grub_add (sz, 1, &sz))
2702+ return GRUB_ERR_OUT_OF_RANGE;
2703+ ctx->filename = grub_realloc (ctx->filename, sz);
2704 }
2705 else
2706 {
2707 off = 0;
2708- ctx->filename = grub_zalloc (csize + 1);
2709+ if (grub_add (csize, 1, &sz))
2710+ return GRUB_ERR_OUT_OF_RANGE;
2711+ ctx->filename = grub_zalloc (sz);
2712 }
2713 if (!ctx->filename)
2714 {
2715@@ -776,14 +789,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
2716 if (node->have_dirents >= node->alloc_dirents)
2717 {
2718 struct grub_fshelp_node *new_node;
2719- node->alloc_dirents *= 2;
2720- new_node = grub_realloc (node,
2721- sizeof (struct grub_fshelp_node)
2722- + ((node->alloc_dirents
2723- - ARRAY_SIZE (node->dirents))
2724- * sizeof (node->dirents[0])));
2725+ grub_size_t sz;
2726+
2727+ if (grub_mul (node->alloc_dirents, 2, &node->alloc_dirents) ||
2728+ grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) ||
2729+ grub_mul (sz, sizeof (node->dirents[0]), &sz) ||
2730+ grub_add (sz, sizeof (struct grub_fshelp_node), &sz))
2731+ goto fail_0;
2732+
2733+ new_node = grub_realloc (node, sz);
2734 if (!new_node)
2735 {
2736+ fail_0:
2737 if (ctx.filename_alloc)
2738 grub_free (ctx.filename);
2739 grub_free (node);
2740@@ -799,14 +816,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
2741 * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1)
2742 {
2743 struct grub_fshelp_node *new_node;
2744- new_node = grub_realloc (node,
2745- sizeof (struct grub_fshelp_node)
2746- + ((node->alloc_dirents
2747- - ARRAY_SIZE (node->dirents))
2748- * sizeof (node->dirents[0]))
2749- + grub_strlen (ctx.symlink) + 1);
2750+ grub_size_t sz;
2751+
2752+ if (grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) ||
2753+ grub_mul (sz, sizeof (node->dirents[0]), &sz) ||
2754+ grub_add (sz, sizeof (struct grub_fshelp_node) + 1, &sz) ||
2755+ grub_add (sz, grub_strlen (ctx.symlink), &sz))
2756+ goto fail_1;
2757+
2758+ new_node = grub_realloc (node, sz);
2759 if (!new_node)
2760 {
2761+ fail_1:
2762 if (ctx.filename_alloc)
2763 grub_free (ctx.filename);
2764 grub_free (node);
2765diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
2766index 90f7fb379..de2b107a4 100644
2767--- a/grub-core/fs/sfs.c
2768+++ b/grub-core/fs/sfs.c
2769@@ -26,6 +26,7 @@
2770 #include <grub/types.h>
2771 #include <grub/fshelp.h>
2772 #include <grub/charset.h>
2773+#include <grub/safemath.h>
2774
2775 GRUB_MOD_LICENSE ("GPLv3+");
2776
2777@@ -307,10 +308,15 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
2778 if (node->cache && node->cache_size >= node->cache_allocated)
2779 {
2780 struct cache_entry *e = node->cache;
2781- e = grub_realloc (node->cache,node->cache_allocated * 2
2782- * sizeof (e[0]));
2783+ grub_size_t sz;
2784+
2785+ if (grub_mul (node->cache_allocated, 2 * sizeof (e[0]), &sz))
2786+ goto fail;
2787+
2788+ e = grub_realloc (node->cache, sz);
2789 if (!e)
2790 {
2791+ fail:
2792 grub_errno = 0;
2793 grub_free (node->cache);
2794 node->cache = 0;
2795@@ -477,10 +483,16 @@ grub_sfs_create_node (struct grub_fshelp_node **node,
2796 grub_size_t len = grub_strlen (name);
2797 grub_uint8_t *name_u8;
2798 int ret;
2799+ grub_size_t sz;
2800+
2801+ if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) ||
2802+ grub_add (sz, 1, &sz))
2803+ return 1;
2804+
2805 *node = grub_malloc (sizeof (**node));
2806 if (!*node)
2807 return 1;
2808- name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
2809+ name_u8 = grub_malloc (sz);
2810 if (!name_u8)
2811 {
2812 grub_free (*node);
2813@@ -724,8 +736,13 @@ grub_sfs_label (grub_device_t device, char **label)
2814 data = grub_sfs_mount (disk);
2815 if (data)
2816 {
2817- grub_size_t len = grub_strlen (data->label);
2818- *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
2819+ grub_size_t sz, len = grub_strlen (data->label);
2820+
2821+ if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) ||
2822+ grub_add (sz, 1, &sz))
2823+ return GRUB_ERR_OUT_OF_RANGE;
2824+
2825+ *label = grub_malloc (sz);
2826 if (*label)
2827 *grub_latin1_to_utf8 ((grub_uint8_t *) *label,
2828 (const grub_uint8_t *) data->label,
2829diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
2830index 95d5c1e1f..785123894 100644
2831--- a/grub-core/fs/squash4.c
2832+++ b/grub-core/fs/squash4.c
2833@@ -26,6 +26,7 @@
2834 #include <grub/types.h>
2835 #include <grub/fshelp.h>
2836 #include <grub/deflate.h>
2837+#include <grub/safemath.h>
2838 #include <minilzo.h>
2839
2840 #include "xz.h"
2841@@ -459,7 +460,17 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
2842 {
2843 char *ret;
2844 grub_err_t err;
2845- ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1);
2846+ grub_size_t sz;
2847+
2848+ if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz))
2849+ {
2850+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
2851+ return NULL;
2852+ }
2853+
2854+ ret = grub_malloc (sz);
2855+ if (!ret)
2856+ return NULL;
2857
2858 err = read_chunk (node->data, ret,
2859 grub_le_to_cpu32 (node->ino.symlink.namelen),
2860@@ -506,11 +517,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
2861
2862 {
2863 grub_fshelp_node_t node;
2864- node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
2865+ grub_size_t sz;
2866+
2867+ if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) ||
2868+ grub_add (sz, sizeof (*node), &sz))
2869+ return 0;
2870+
2871+ node = grub_malloc (sz);
2872 if (!node)
2873 return 0;
2874- grub_memcpy (node, dir,
2875- sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
2876+ grub_memcpy (node, dir, sz);
2877 if (hook (".", GRUB_FSHELP_DIR, node, hook_data))
2878 return 1;
2879
2880@@ -518,12 +534,15 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
2881 {
2882 grub_err_t err;
2883
2884- node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
2885+ if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) ||
2886+ grub_add (sz, sizeof (*node), &sz))
2887+ return 0;
2888+
2889+ node = grub_malloc (sz);
2890 if (!node)
2891 return 0;
2892
2893- grub_memcpy (node, dir,
2894- sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
2895+ grub_memcpy (node, dir, sz);
2896
2897 node->stsize--;
2898 err = read_chunk (dir->data, &node->ino, sizeof (node->ino),
2899@@ -557,6 +576,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
2900 enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG;
2901 struct grub_squash_dirent di;
2902 struct grub_squash_inode ino;
2903+ grub_size_t sz;
2904
2905 err = read_chunk (dir->data, &di, sizeof (di),
2906 grub_le_to_cpu64 (dir->data->sb.diroffset)
2907@@ -589,13 +609,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
2908 if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK)
2909 filetype = GRUB_FSHELP_SYMLINK;
2910
2911- node = grub_malloc (sizeof (*node)
2912- + (dir->stsize + 1) * sizeof (dir->stack[0]));
2913+ if (grub_add (dir->stsize, 1, &sz) ||
2914+ grub_mul (sz, sizeof (dir->stack[0]), &sz) ||
2915+ grub_add (sz, sizeof (*node), &sz))
2916+ return 0;
2917+
2918+ node = grub_malloc (sz);
2919 if (! node)
2920 return 0;
2921
2922- grub_memcpy (node, dir,
2923- sizeof (*node) + dir->stsize * sizeof (dir->stack[0]));
2924+ grub_memcpy (node, dir, sz - sizeof(dir->stack[0]));
2925
2926 node->ino = ino;
2927 node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
2928diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
2929index a83761674..21ac7f446 100644
2930--- a/grub-core/fs/udf.c
2931+++ b/grub-core/fs/udf.c
2932@@ -28,6 +28,7 @@
2933 #include <grub/charset.h>
2934 #include <grub/datetime.h>
2935 #include <grub/udf.h>
2936+#include <grub/safemath.h>
2937
2938 GRUB_MOD_LICENSE ("GPLv3+");
2939
2940@@ -890,9 +891,19 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf)
2941 utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2];
2942 }
2943 if (!outbuf)
2944- outbuf = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1);
2945+ {
2946+ grub_size_t size;
2947+
2948+ if (grub_mul (utf16len, GRUB_MAX_UTF8_PER_UTF16, &size) ||
2949+ grub_add (size, 1, &size))
2950+ goto fail;
2951+
2952+ outbuf = grub_malloc (size);
2953+ }
2954 if (outbuf)
2955 *grub_utf16_to_utf8 ((grub_uint8_t *) outbuf, utf16, utf16len) = '\0';
2956+
2957+ fail:
2958 grub_free (utf16);
2959 return outbuf;
2960 }
2961@@ -1005,7 +1016,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
2962 grub_size_t sz = U64 (node->block.fe.file_size);
2963 grub_uint8_t *raw;
2964 const grub_uint8_t *ptr;
2965- char *out, *optr;
2966+ char *out = NULL, *optr;
2967
2968 if (sz < 4)
2969 return NULL;
2970@@ -1013,14 +1024,16 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
2971 if (!raw)
2972 return NULL;
2973 if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0)
2974- {
2975- grub_free (raw);
2976- return NULL;
2977- }
2978+ goto fail_1;
2979
2980- out = grub_malloc (sz * 2 + 1);
2981+ if (grub_mul (sz, 2, &sz) ||
2982+ grub_add (sz, 1, &sz))
2983+ goto fail_0;
2984+
2985+ out = grub_malloc (sz);
2986 if (!out)
2987 {
2988+ fail_0:
2989 grub_free (raw);
2990 return NULL;
2991 }
2992@@ -1031,17 +1044,17 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
2993 {
2994 grub_size_t s;
2995 if ((grub_size_t) (ptr - raw + 4) > sz)
2996- goto fail;
2997+ goto fail_1;
2998 if (!(ptr[2] == 0 && ptr[3] == 0))
2999- goto fail;
3000+ goto fail_1;
3001 s = 4 + ptr[1];
3002 if ((grub_size_t) (ptr - raw + s) > sz)
3003- goto fail;
3004+ goto fail_1;
3005 switch (*ptr)
3006 {
3007 case 1:
3008 if (ptr[1])
3009- goto fail;
3010+ goto fail_1;
3011 /* Fallthrough. */
3012 case 2:
3013 /* in 4 bytes. out: 1 byte. */
3014@@ -1066,11 +1079,11 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
3015 if (optr != out)
3016 *optr++ = '/';
3017 if (!read_string (ptr + 4, s - 4, optr))
3018- goto fail;
3019+ goto fail_1;
3020 optr += grub_strlen (optr);
3021 break;
3022 default:
3023- goto fail;
3024+ goto fail_1;
3025 }
3026 ptr += s;
3027 }
3028@@ -1078,7 +1091,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node)
3029 grub_free (raw);
3030 return out;
3031
3032- fail:
3033+ fail_1:
3034 grub_free (raw);
3035 grub_free (out);
3036 grub_error (GRUB_ERR_BAD_FS, "invalid symlink");
3037diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
3038index 96ffecbfc..ea6590290 100644
3039--- a/grub-core/fs/xfs.c
3040+++ b/grub-core/fs/xfs.c
3041@@ -25,6 +25,7 @@
3042 #include <grub/dl.h>
3043 #include <grub/types.h>
3044 #include <grub/fshelp.h>
3045+#include <grub/safemath.h>
3046
3047 GRUB_MOD_LICENSE ("GPLv3+");
3048
3049@@ -899,6 +900,7 @@ static struct grub_xfs_data *
3050 grub_xfs_mount (grub_disk_t disk)
3051 {
3052 struct grub_xfs_data *data = 0;
3053+ grub_size_t sz;
3054
3055 data = grub_zalloc (sizeof (struct grub_xfs_data));
3056 if (!data)
3057@@ -913,10 +915,11 @@ grub_xfs_mount (grub_disk_t disk)
3058 if (!grub_xfs_sb_valid(data))
3059 goto fail;
3060
3061- data = grub_realloc (data,
3062- sizeof (struct grub_xfs_data)
3063- - sizeof (struct grub_xfs_inode)
3064- + grub_xfs_inode_size(data) + 1);
3065+ if (grub_add (grub_xfs_inode_size (data),
3066+ sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) + 1, &sz))
3067+ goto fail;
3068+
3069+ data = grub_realloc (data, sz);
3070
3071 if (! data)
3072 goto fail;
3073diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
3074index 381dde556..36d0373a6 100644
3075--- a/grub-core/fs/zfs/zfs.c
3076+++ b/grub-core/fs/zfs/zfs.c
3077@@ -55,6 +55,7 @@
3078 #include <grub/deflate.h>
3079 #include <grub/crypto.h>
3080 #include <grub/i18n.h>
3081+#include <grub/safemath.h>
3082
3083 GRUB_MOD_LICENSE ("GPLv3+");
3084
3085@@ -773,11 +774,14 @@ fill_vdev_info (struct grub_zfs_data *data,
3086 if (data->n_devices_attached > data->n_devices_allocated)
3087 {
3088 void *tmp;
3089- data->n_devices_allocated = 2 * data->n_devices_attached + 1;
3090- data->devices_attached
3091- = grub_realloc (tmp = data->devices_attached,
3092- data->n_devices_allocated
3093- * sizeof (data->devices_attached[0]));
3094+ grub_size_t sz;
3095+
3096+ if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) ||
3097+ grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) ||
3098+ grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz))
3099+ return GRUB_ERR_OUT_OF_RANGE;
3100+
3101+ data->devices_attached = grub_realloc (tmp = data->devices_attached, sz);
3102 if (!data->devices_attached)
3103 {
3104 data->devices_attached = tmp;
3105@@ -3468,14 +3472,18 @@ grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name)
3106 {
3107 char *nvpair;
3108 char *ret;
3109- grub_size_t size;
3110+ grub_size_t size, sz;
3111 int found;
3112
3113 found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair,
3114 &size, 0);
3115 if (!found)
3116 return 0;
3117- ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t));
3118+
3119+ if (grub_add (size, 3 * sizeof (grub_uint32_t), &sz))
3120+ return 0;
3121+
3122+ ret = grub_zalloc (sz);
3123 if (!ret)
3124 return 0;
3125 grub_memcpy (ret, nvlist, sizeof (grub_uint32_t));
3126diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c
3127index 1402e0bc2..de3b015f5 100644
3128--- a/grub-core/fs/zfs/zfscrypt.c
3129+++ b/grub-core/fs/zfs/zfscrypt.c
3130@@ -22,6 +22,7 @@
3131 #include <grub/misc.h>
3132 #include <grub/disk.h>
3133 #include <grub/partition.h>
3134+#include <grub/safemath.h>
3135 #include <grub/dl.h>
3136 #include <grub/types.h>
3137 #include <grub/zfs/zfs.h>
3138@@ -82,9 +83,13 @@ grub_zfs_add_key (grub_uint8_t *key_in,
3139 int passphrase)
3140 {
3141 struct grub_zfs_wrap_key *key;
3142+ grub_size_t sz;
3143+
3144 if (!passphrase && keylen > 32)
3145 keylen = 32;
3146- key = grub_malloc (sizeof (*key) + keylen);
3147+ if (grub_add (sizeof (*key), keylen, &sz))
3148+ return GRUB_ERR_OUT_OF_RANGE;
3149+ key = grub_malloc (sz);
3150 if (!key)
3151 return grub_errno;
3152 key->is_passphrase = passphrase;
3153diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c
3154index fd7744a6f..3288609a5 100644
3155--- a/grub-core/lib/arg.c
3156+++ b/grub-core/lib/arg.c
3157@@ -23,6 +23,7 @@
3158 #include <grub/term.h>
3159 #include <grub/extcmd.h>
3160 #include <grub/i18n.h>
3161+#include <grub/safemath.h>
3162
3163 /* Built-in parser for default options. */
3164 static const struct grub_arg_option help_options[] =
3165@@ -216,7 +217,13 @@ static inline grub_err_t
3166 add_arg (char ***argl, int *num, char *s)
3167 {
3168 char **p = *argl;
3169- *argl = grub_realloc (*argl, (++(*num) + 1) * sizeof (char *));
3170+ grub_size_t sz;
3171+
3172+ if (grub_add (++(*num), 1, &sz) ||
3173+ grub_mul (sz, sizeof (char *), &sz))
3174+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
3175+
3176+ *argl = grub_realloc (*argl, sz);
3177 if (! *argl)
3178 {
3179 grub_free (p);
3180@@ -431,6 +438,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc,
3181 grub_size_t argcnt;
3182 struct grub_arg_list *list;
3183 const struct grub_arg_option *options;
3184+ grub_size_t sz0, sz1;
3185
3186 options = extcmd->options;
3187 if (! options)
3188@@ -443,7 +451,15 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc,
3189 argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */
3190 }
3191
3192- list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt);
3193+ if (grub_mul (sizeof (*list), i, &sz0) ||
3194+ grub_mul (sizeof (char *), argcnt, &sz1) ||
3195+ grub_add (sz0, sz1, &sz0))
3196+ {
3197+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
3198+ return 0;
3199+ }
3200+
3201+ list = grub_zalloc (sz0);
3202 if (! list)
3203 return 0;
3204
3205diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
3206index 3730ed382..b92cbe98d 100644
3207--- a/grub-core/loader/i386/bsd.c
3208+++ b/grub-core/loader/i386/bsd.c
3209@@ -35,6 +35,7 @@
3210 #include <grub/ns8250.h>
3211 #include <grub/bsdlabel.h>
3212 #include <grub/crypto.h>
3213+#include <grub/safemath.h>
3214 #include <grub/verify.h>
3215 #ifdef GRUB_MACHINE_PCBIOS
3216 #include <grub/machine/int.h>
3217@@ -1012,11 +1013,16 @@ grub_netbsd_add_modules (void)
3218 struct grub_netbsd_btinfo_modules *mods;
3219 unsigned i;
3220 grub_err_t err;
3221+ grub_size_t sz;
3222
3223 for (mod = netbsd_mods; mod; mod = mod->next)
3224 modcnt++;
3225
3226- mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt);
3227+ if (grub_mul (modcnt, sizeof (mods->mods[0]), &sz) ||
3228+ grub_add (sz, sizeof (*mods), &sz))
3229+ return GRUB_ERR_OUT_OF_RANGE;
3230+
3231+ mods = grub_malloc (sz);
3232 if (!mods)
3233 return grub_errno;
3234
3235diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
3236index e332d5eb4..906ec7d67 100644
3237--- a/grub-core/net/dns.c
3238+++ b/grub-core/net/dns.c
3239@@ -22,6 +22,7 @@
3240 #include <grub/i18n.h>
3241 #include <grub/err.h>
3242 #include <grub/time.h>
3243+#include <grub/safemath.h>
3244
3245 struct dns_cache_element
3246 {
3247@@ -51,9 +52,15 @@ grub_net_add_dns_server (const struct grub_net_network_level_address *s)
3248 {
3249 int na = dns_servers_alloc * 2;
3250 struct grub_net_network_level_address *ns;
3251+ grub_size_t sz;
3252+
3253 if (na < 8)
3254 na = 8;
3255- ns = grub_realloc (dns_servers, na * sizeof (ns[0]));
3256+
3257+ if (grub_mul (na, sizeof (ns[0]), &sz))
3258+ return GRUB_ERR_OUT_OF_RANGE;
3259+
3260+ ns = grub_realloc (dns_servers, sz);
3261 if (!ns)
3262 return grub_errno;
3263 dns_servers_alloc = na;
3264diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
3265index d57fb72fa..4dfcc3107 100644
3266--- a/grub-core/normal/charset.c
3267+++ b/grub-core/normal/charset.c
3268@@ -48,6 +48,7 @@
3269 #include <grub/unicode.h>
3270 #include <grub/term.h>
3271 #include <grub/normal.h>
3272+#include <grub/safemath.h>
3273
3274 #if HAVE_FONT_SOURCE
3275 #include "widthspec.h"
3276@@ -464,6 +465,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
3277 {
3278 struct grub_unicode_combining *n;
3279 unsigned j;
3280+ grub_size_t sz;
3281
3282 if (!haveout)
3283 continue;
3284@@ -477,10 +479,14 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen,
3285 n = out->combining_inline;
3286 else if (out->ncomb > (int) ARRAY_SIZE (out->combining_inline))
3287 {
3288- n = grub_realloc (out->combining_ptr,
3289- sizeof (n[0]) * (out->ncomb + 1));
3290+ if (grub_add (out->ncomb, 1, &sz) ||
3291+ grub_mul (sz, sizeof (n[0]), &sz))
3292+ goto fail;
3293+
3294+ n = grub_realloc (out->combining_ptr, sz);
3295 if (!n)
3296 {
3297+ fail:
3298 grub_errno = GRUB_ERR_NONE;
3299 continue;
3300 }
3301diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c
3302index c57242e2e..de03fe63b 100644
3303--- a/grub-core/normal/cmdline.c
3304+++ b/grub-core/normal/cmdline.c
3305@@ -28,6 +28,7 @@
3306 #include <grub/env.h>
3307 #include <grub/i18n.h>
3308 #include <grub/charset.h>
3309+#include <grub/safemath.h>
3310
3311 static grub_uint32_t *kill_buf;
3312
3313@@ -307,12 +308,21 @@ cl_insert (struct cmdline_term *cl_terms, unsigned nterms,
3314 if (len + (*llen) >= (*max_len))
3315 {
3316 grub_uint32_t *nbuf;
3317- (*max_len) *= 2;
3318- nbuf = grub_realloc ((*buf), sizeof (grub_uint32_t) * (*max_len));
3319+ grub_size_t sz;
3320+
3321+ if (grub_mul (*max_len, 2, max_len) ||
3322+ grub_mul (*max_len, sizeof (grub_uint32_t), &sz))
3323+ {
3324+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
3325+ goto fail;
3326+ }
3327+
3328+ nbuf = grub_realloc ((*buf), sz);
3329 if (nbuf)
3330 (*buf) = nbuf;
3331 else
3332 {
3333+ fail:
3334 grub_print_error ();
3335 grub_errno = GRUB_ERR_NONE;
3336 (*max_len) /= 2;
3337diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
3338index 1993995be..50eef918c 100644
3339--- a/grub-core/normal/menu_entry.c
3340+++ b/grub-core/normal/menu_entry.c
3341@@ -27,6 +27,7 @@
3342 #include <grub/auth.h>
3343 #include <grub/i18n.h>
3344 #include <grub/charset.h>
3345+#include <grub/safemath.h>
3346
3347 enum update_mode
3348 {
3349@@ -113,10 +114,18 @@ ensure_space (struct line *linep, int extra)
3350 {
3351 if (linep->max_len < linep->len + extra)
3352 {
3353- linep->max_len = 2 * (linep->len + extra);
3354- linep->buf = grub_realloc (linep->buf, (linep->max_len + 1) * sizeof (linep->buf[0]));
3355+ grub_size_t sz0, sz1;
3356+
3357+ if (grub_add (linep->len, extra, &sz0) ||
3358+ grub_mul (sz0, 2, &sz0) ||
3359+ grub_add (sz0, 1, &sz1) ||
3360+ grub_mul (sz1, sizeof (linep->buf[0]), &sz1))
3361+ return 0;
3362+
3363+ linep->buf = grub_realloc (linep->buf, sz1);
3364 if (! linep->buf)
3365 return 0;
3366+ linep->max_len = sz0;
3367 }
3368
3369 return 1;
3370diff --git a/grub-core/script/argv.c b/grub-core/script/argv.c
3371index 217ec5d1e..5751fdd57 100644
3372--- a/grub-core/script/argv.c
3373+++ b/grub-core/script/argv.c
3374@@ -20,6 +20,7 @@
3375 #include <grub/mm.h>
3376 #include <grub/misc.h>
3377 #include <grub/script_sh.h>
3378+#include <grub/safemath.h>
3379
3380 /* Return nearest power of two that is >= v. */
3381 static unsigned
3382@@ -81,11 +82,16 @@ int
3383 grub_script_argv_next (struct grub_script_argv *argv)
3384 {
3385 char **p = argv->args;
3386+ grub_size_t sz;
3387
3388 if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0)
3389 return 0;
3390
3391- p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *)));
3392+ if (grub_add (argv->argc, 2, &sz) ||
3393+ grub_mul (sz, sizeof (char *), &sz))
3394+ return 1;
3395+
3396+ p = grub_realloc (p, round_up_exp (sz));
3397 if (! p)
3398 return 1;
3399
3400@@ -105,13 +111,19 @@ grub_script_argv_append (struct grub_script_argv *argv, const char *s,
3401 {
3402 grub_size_t a;
3403 char *p = argv->args[argv->argc - 1];
3404+ grub_size_t sz;
3405
3406 if (! s)
3407 return 0;
3408
3409 a = p ? grub_strlen (p) : 0;
3410
3411- p = grub_realloc (p, round_up_exp ((a + slen + 1) * sizeof (char)));
3412+ if (grub_add (a, slen, &sz) ||
3413+ grub_add (sz, 1, &sz) ||
3414+ grub_mul (sz, sizeof (char), &sz))
3415+ return 1;
3416+
3417+ p = grub_realloc (p, round_up_exp (sz));
3418 if (! p)
3419 return 1;
3420
3421diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c
3422index c6bd3172f..5fb0cbd0b 100644
3423--- a/grub-core/script/lexer.c
3424+++ b/grub-core/script/lexer.c
3425@@ -24,6 +24,7 @@
3426 #include <grub/mm.h>
3427 #include <grub/script_sh.h>
3428 #include <grub/i18n.h>
3429+#include <grub/safemath.h>
3430
3431 #define yytext_ptr char *
3432 #include "grub_script.tab.h"
3433@@ -110,10 +111,14 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str)
3434 old = lexer->recording;
3435 if (lexer->recordlen < len)
3436 lexer->recordlen = len;
3437- lexer->recordlen *= 2;
3438+
3439+ if (grub_mul (lexer->recordlen, 2, &lexer->recordlen))
3440+ goto fail;
3441+
3442 lexer->recording = grub_realloc (lexer->recording, lexer->recordlen);
3443 if (!lexer->recording)
3444 {
3445+ fail:
3446 grub_free (old);
3447 lexer->recordpos = 0;
3448 lexer->recordlen = 0;
3449@@ -130,7 +135,7 @@ int
3450 grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
3451 const char *input)
3452 {
3453- grub_size_t len = 0;
3454+ grub_size_t len = 0, sz;
3455 char *p = 0;
3456 char *line = 0;
3457 YY_BUFFER_STATE buffer;
3458@@ -168,12 +173,22 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
3459 }
3460 else if (len && line[len - 1] != '\n')
3461 {
3462- p = grub_realloc (line, len + 2);
3463+ if (grub_add (len, 2, &sz))
3464+ {
3465+ grub_free (line);
3466+ grub_script_yyerror (parserstate, N_("overflow is detected"));
3467+ return 1;
3468+ }
3469+
3470+ p = grub_realloc (line, sz);
3471 if (p)
3472 {
3473 p[len++] = '\n';
3474 p[len] = '\0';
3475 }
3476+ else
3477+ grub_free (line);
3478+
3479 line = p;
3480 }
3481
3482diff --git a/grub-core/video/bitmap.c b/grub-core/video/bitmap.c
3483index b2e031566..6256e209a 100644
3484--- a/grub-core/video/bitmap.c
3485+++ b/grub-core/video/bitmap.c
3486@@ -23,6 +23,7 @@
3487 #include <grub/mm.h>
3488 #include <grub/misc.h>
3489 #include <grub/i18n.h>
3490+#include <grub/safemath.h>
3491
3492 GRUB_MOD_LICENSE ("GPLv3+");
3493
3494@@ -58,7 +59,7 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
3495 enum grub_video_blit_format blit_format)
3496 {
3497 struct grub_video_mode_info *mode_info;
3498- unsigned int size;
3499+ grub_size_t size;
3500
3501 if (!bitmap)
3502 return grub_error (GRUB_ERR_BUG, "invalid argument");
3503@@ -137,19 +138,25 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
3504
3505 mode_info->pitch = width * mode_info->bytes_per_pixel;
3506
3507- /* Calculate size needed for the data. */
3508- size = (width * mode_info->bytes_per_pixel) * height;
3509+ /* Calculate size needed for the data. */
3510+ if (grub_mul (width, mode_info->bytes_per_pixel, &size) ||
3511+ grub_mul (size, height, &size))
3512+ {
3513+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
3514+ goto fail;
3515+ }
3516
3517 (*bitmap)->data = grub_zalloc (size);
3518 if (! (*bitmap)->data)
3519- {
3520- grub_free (*bitmap);
3521- *bitmap = 0;
3522-
3523- return grub_errno;
3524- }
3525+ goto fail;
3526
3527 return GRUB_ERR_NONE;
3528+
3529+ fail:
3530+ grub_free (*bitmap);
3531+ *bitmap = NULL;
3532+
3533+ return grub_errno;
3534 }
3535
3536 /* Frees all resources allocated by bitmap. */
3537diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
3538index 61bd64537..0157ff742 100644
3539--- a/grub-core/video/readers/png.c
3540+++ b/grub-core/video/readers/png.c
3541@@ -23,6 +23,7 @@
3542 #include <grub/mm.h>
3543 #include <grub/misc.h>
3544 #include <grub/bufio.h>
3545+#include <grub/safemath.h>
3546
3547 GRUB_MOD_LICENSE ("GPLv3+");
3548
3549@@ -301,9 +302,17 @@ grub_png_decode_image_header (struct grub_png_data *data)
3550 data->bpp <<= 1;
3551
3552 data->color_bits = color_bits;
3553- data->row_bytes = data->image_width * data->bpp;
3554+
3555+ if (grub_mul (data->image_width, data->bpp, &data->row_bytes))
3556+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
3557+
3558 if (data->color_bits <= 4)
3559- data->row_bytes = (data->image_width * data->color_bits + 7) / 8;
3560+ {
3561+ if (grub_mul (data->image_width, data->color_bits + 7, &data->row_bytes))
3562+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
3563+
3564+ data->row_bytes >>= 3;
3565+ }
3566
3567 #ifndef GRUB_CPU_WORDS_BIGENDIAN
3568 if (data->is_16bit || data->is_gray || data->is_palette)
3569
3570From 99c176e216b7196ac8d2af2b9bc483070b1a170a Mon Sep 17 00:00:00 2001
3571From: Peter Jones <pjones@redhat.com>
3572Date: Sat, 4 Jul 2020 12:25:09 -0400
3573Subject: iso9660: Don't leak memory on realloc() failures
3574
3575Signed-off-by: Peter Jones <pjones@redhat.com>
3576Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3577---
3578 grub-core/fs/iso9660.c | 24 ++++++++++++++++++++----
3579 1 file changed, 20 insertions(+), 4 deletions(-)
3580
3581diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
3582index 7ba5b300b..5ec4433b8 100644
3583--- a/grub-core/fs/iso9660.c
3584+++ b/grub-core/fs/iso9660.c
3585@@ -533,14 +533,20 @@ add_part (struct iterate_dir_ctx *ctx,
3586 {
3587 int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;
3588 grub_size_t sz;
3589+ char *new;
3590
3591 if (grub_add (size, len2, &sz) ||
3592 grub_add (sz, 1, &sz))
3593 return;
3594
3595- ctx->symlink = grub_realloc (ctx->symlink, sz);
3596- if (! ctx->symlink)
3597- return;
3598+ new = grub_realloc (ctx->symlink, sz);
3599+ if (!new)
3600+ {
3601+ grub_free (ctx->symlink);
3602+ ctx->symlink = NULL;
3603+ return;
3604+ }
3605+ ctx->symlink = new;
3606
3607 grub_memcpy (ctx->symlink + size, part, len2);
3608 ctx->symlink[size + len2] = 0;
3609@@ -634,7 +640,12 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
3610 is the length. Both are part of the `Component
3611 Record'. */
3612 if (ctx->symlink && !ctx->was_continue)
3613- add_part (ctx, "/", 1);
3614+ {
3615+ add_part (ctx, "/", 1);
3616+ if (grub_errno)
3617+ return grub_errno;
3618+ }
3619+
3620 add_part (ctx, (char *) &entry->data[pos + 2],
3621 entry->data[pos + 1]);
3622 ctx->was_continue = (entry->data[pos] & 1);
3623@@ -653,6 +664,11 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
3624 add_part (ctx, "/", 1);
3625 break;
3626 }
3627+
3628+ /* Check if grub_realloc() failed in add_part(). */
3629+ if (grub_errno)
3630+ return grub_errno;
3631+
3632 /* In pos + 1 the length of the `Component Record' is
3633 stored. */
3634 pos += entry->data[pos + 1] + 2;
3635
3636From fcc11dc1e68192d50cfb914314fb5e2f0504c498 Mon Sep 17 00:00:00 2001
3637From: Daniel Kiper <daniel.kiper@oracle.com>
3638Date: Tue, 7 Jul 2020 15:36:26 +0200
3639Subject: font: Do not load more than one NAME section
3640
3641The GRUB font file can have one NAME section only. Though if somebody
3642crafts a broken font file with many NAME sections and loads it then the
3643GRUB leaks memory. So, prevent against that by loading first NAME
3644section and failing in controlled way on following one.
3645
3646Reported-by: Chris Coulson <chris.coulson@canonical.com>
3647Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
3648Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
3649---
3650 grub-core/font/font.c | 6 ++++++
3651 1 file changed, 6 insertions(+)
3652
3653diff --git a/grub-core/font/font.c b/grub-core/font/font.c
3654index 5edb477ac..d09bb38d8 100644
3655--- a/grub-core/font/font.c
3656+++ b/grub-core/font/font.c
3657@@ -532,6 +532,12 @@ grub_font_load (const char *filename)
3658 if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME,
3659 sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
3660 {
3661+ if (font->name != NULL)
3662+ {
3663+ grub_error (GRUB_ERR_BAD_FONT, "invalid font file: too many NAME sections");
3664+ goto fail;
3665+ }
3666+
3667 font->name = read_section_as_string (&section);
3668 if (!font->name)
3669 goto fail;
3670
3671From e283bb250350e8c2f7edeb344a624c57c26b042f Mon Sep 17 00:00:00 2001
3672From: Alexey Makhalov <amakhalov@vmware.com>
3673Date: Wed, 8 Jul 2020 20:41:56 +0000
3674Subject: gfxmenu: Fix double free in load_image()
3675
3676self->bitmap should be zeroed after free. Otherwise, there is a chance
3677to double free (USE_AFTER_FREE) it later in rescale_image().
3678
3679Fixes: CID 292472
3680
3681Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
3682Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3683---
3684 grub-core/gfxmenu/gui_image.c | 5 ++++-
3685 1 file changed, 4 insertions(+), 1 deletion(-)
3686
3687diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c
3688index 29784ed2d..6b2e976f1 100644
3689--- a/grub-core/gfxmenu/gui_image.c
3690+++ b/grub-core/gfxmenu/gui_image.c
3691@@ -195,7 +195,10 @@ load_image (grub_gui_image_t self, const char *path)
3692 return grub_errno;
3693
3694 if (self->bitmap && (self->bitmap != self->raw_bitmap))
3695- grub_video_bitmap_destroy (self->bitmap);
3696+ {
3697+ grub_video_bitmap_destroy (self->bitmap);
3698+ self->bitmap = 0;
3699+ }
3700 if (self->raw_bitmap)
3701 grub_video_bitmap_destroy (self->raw_bitmap);
3702
3703
3704From 387219ffbb751afd336ebd71f1a375d9923ba416 Mon Sep 17 00:00:00 2001
3705From: Alexey Makhalov <amakhalov@vmware.com>
3706Date: Wed, 8 Jul 2020 21:30:43 +0000
3707Subject: xnu: Fix double free in grub_xnu_devprop_add_property()
3708
3709grub_xnu_devprop_add_property() should not free utf8 and utf16 as it get
3710allocated and freed in the caller.
3711
3712Minor improvement: do prop fields initialization after memory allocations.
3713
3714Fixes: CID 292442, CID 292457, CID 292460, CID 292466
3715
3716Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
3717Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3718---
3719 grub-core/loader/i386/xnu.c | 17 ++++++++---------
3720 1 file changed, 8 insertions(+), 9 deletions(-)
3721
3722diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
3723index b7d176b5d..e9e119259 100644
3724--- a/grub-core/loader/i386/xnu.c
3725+++ b/grub-core/loader/i386/xnu.c
3726@@ -262,20 +262,19 @@ grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor *dev,
3727 if (!prop)
3728 return grub_errno;
3729
3730- prop->name = utf8;
3731- prop->name16 = utf16;
3732- prop->name16len = utf16len;
3733-
3734- prop->length = datalen;
3735- prop->data = grub_malloc (prop->length);
3736+ prop->data = grub_malloc (datalen);
3737 if (!prop->data)
3738 {
3739- grub_free (prop->name);
3740- grub_free (prop->name16);
3741 grub_free (prop);
3742 return grub_errno;
3743 }
3744- grub_memcpy (prop->data, data, prop->length);
3745+ grub_memcpy (prop->data, data, datalen);
3746+
3747+ prop->name = utf8;
3748+ prop->name16 = utf16;
3749+ prop->name16len = utf16len;
3750+ prop->length = datalen;
3751+
3752 grub_list_push (GRUB_AS_LIST_P (&dev->properties),
3753 GRUB_AS_LIST (prop));
3754 return GRUB_ERR_NONE;
3755
3756From 8b93dd5ba38c2d726a08b271b14a74e8f960d147 Mon Sep 17 00:00:00 2001
3757From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3758Date: Thu, 9 Jul 2020 03:05:23 +0000
3759Subject: lzma: Make sure we don't dereference past array
3760
3761The two dimensional array p->posSlotEncoder[4][64] is being dereferenced
3762using the GetLenToPosState() macro which checks if len is less than 5,
3763and if so subtracts 2 from it. If len = 0, that is 0 - 2 = 4294967294.
3764Obviously we don't want to dereference that far out so we check if the
3765position found is greater or equal kNumLenToPosStates (4) and bail out.
3766
3767N.B.: Upstream LZMA 18.05 and later has this function completely rewritten
3768without any history.
3769
3770Fixes: CID 51526
3771
3772Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3773Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3774---
3775 grub-core/lib/LzmaEnc.c | 10 ++++++++--
3776 1 file changed, 8 insertions(+), 2 deletions(-)
3777
3778diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c
3779index f2ec04a8c..753e56a95 100644
3780--- a/grub-core/lib/LzmaEnc.c
3781+++ b/grub-core/lib/LzmaEnc.c
3782@@ -1877,13 +1877,19 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
3783 }
3784 else
3785 {
3786- UInt32 posSlot;
3787+ UInt32 posSlot, lenToPosState;
3788 RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
3789 p->state = kMatchNextStates[p->state];
3790 LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
3791 pos -= LZMA_NUM_REPS;
3792 GetPosSlot(pos, posSlot);
3793- RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
3794+ lenToPosState = GetLenToPosState(len);
3795+ if (lenToPosState >= kNumLenToPosStates)
3796+ {
3797+ p->result = SZ_ERROR_DATA;
3798+ return CheckErrors(p);
3799+ }
3800+ RcTree_Encode(&p->rc, p->posSlotEncoder[lenToPosState], kNumPosSlotBits, posSlot);
3801
3802 if (posSlot >= kStartPosModelIndex)
3803 {
3804
3805From 2328abbe2caa2129084da04a3e19461ddc571549 Mon Sep 17 00:00:00 2001
3806From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3807Date: Tue, 7 Jul 2020 15:12:25 -0400
3808Subject: term: Fix overflow on user inputs
3809
3810This requires a very weird input from the serial interface but can cause
3811an overflow in input_buf (keys) overwriting the next variable (npending)
3812with the user choice:
3813
3814(pahole output)
3815
3816struct grub_terminfo_input_state {
3817 int input_buf[6]; /* 0 24 */
3818 int npending; /* 24 4 */ <- CORRUPT
3819 ...snip...
3820
3821The magic string requires causing this is "ESC,O,],0,1,2,q" and we overflow
3822npending with "q" (aka increase npending to 161). The simplest fix is to
3823just to disallow overwrites input_buf, which exactly what this patch does.
3824
3825Fixes: CID 292449
3826
3827Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3828Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3829---
3830 grub-core/term/terminfo.c | 9 ++++++---
3831 1 file changed, 6 insertions(+), 3 deletions(-)
3832
3833diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
3834index 63892ad42..aa3a108ca 100644
3835--- a/grub-core/term/terminfo.c
3836+++ b/grub-core/term/terminfo.c
3837@@ -398,7 +398,7 @@ grub_terminfo_getwh (struct grub_term_output *term)
3838 }
3839
3840 static void
3841-grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
3842+grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, int max_len,
3843 int (*readkey) (struct grub_term_input *term))
3844 {
3845 int c;
3846@@ -414,6 +414,9 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
3847 if (c == -1) \
3848 return; \
3849 \
3850+ if (*len >= max_len) \
3851+ return; \
3852+ \
3853 keys[*len] = c; \
3854 (*len)++; \
3855 }
3856@@ -602,8 +605,8 @@ grub_terminfo_getkey (struct grub_term_input *termi)
3857 return ret;
3858 }
3859
3860- grub_terminfo_readkey (termi, data->input_buf,
3861- &data->npending, data->readkey);
3862+ grub_terminfo_readkey (termi, data->input_buf, &data->npending,
3863+ GRUB_TERMINFO_READKEY_MAX_LEN, data->readkey);
3864
3865 #if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)
3866 if (data->npending == 1 && data->input_buf[0] == GRUB_TERM_ESC
3867
3868From ba1d97845644290f03754432bcb6bbd6fefe7003 Mon Sep 17 00:00:00 2001
3869From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3870Date: Tue, 7 Jul 2020 22:02:31 -0400
3871Subject: udf: Fix memory leak
3872
3873Fixes: CID 73796
3874
3875Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3876Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3877Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
3878---
3879 grub-core/fs/udf.c | 17 +++++++++++++----
3880 1 file changed, 13 insertions(+), 4 deletions(-)
3881
3882diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
3883index 21ac7f446..2ac5c1d00 100644
3884--- a/grub-core/fs/udf.c
3885+++ b/grub-core/fs/udf.c
3886@@ -965,8 +965,10 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
3887 return 0;
3888
3889 if (grub_udf_read_icb (dir->data, &dirent.icb, child))
3890- return 0;
3891-
3892+ {
3893+ grub_free (child);
3894+ return 0;
3895+ }
3896 if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
3897 {
3898 /* This is the parent directory. */
3899@@ -988,11 +990,18 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
3900 dirent.file_ident_length,
3901 (char *) raw))
3902 != dirent.file_ident_length)
3903- return 0;
3904+ {
3905+ grub_free (child);
3906+ return 0;
3907+ }
3908
3909 filename = read_string (raw, dirent.file_ident_length, 0);
3910 if (!filename)
3911- grub_print_error ();
3912+ {
3913+ /* As the hook won't get called. */
3914+ grub_free (child);
3915+ grub_print_error ();
3916+ }
3917
3918 if (filename && hook (filename, type, child, hook_data))
3919 {
3920
3921From 3b39c2023f3aa242b008385939a7394e5946e94b Mon Sep 17 00:00:00 2001
3922From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3923Date: Fri, 26 Jun 2020 10:51:43 -0400
3924Subject: multiboot2: Fix memory leak if
3925 grub_create_loader_cmdline() fails
3926
3927Fixes: CID 292468
3928
3929Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
3930Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3931---
3932 grub-core/loader/multiboot_mbi2.c | 6 +++++-
3933 1 file changed, 5 insertions(+), 1 deletion(-)
3934
3935diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
3936index 53da78615..0efc66062 100644
3937--- a/grub-core/loader/multiboot_mbi2.c
3938+++ b/grub-core/loader/multiboot_mbi2.c
3939@@ -1070,7 +1070,11 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
3940 err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
3941 newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE);
3942 if (err)
3943- return err;
3944+ {
3945+ grub_free (newmod->cmdline);
3946+ grub_free (newmod);
3947+ return err;
3948+ }
3949
3950 if (modules_last)
3951 modules_last->next = newmod;
3952
3953From 7726da0d972c3996b3ced02586204334eb03d472 Mon Sep 17 00:00:00 2001
3954From: Alexey Makhalov <amakhalov@vmware.com>
3955Date: Thu, 9 Jul 2020 08:10:40 +0000
3956Subject: tftp: Do not use priority queue
3957
3958There is not need to reassemble the order of blocks. Per RFC 1350,
3959server must wait for the ACK, before sending next block. Data packets
3960can be served immediately without putting them to priority queue.
3961
3962Logic to handle incoming packet is this:
3963 - if packet block id equal to expected block id, then
3964 process the packet,
3965 - if packet block id is less than expected - this is retransmit
3966 of old packet, then ACK it and drop the packet,
3967 - if packet block id is more than expected - that shouldn't
3968 happen, just drop the packet.
3969
3970It makes the tftp receive path code simpler, smaller and faster.
3971As a benefit, this change fixes CID# 73624 and CID# 96690, caused
3972by following while loop:
3973
3974 while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
3975
3976where tftph pointer is not moving from one iteration to another, causing
3977to serve same packet again. Luckily, double serving didn't happen due to
3978data->block++ during the first iteration.
3979
3980Fixes: CID 73624, CID 96690
3981
3982Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
3983Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
3984---
3985 grub-core/net/tftp.c | 168 ++++++++++++++-----------------------------
3986 1 file changed, 53 insertions(+), 115 deletions(-)
3987
3988diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
3989index a0817a075..84229d03d 100644
3990--- a/grub-core/net/tftp.c
3991+++ b/grub-core/net/tftp.c
3992@@ -25,7 +25,6 @@
3993 #include <grub/mm.h>
3994 #include <grub/dl.h>
3995 #include <grub/file.h>
3996-#include <grub/priority_queue.h>
3997 #include <grub/i18n.h>
3998
3999 GRUB_MOD_LICENSE ("GPLv3+");
4000@@ -106,31 +105,8 @@ typedef struct tftp_data
4001 int have_oack;
4002 struct grub_error_saved save_err;
4003 grub_net_udp_socket_t sock;
4004- grub_priority_queue_t pq;
4005 } *tftp_data_t;
4006
4007-static int
4008-cmp_block (grub_uint16_t a, grub_uint16_t b)
4009-{
4010- grub_int16_t i = (grub_int16_t) (a - b);
4011- if (i > 0)
4012- return +1;
4013- if (i < 0)
4014- return -1;
4015- return 0;
4016-}
4017-
4018-static int
4019-cmp (const void *a__, const void *b__)
4020-{
4021- struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
4022- struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
4023- struct tftphdr *a = (struct tftphdr *) a_->data;
4024- struct tftphdr *b = (struct tftphdr *) b_->data;
4025- /* We want the first elements to be on top. */
4026- return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block));
4027-}
4028-
4029 static grub_err_t
4030 ack (tftp_data_t data, grub_uint64_t block)
4031 {
4032@@ -207,73 +183,60 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
4033 return GRUB_ERR_NONE;
4034 }
4035
4036- err = grub_priority_queue_push (data->pq, &nb);
4037- if (err)
4038- return err;
4039-
4040- {
4041- struct grub_net_buff **nb_top_p, *nb_top;
4042- while (1)
4043- {
4044- nb_top_p = grub_priority_queue_top (data->pq);
4045- if (!nb_top_p)
4046- return GRUB_ERR_NONE;
4047- nb_top = *nb_top_p;
4048- tftph = (struct tftphdr *) nb_top->data;
4049- if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0)
4050- break;
4051- ack (data, grub_be_to_cpu16 (tftph->u.data.block));
4052- grub_netbuff_free (nb_top);
4053- grub_priority_queue_pop (data->pq);
4054- }
4055- while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
4056- {
4057- unsigned size;
4058-
4059- grub_priority_queue_pop (data->pq);
4060-
4061- if (file->device->net->packs.count < 50)
4062+ /* Ack old/retransmitted block. */
4063+ if (grub_be_to_cpu16 (tftph->u.data.block) < data->block + 1)
4064+ ack (data, grub_be_to_cpu16 (tftph->u.data.block));
4065+ /* Ignore unexpected block. */
4066+ else if (grub_be_to_cpu16 (tftph->u.data.block) > data->block + 1)
4067+ grub_dprintf ("tftp", "TFTP unexpected block # %d\n", tftph->u.data.block);
4068+ else
4069+ {
4070+ unsigned size;
4071+
4072+ if (file->device->net->packs.count < 50)
4073+ {
4074 err = ack (data, data->block + 1);
4075- else
4076- {
4077- file->device->net->stall = 1;
4078- err = 0;
4079- }
4080- if (err)
4081- return err;
4082-
4083- err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) +
4084- sizeof (tftph->u.data.block));
4085- if (err)
4086- return err;
4087- size = nb_top->tail - nb_top->data;
4088-
4089- data->block++;
4090- if (size < data->block_size)
4091- {
4092- if (data->ack_sent < data->block)
4093- ack (data, data->block);
4094- file->device->net->eof = 1;
4095- file->device->net->stall = 1;
4096- grub_net_udp_close (data->sock);
4097- data->sock = NULL;
4098- }
4099- /* Prevent garbage in broken cards. Is it still necessary
4100- given that IP implementation has been fixed?
4101- */
4102- if (size > data->block_size)
4103- {
4104- err = grub_netbuff_unput (nb_top, size - data->block_size);
4105- if (err)
4106- return err;
4107- }
4108- /* If there is data, puts packet in socket list. */
4109- if ((nb_top->tail - nb_top->data) > 0)
4110- grub_net_put_packet (&file->device->net->packs, nb_top);
4111- else
4112- grub_netbuff_free (nb_top);
4113- }
4114- }
4115+ if (err)
4116+ return err;
4117+ }
4118+ else
4119+ file->device->net->stall = 1;
4120+
4121+ err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
4122+ sizeof (tftph->u.data.block));
4123+ if (err)
4124+ return err;
4125+ size = nb->tail - nb->data;
4126+
4127+ data->block++;
4128+ if (size < data->block_size)
4129+ {
4130+ if (data->ack_sent < data->block)
4131+ ack (data, data->block);
4132+ file->device->net->eof = 1;
4133+ file->device->net->stall = 1;
4134+ grub_net_udp_close (data->sock);
4135+ data->sock = NULL;
4136+ }
4137+ /*
4138+ * Prevent garbage in broken cards. Is it still necessary
4139+ * given that IP implementation has been fixed?
4140+ */
4141+ if (size > data->block_size)
4142+ {
4143+ err = grub_netbuff_unput (nb, size - data->block_size);
4144+ if (err)
4145+ return err;
4146+ }
4147+ /* If there is data, puts packet in socket list. */
4148+ if ((nb->tail - nb->data) > 0)
4149+ {
4150+ grub_net_put_packet (&file->device->net->packs, nb);
4151+ /* Do not free nb. */
4152+ return GRUB_ERR_NONE;
4153+ }
4154+ }
4155+ grub_netbuff_free (nb);
4156 return GRUB_ERR_NONE;
4157 case TFTP_ERROR:
4158 data->have_oack = 1;
4159@@ -287,19 +250,6 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
4160 }
4161 }
4162
4163-static void
4164-destroy_pq (tftp_data_t data)
4165-{
4166- struct grub_net_buff **nb_p;
4167- while ((nb_p = grub_priority_queue_top (data->pq)))
4168- {
4169- grub_netbuff_free (*nb_p);
4170- grub_priority_queue_pop (data->pq);
4171- }
4172-
4173- grub_priority_queue_destroy (data->pq);
4174-}
4175-
4176 static grub_err_t
4177 tftp_open (struct grub_file *file, const char *filename)
4178 {
4179@@ -322,17 +322,9 @@ tftp_open (struct grub_file *file, const char *filename)
4180 file->not_easily_seekable = 1;
4181 file->data = data;
4182
4183- data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
4184- if (!data->pq)
4185- {
4186- grub_free (data);
4187- return grub_errno;
4188- }
4189-
4190 err = grub_net_resolve_address (file->device->net->server, &addr);
4191 if (err)
4192 {
4193- destroy_pq (data);
4194 grub_free (data);
4195 return err;
4196 }
4197@@ -396,7 +338,6 @@ tftp_open (struct grub_file *file, const char *filename)
4198 file);
4199 if (!data->sock)
4200 {
4201- destroy_pq (data);
4202 grub_free (data);
4203 return grub_errno;
4204 }
4205@@ -410,7 +351,6 @@ tftp_open (struct grub_file *file, const char *filename)
4206 if (err)
4207 {
4208 grub_net_udp_close (data->sock);
4209- destroy_pq (data);
4210 grub_free (data);
4211 return err;
4212 }
4213@@ -427,7 +367,6 @@ tftp_open (struct grub_file *file, const char *filename)
4214 if (grub_errno)
4215 {
4216 grub_net_udp_close (data->sock);
4217- destroy_pq (data);
4218 grub_free (data);
4219 return grub_errno;
4220 }
4221@@ -470,7 +409,6 @@ tftp_close (struct grub_file *file)
4222 grub_print_error ();
4223 grub_net_udp_close (data->sock);
4224 }
4225- destroy_pq (data);
4226 grub_free (data);
4227 return GRUB_ERR_NONE;
4228 }
4229
4230From f1e2fd65877424ee8d8d2bdd78ce28b420dee4d8 Mon Sep 17 00:00:00 2001
4231From: Alexey Makhalov <amakhalov@vmware.com>
4232Date: Wed, 15 Jul 2020 06:42:37 +0000
4233Subject: relocator: Protect grub_relocator_alloc_chunk_addr()
4234 input args against integer underflow/overflow
4235
4236Use arithmetic macros from safemath.h to accomplish it. In this commit,
4237I didn't want to be too paranoid to check every possible math equation
4238for overflow/underflow. Only obvious places (with non zero chance of
4239overflow/underflow) were refactored.
4240
4241Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
4242Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
4243---
4244 grub-core/loader/i386/linux.c | 9 +++++++--
4245 grub-core/loader/i386/pc/linux.c | 9 +++++++--
4246 grub-core/loader/i386/xen.c | 12 ++++++++++--
4247 grub-core/loader/xnu.c | 11 +++++++----
4248 4 files changed, 31 insertions(+), 10 deletions(-)
4249
4250diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
4251index 2eab9bb10..58d76fc0a 100644
4252--- a/grub-core/loader/i386/linux.c
4253+++ b/grub-core/loader/i386/linux.c
4254@@ -36,6 +36,7 @@
4255 #include <grub/lib/cmdline.h>
4256 #include <grub/linux.h>
4257 #include <grub/machine/kernel.h>
4258+#include <grub/safemath.h>
4259
4260 GRUB_MOD_LICENSE ("GPLv3+");
4261
4262@@ -549,9 +550,13 @@ grub_linux_boot (void)
4263
4264 {
4265 grub_relocator_chunk_t ch;
4266+ grub_size_t sz;
4267+
4268+ if (grub_add (ctx.real_size, efi_mmap_size, &sz))
4269+ return GRUB_ERR_OUT_OF_RANGE;
4270+
4271 err = grub_relocator_alloc_chunk_addr (relocator, &ch,
4272- ctx.real_mode_target,
4273- (ctx.real_size + efi_mmap_size));
4274+ ctx.real_mode_target, sz);
4275 if (err)
4276 return err;
4277 real_mode_mem = get_virtual_current_address (ch);
4278diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
4279index 47ea2945e..31f09922b 100644
4280--- a/grub-core/loader/i386/pc/linux.c
4281+++ b/grub-core/loader/i386/pc/linux.c
4282@@ -35,6 +35,7 @@
4283 #include <grub/i386/floppy.h>
4284 #include <grub/lib/cmdline.h>
4285 #include <grub/linux.h>
4286+#include <grub/safemath.h>
4287
4288 GRUB_MOD_LICENSE ("GPLv3+");
4289
4290@@ -218,8 +219,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
4291 setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
4292
4293 real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
4294- grub_linux16_prot_size = grub_file_size (file)
4295- - real_size - GRUB_DISK_SECTOR_SIZE;
4296+ if (grub_sub (grub_file_size (file), real_size, &grub_linux16_prot_size) ||
4297+ grub_sub (grub_linux16_prot_size, GRUB_DISK_SECTOR_SIZE, &grub_linux16_prot_size))
4298+ {
4299+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
4300+ goto fail;
4301+ }
4302
4303 if (! grub_linux_is_bzimage
4304 && GRUB_LINUX_ZIMAGE_ADDR + grub_linux16_prot_size
4305diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
4306index 8f662c8ac..cd24874ca 100644
4307--- a/grub-core/loader/i386/xen.c
4308+++ b/grub-core/loader/i386/xen.c
4309@@ -41,6 +41,7 @@
4310 #include <grub/linux.h>
4311 #include <grub/i386/memory.h>
4312 #include <grub/verify.h>
4313+#include <grub/safemath.h>
4314
4315 GRUB_MOD_LICENSE ("GPLv3+");
4316
4317@@ -636,6 +637,7 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
4318 grub_relocator_chunk_t ch;
4319 grub_addr_t kern_start;
4320 grub_addr_t kern_end;
4321+ grub_size_t sz;
4322
4323 if (argc == 0)
4324 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
4325@@ -703,8 +705,14 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
4326
4327 xen_state.max_addr = ALIGN_UP (kern_end, PAGE_SIZE);
4328
4329- err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start,
4330- kern_end - kern_start);
4331+
4332+ if (grub_sub (kern_end, kern_start, &sz))
4333+ {
4334+ err = GRUB_ERR_OUT_OF_RANGE;
4335+ goto fail;
4336+ }
4337+
4338+ err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start, sz);
4339 if (err)
4340 goto fail;
4341 kern_chunk_src = get_virtual_current_address (ch);
4342diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
4343index 77d7060e1..9ae4ceb35 100644
4344--- a/grub-core/loader/xnu.c
4345+++ b/grub-core/loader/xnu.c
4346@@ -34,6 +34,7 @@
4347 #include <grub/env.h>
4348 #include <grub/i18n.h>
4349 #include <grub/verify.h>
4350+#include <grub/safemath.h>
4351
4352 GRUB_MOD_LICENSE ("GPLv3+");
4353
4354@@ -59,15 +60,17 @@ grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target)
4355 {
4356 grub_err_t err;
4357 grub_relocator_chunk_t ch;
4358+ grub_addr_t tgt;
4359+
4360+ if (grub_add (grub_xnu_heap_target_start, grub_xnu_heap_size, &tgt))
4361+ return GRUB_ERR_OUT_OF_RANGE;
4362
4363- err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch,
4364- grub_xnu_heap_target_start
4365- + grub_xnu_heap_size, size);
4366+ err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, tgt, size);
4367 if (err)
4368 return err;
4369
4370 *src = get_virtual_current_address (ch);
4371- *target = grub_xnu_heap_target_start + grub_xnu_heap_size;
4372+ *target = tgt;
4373 grub_xnu_heap_size += size;
4374 grub_dprintf ("xnu", "val=%p\n", *src);
4375 return GRUB_ERR_NONE;
4376
4377From e39786ab462b1e4770fb35c736927286381ec47d Mon Sep 17 00:00:00 2001
4378From: Alexey Makhalov <amakhalov@vmware.com>
4379Date: Wed, 8 Jul 2020 01:44:38 +0000
4380Subject: relocator: Protect grub_relocator_alloc_chunk_align()
4381 max_addr against integer underflow
4382
4383This commit introduces integer underflow mitigation in max_addr calculation
4384in grub_relocator_alloc_chunk_align() invocation.
4385
4386It consists of 2 fixes:
4387 1. Introduced grub_relocator_alloc_chunk_align_safe() wrapper function to perform
4388 sanity check for min/max and size values, and to make safe invocation of
4389 grub_relocator_alloc_chunk_align() with validated max_addr value. Replace all
4390 invocations such as grub_relocator_alloc_chunk_align(..., min_addr, max_addr - size, size, ...)
4391 by grub_relocator_alloc_chunk_align_safe(..., min_addr, max_addr, size, ...).
4392 2. Introduced UP_TO_TOP32(s) macro for the cases where max_addr is 32-bit top
4393 address (0xffffffff - size + 1) or similar.
4394
4395Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
4396Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
4397---
4398 grub-core/lib/i386/relocator.c | 28 ++++++++++----------------
4399 grub-core/lib/mips/relocator.c | 6 ++----
4400 grub-core/lib/powerpc/relocator.c | 6 ++----
4401 grub-core/lib/x86_64/efi/relocator.c | 7 +++----
4402 grub-core/loader/i386/linux.c | 5 ++---
4403 grub-core/loader/i386/multiboot_mbi.c | 7 +++----
4404 grub-core/loader/i386/pc/linux.c | 6 ++----
4405 grub-core/loader/mips/linux.c | 9 +++------
4406 grub-core/loader/multiboot.c | 2 +-
4407 grub-core/loader/multiboot_elfxx.c | 10 ++++-----
4408 grub-core/loader/multiboot_mbi2.c | 10 ++++-----
4409 grub-core/loader/xnu_resume.c | 2 +-
4410 include/grub/relocator.h | 29 +++++++++++++++++++++++++++
4411 13 files changed, 69 insertions(+), 58 deletions(-)
4412
4413diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c
4414index 71dd4f0ab..34cbe834f 100644
4415--- a/grub-core/lib/i386/relocator.c
4416+++ b/grub-core/lib/i386/relocator.c
4417@@ -83,11 +83,10 @@ grub_relocator32_boot (struct grub_relocator *rel,
4418 /* Specific memory range due to Global Descriptor Table for use by payload
4419 that we will store in returned chunk. The address range and preference
4420 are based on "THE LINUX/x86 BOOT PROTOCOL" specification. */
4421- err = grub_relocator_alloc_chunk_align (rel, &ch, 0x1000,
4422- 0x9a000 - RELOCATOR_SIZEOF (32),
4423- RELOCATOR_SIZEOF (32), 16,
4424- GRUB_RELOCATOR_PREFERENCE_LOW,
4425- avoid_efi_bootservices);
4426+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x1000, 0x9a000,
4427+ RELOCATOR_SIZEOF (32), 16,
4428+ GRUB_RELOCATOR_PREFERENCE_LOW,
4429+ avoid_efi_bootservices);
4430 if (err)
4431 return err;
4432
4433@@ -125,13 +124,10 @@ grub_relocator16_boot (struct grub_relocator *rel,
4434 grub_relocator_chunk_t ch;
4435
4436 /* Put it higher than the byte it checks for A20 check. */
4437- err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
4438- 0xa0000 - RELOCATOR_SIZEOF (16)
4439- - GRUB_RELOCATOR16_STACK_SIZE,
4440- RELOCATOR_SIZEOF (16)
4441- + GRUB_RELOCATOR16_STACK_SIZE, 16,
4442- GRUB_RELOCATOR_PREFERENCE_NONE,
4443- 0);
4444+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x8010, 0xa0000,
4445+ RELOCATOR_SIZEOF (16) +
4446+ GRUB_RELOCATOR16_STACK_SIZE, 16,
4447+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4448 if (err)
4449 return err;
4450
4451@@ -183,11 +179,9 @@ grub_relocator64_boot (struct grub_relocator *rel,
4452 void *relst;
4453 grub_relocator_chunk_t ch;
4454
4455- err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr,
4456- max_addr - RELOCATOR_SIZEOF (64),
4457- RELOCATOR_SIZEOF (64), 16,
4458- GRUB_RELOCATOR_PREFERENCE_NONE,
4459- 0);
4460+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, min_addr, max_addr,
4461+ RELOCATOR_SIZEOF (64), 16,
4462+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4463 if (err)
4464 return err;
4465
4466diff --git a/grub-core/lib/mips/relocator.c b/grub-core/lib/mips/relocator.c
4467index 9d5f49cb9..743b213e6 100644
4468--- a/grub-core/lib/mips/relocator.c
4469+++ b/grub-core/lib/mips/relocator.c
4470@@ -120,10 +120,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
4471 unsigned i;
4472 grub_addr_t vtarget;
4473
4474- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
4475- (0xffffffff - stateset_size)
4476- + 1, stateset_size,
4477- sizeof (grub_uint32_t),
4478+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
4479+ stateset_size, sizeof (grub_uint32_t),
4480 GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4481 if (err)
4482 return err;
4483diff --git a/grub-core/lib/powerpc/relocator.c b/grub-core/lib/powerpc/relocator.c
4484index bdf2b111b..8ffb8b686 100644
4485--- a/grub-core/lib/powerpc/relocator.c
4486+++ b/grub-core/lib/powerpc/relocator.c
4487@@ -115,10 +115,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
4488 unsigned i;
4489 grub_relocator_chunk_t ch;
4490
4491- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
4492- (0xffffffff - stateset_size)
4493- + 1, stateset_size,
4494- sizeof (grub_uint32_t),
4495+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
4496+ stateset_size, sizeof (grub_uint32_t),
4497 GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4498 if (err)
4499 return err;
4500diff --git a/grub-core/lib/x86_64/efi/relocator.c b/grub-core/lib/x86_64/efi/relocator.c
4501index 3caef7a40..7d200a125 100644
4502--- a/grub-core/lib/x86_64/efi/relocator.c
4503+++ b/grub-core/lib/x86_64/efi/relocator.c
4504@@ -50,10 +50,9 @@ grub_relocator64_efi_boot (struct grub_relocator *rel,
4505 * 64-bit relocator code may live above 4 GiB quite well.
4506 * However, I do not want ask for problems. Just in case.
4507 */
4508- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
4509- 0x100000000 - RELOCATOR_SIZEOF (64_efi),
4510- RELOCATOR_SIZEOF (64_efi), 16,
4511- GRUB_RELOCATOR_PREFERENCE_NONE, 1);
4512+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0, 0x100000000,
4513+ RELOCATOR_SIZEOF (64_efi), 16,
4514+ GRUB_RELOCATOR_PREFERENCE_NONE, 1);
4515 if (err)
4516 return err;
4517
4518diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
4519index 58d76fc0a..c98fbbb37 100644
4520--- a/grub-core/loader/i386/linux.c
4521+++ b/grub-core/loader/i386/linux.c
4522@@ -183,9 +183,8 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
4523 for (; err && *align + 1 > min_align; (*align)--)
4524 {
4525 grub_errno = GRUB_ERR_NONE;
4526- err = grub_relocator_alloc_chunk_align (relocator, &ch,
4527- 0x1000000,
4528- 0xffffffff & ~prot_size,
4529+ err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
4530+ UP_TO_TOP32 (prot_size),
4531 prot_size, 1 << *align,
4532 GRUB_RELOCATOR_PREFERENCE_LOW,
4533 1);
4534diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
4535index ad3cc292f..a67d9d0a8 100644
4536--- a/grub-core/loader/i386/multiboot_mbi.c
4537+++ b/grub-core/loader/i386/multiboot_mbi.c
4538@@ -466,10 +466,9 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
4539
4540 bufsize = grub_multiboot_get_mbi_size ();
4541
4542- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
4543- 0x10000, 0xa0000 - bufsize,
4544- bufsize, 4,
4545- GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4546+ err = grub_relocator_alloc_chunk_align_safe (grub_multiboot_relocator, &ch,
4547+ 0x10000, 0xa0000, bufsize, 4,
4548+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4549 if (err)
4550 return err;
4551 ptrorig = get_virtual_current_address (ch);
4552diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
4553index 31f09922b..5fed5ffdf 100644
4554--- a/grub-core/loader/i386/pc/linux.c
4555+++ b/grub-core/loader/i386/pc/linux.c
4556@@ -453,10 +453,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
4557
4558 {
4559 grub_relocator_chunk_t ch;
4560- err = grub_relocator_alloc_chunk_align (relocator, &ch,
4561- addr_min, addr_max - size,
4562- size, 0x1000,
4563- GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
4564+ err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, addr_min, addr_max, size,
4565+ 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
4566 if (err)
4567 return err;
4568 initrd_chunk = get_virtual_current_address (ch);
4569diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c
4570index 7b723bf18..e4ed95921 100644
4571--- a/grub-core/loader/mips/linux.c
4572+++ b/grub-core/loader/mips/linux.c
4573@@ -442,12 +442,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
4574 {
4575 grub_relocator_chunk_t ch;
4576
4577- err = grub_relocator_alloc_chunk_align (relocator, &ch,
4578- (target_addr & 0x1fffffff)
4579- + linux_size + 0x10000,
4580- (0x10000000 - size),
4581- size, 0x10000,
4582- GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4583+ err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, (target_addr & 0x1fffffff) +
4584+ linux_size + 0x10000, 0x10000000, size,
4585+ 0x10000, GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4586
4587 if (err)
4588 goto fail;
4589diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
4590index 4a98d7082..facb13f3d 100644
4591--- a/grub-core/loader/multiboot.c
4592+++ b/grub-core/loader/multiboot.c
4593@@ -403,7 +403,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
4594 {
4595 grub_relocator_chunk_t ch;
4596 err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
4597- lowest_addr, (0xffffffff - size) + 1,
4598+ lowest_addr, UP_TO_TOP32 (size),
4599 size, MULTIBOOT_MOD_ALIGN,
4600 GRUB_RELOCATOR_PREFERENCE_NONE, 1);
4601 if (err)
4602diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
4603index cc6853692..f2318e0d1 100644
4604--- a/grub-core/loader/multiboot_elfxx.c
4605+++ b/grub-core/loader/multiboot_elfxx.c
4606@@ -109,10 +109,10 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
4607 if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
4608 return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
4609
4610- err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
4611- mld->min_addr, mld->max_addr - load_size,
4612- load_size, mld->align ? mld->align : 1,
4613- mld->preference, mld->avoid_efi_boot_services);
4614+ err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch,
4615+ mld->min_addr, mld->max_addr,
4616+ load_size, mld->align ? mld->align : 1,
4617+ mld->preference, mld->avoid_efi_boot_services);
4618
4619 if (err)
4620 {
4621@@ -256,7 +256,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
4622 continue;
4623
4624 err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch, 0,
4625- (0xffffffff - sh->sh_size) + 1,
4626+ UP_TO_TOP32 (sh->sh_size),
4627 sh->sh_size, sh->sh_addralign,
4628 GRUB_RELOCATOR_PREFERENCE_NONE,
4629 mld->avoid_efi_boot_services);
4630diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
4631index 0efc66062..03967839c 100644
4632--- a/grub-core/loader/multiboot_mbi2.c
4633+++ b/grub-core/loader/multiboot_mbi2.c
4634@@ -295,10 +295,10 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
4635 return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
4636 }
4637
4638- err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
4639- mld.min_addr, mld.max_addr - code_size,
4640- code_size, mld.align ? mld.align : 1,
4641- mld.preference, keep_bs);
4642+ err = grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch,
4643+ mld.min_addr, mld.max_addr,
4644+ code_size, mld.align ? mld.align : 1,
4645+ mld.preference, keep_bs);
4646 }
4647 else
4648 err = grub_relocator_alloc_chunk_addr (grub_multiboot2_relocator,
4649@@ -708,7 +708,7 @@ grub_multiboot2_make_mbi (grub_uint32_t *target)
4650 COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);
4651
4652 err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
4653- 0, 0xffffffff - bufsize,
4654+ 0, UP_TO_TOP32 (bufsize),
4655 bufsize, MULTIBOOT_TAG_ALIGN,
4656 GRUB_RELOCATOR_PREFERENCE_NONE, 1);
4657 if (err)
4658diff --git a/grub-core/loader/xnu_resume.c b/grub-core/loader/xnu_resume.c
4659index 8089804d4..d648ef0cd 100644
4660--- a/grub-core/loader/xnu_resume.c
4661+++ b/grub-core/loader/xnu_resume.c
4662@@ -129,7 +129,7 @@ grub_xnu_resume (char *imagename)
4663 {
4664 grub_relocator_chunk_t ch;
4665 err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &ch, 0,
4666- (0xffffffff - hibhead.image_size) + 1,
4667+ UP_TO_TOP32 (hibhead.image_size),
4668 hibhead.image_size,
4669 GRUB_XNU_PAGESIZE,
4670 GRUB_RELOCATOR_PREFERENCE_NONE, 0);
4671diff --git a/include/grub/relocator.h b/include/grub/relocator.h
4672index 24d8672d2..1b3bdd92a 100644
4673--- a/include/grub/relocator.h
4674+++ b/include/grub/relocator.h
4675@@ -49,6 +49,35 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
4676 int preference,
4677 int avoid_efi_boot_services);
4678
4679+/*
4680+ * Wrapper for grub_relocator_alloc_chunk_align() with purpose of
4681+ * protecting against integer underflow.
4682+ *
4683+ * Compare to its callee, max_addr has different meaning here.
4684+ * It covers entire chunk and not just start address of the chunk.
4685+ */
4686+static inline grub_err_t
4687+grub_relocator_alloc_chunk_align_safe (struct grub_relocator *rel,
4688+ grub_relocator_chunk_t *out,
4689+ grub_phys_addr_t min_addr,
4690+ grub_phys_addr_t max_addr,
4691+ grub_size_t size, grub_size_t align,
4692+ int preference,
4693+ int avoid_efi_boot_services)
4694+{
4695+ /* Sanity check and ensure following equation (max_addr - size) is safe. */
4696+ if (max_addr < size || (max_addr - size) < min_addr)
4697+ return GRUB_ERR_OUT_OF_RANGE;
4698+
4699+ return grub_relocator_alloc_chunk_align (rel, out, min_addr,
4700+ max_addr - size,
4701+ size, align, preference,
4702+ avoid_efi_boot_services);
4703+}
4704+
4705+/* Top 32-bit address minus s bytes and plus 1 byte. */
4706+#define UP_TO_TOP32(s) ((~(s) & 0xffffffff) + 1)
4707+
4708 #define GRUB_RELOCATOR_PREFERENCE_NONE 0
4709 #define GRUB_RELOCATOR_PREFERENCE_LOW 1
4710 #define GRUB_RELOCATOR_PREFERENCE_HIGH 2
4711
4712From 7855b7e78de5f257fa686ec569bda27472c4f5da Mon Sep 17 00:00:00 2001
4713From: Chris Coulson <chris.coulson@canonical.com>
4714Date: Fri, 10 Jul 2020 11:21:14 +0100
4715Subject: script: Remove unused fields from grub_script_function
4716 struct
4717
4718Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
4719Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
4720---
4721 include/grub/script_sh.h | 5 -----
4722 1 file changed, 5 deletions(-)
4723
4724diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
4725index 360c2be1f..b382bcf09 100644
4726--- a/include/grub/script_sh.h
4727+++ b/include/grub/script_sh.h
4728@@ -359,13 +359,8 @@ struct grub_script_function
4729 /* The script function. */
4730 struct grub_script *func;
4731
4732- /* The flags. */
4733- unsigned flags;
4734-
4735 /* The next element. */
4736 struct grub_script_function *next;
4737-
4738- int references;
4739 };
4740 typedef struct grub_script_function *grub_script_function_t;
4741
4742
4743From fdc80d2460e5d3b54f5cde8657f9e171b0b9a376 Mon Sep 17 00:00:00 2001
4744From: Chris Coulson <chris.coulson@canonical.com>
4745Date: Fri, 10 Jul 2020 14:41:45 +0100
4746Subject: script: Avoid a use-after-free when redefining a
4747 function during execution
4748
4749Defining a new function with the same name as a previously defined
4750function causes the grub_script and associated resources for the
4751previous function to be freed. If the previous function is currently
4752executing when a function with the same name is defined, this results
4753in use-after-frees when processing subsequent commands in the original
4754function.
4755
4756Instead, reject a new function definition if it has the same name as
4757a previously defined function, and that function is currently being
4758executed. Although a behavioural change, this should be backwards
4759compatible with existing configurations because they can't be
4760dependent on the current behaviour without being broken.
4761
4762Fixes: CVE-2020-15706
4763
4764Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
4765Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
4766---
4767 grub-core/script/execute.c | 2 ++
4768 grub-core/script/function.c | 16 +++++++++++++---
4769 grub-core/script/parser.y | 3 ++-
4770 include/grub/script_sh.h | 2 ++
4771 4 files changed, 19 insertions(+), 4 deletions(-)
4772
4773diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
4774index c8d6806fe..7e028e135 100644
4775--- a/grub-core/script/execute.c
4776+++ b/grub-core/script/execute.c
4777@@ -838,7 +838,9 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
4778 old_scope = scope;
4779 scope = &new_scope;
4780
4781+ func->executing++;
4782 ret = grub_script_execute (func->func);
4783+ func->executing--;
4784
4785 function_return = 0;
4786 active_loops = loops;
4787diff --git a/grub-core/script/function.c b/grub-core/script/function.c
4788index d36655e51..3aad04bf9 100644
4789--- a/grub-core/script/function.c
4790+++ b/grub-core/script/function.c
4791@@ -34,6 +34,7 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
4792 func = (grub_script_function_t) grub_malloc (sizeof (*func));
4793 if (! func)
4794 return 0;
4795+ func->executing = 0;
4796
4797 func->name = grub_strdup (functionname_arg->str);
4798 if (! func->name)
4799@@ -60,10 +61,19 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
4800 grub_script_function_t q;
4801
4802 q = *p;
4803- grub_script_free (q->func);
4804- q->func = cmd;
4805 grub_free (func);
4806- func = q;
4807+ if (q->executing > 0)
4808+ {
4809+ grub_error (GRUB_ERR_BAD_ARGUMENT,
4810+ N_("attempt to redefine a function being executed"));
4811+ func = NULL;
4812+ }
4813+ else
4814+ {
4815+ grub_script_free (q->func);
4816+ q->func = cmd;
4817+ func = q;
4818+ }
4819 }
4820 else
4821 {
4822diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y
4823index 4f0ab8319..f80b86b6f 100644
4824--- a/grub-core/script/parser.y
4825+++ b/grub-core/script/parser.y
4826@@ -289,7 +289,8 @@ function: "function" "name"
4827 grub_script_mem_free (state->func_mem);
4828 else {
4829 script->children = state->scripts;
4830- grub_script_function_create ($2, script);
4831+ if (!grub_script_function_create ($2, script))
4832+ grub_script_free (script);
4833 }
4834
4835 state->scripts = $<scripts>3;
4836diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
4837index b382bcf09..6c48e0751 100644
4838--- a/include/grub/script_sh.h
4839+++ b/include/grub/script_sh.h
4840@@ -361,6 +361,8 @@ struct grub_script_function
4841
4842 /* The next element. */
4843 struct grub_script_function *next;
4844+
4845+ unsigned executing;
4846 };
4847 typedef struct grub_script_function *grub_script_function_t;
4848
4849
4850From dcc097ac0531485f0785816469370bfcb1a29f60 Mon Sep 17 00:00:00 2001
4851From: Alexey Makhalov <amakhalov@vmware.com>
4852Date: Fri, 17 Jul 2020 05:17:26 +0000
4853Subject: relocator: Fix grub_relocator_alloc_chunk_align() top
4854 memory allocation
4855
4856Current implementation of grub_relocator_alloc_chunk_align()
4857does not allow allocation of the top byte.
4858
4859Assuming input args are:
4860 max_addr = 0xfffff000;
4861 size = 0x1000;
4862
4863And this is valid. But following overflow protection will
4864unnecessarily move max_addr one byte down (to 0xffffefff):
4865 if (max_addr > ~size)
4866 max_addr = ~size;
4867
4868~size + 1 will fix the situation. In addition, check size
4869for non zero to do not zero max_addr.
4870
4871Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
4872Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
4873---
4874 grub-core/lib/relocator.c | 4 ++--
4875 1 file changed, 2 insertions(+), 2 deletions(-)
4876
4877diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
4878index 5847aac36..f2c1944c2 100644
4879--- a/grub-core/lib/relocator.c
4880+++ b/grub-core/lib/relocator.c
4881@@ -1386,8 +1386,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
4882 };
4883 grub_addr_t min_addr2 = 0, max_addr2;
4884
4885- if (max_addr > ~size)
4886- max_addr = ~size;
4887+ if (size && (max_addr > ~size))
4888+ max_addr = ~size + 1;
4889
4890 #ifdef GRUB_MACHINE_PCBIOS
4891 if (min_addr < 0x1000)
4892
4893From 2db482b906c425aa755fc78e8e8980659b92f5a1 Mon Sep 17 00:00:00 2001
4894From: Peter Jones <pjones@redhat.com>
4895Date: Sun, 19 Jul 2020 14:43:31 -0400
4896Subject: hfsplus: fix two more overflows
4897
4898Both node->size and node->namelen come from the supplied filesystem,
4899which may be user-supplied. We can't trust them for the math unless we
4900know they don't overflow; making sure they go through calloc() first
4901will give us that.
4902
4903Signed-off-by: Peter Jones <pjones@redhat.com>
4904Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
4905---
4906 grub-core/fs/hfsplus.c | 11 ++++++++---
4907 1 file changed, 8 insertions(+), 3 deletions(-)
4908
4909diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
4910index dae43becc..9c4e4c88c 100644
4911--- a/grub-core/fs/hfsplus.c
4912+++ b/grub-core/fs/hfsplus.c
4913@@ -31,6 +31,7 @@
4914 #include <grub/hfs.h>
4915 #include <grub/charset.h>
4916 #include <grub/hfsplus.h>
4917+#include <grub/safemath.h>
4918
4919 GRUB_MOD_LICENSE ("GPLv3+");
4920
4921@@ -475,8 +476,12 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
4922 {
4923 char *symlink;
4924 grub_ssize_t numread;
4925+ grub_size_t sz = node->size;
4926
4927- symlink = grub_malloc (node->size + 1);
4928+ if (grub_add (sz, 1, &sz))
4929+ return NULL;
4930+
4931+ symlink = grub_malloc (sz);
4932 if (!symlink)
4933 return 0;
4934
4935@@ -715,8 +720,8 @@ list_nodes (void *record, void *hook_arg)
4936 if (type == GRUB_FSHELP_UNKNOWN)
4937 return 0;
4938
4939- filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen)
4940- * GRUB_MAX_UTF8_PER_UTF16 + 1);
4941+ filename = grub_calloc (grub_be_to_cpu16 (catkey->namelen),
4942+ GRUB_MAX_UTF8_PER_UTF16 + 1);
4943 if (! filename)
4944 return 0;
4945
4946
4947From fc669c03dbffd20667f40a2375c30ef91cdc2707 Mon Sep 17 00:00:00 2001
4948From: Peter Jones <pjones@redhat.com>
4949Date: Sun, 19 Jul 2020 15:48:20 -0400
4950Subject: lvm: fix two more potential data-dependent alloc
4951 overflows
4952
4953It appears to be possible to make a (possibly invalid) lvm PV with a
4954metadata size field that overflows our type when adding it to the
4955address we've allocated. Even if it doesn't, it may be possible to do
4956so with the math using the outcome of that as an operand. Check them
4957both.
4958
4959Signed-off-by: Peter Jones <pjones@redhat.com>
4960Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
4961---
4962 grub-core/disk/lvm.c | 47 ++++++++++++++++++++++++++++++++++++--------
4963 1 file changed, 39 insertions(+), 8 deletions(-)
4964
4965diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
4966index d1df640b3..e1299a348 100644
4967--- a/grub-core/disk/lvm.c
4968+++ b/grub-core/disk/lvm.c
4969@@ -25,6 +25,7 @@
4970 #include <grub/lvm.h>
4971 #include <grub/partition.h>
4972 #include <grub/i18n.h>
4973+#include <grub/safemath.h>
4974
4975 #ifdef GRUB_UTIL
4976 #include <grub/emu/misc.h>
4977@@ -102,10 +103,11 @@ grub_lvm_detect (grub_disk_t disk,
4978 {
4979 grub_err_t err;
4980 grub_uint64_t mda_offset, mda_size;
4981+ grub_size_t ptr;
4982 char buf[GRUB_LVM_LABEL_SIZE];
4983 char vg_id[GRUB_LVM_ID_STRLEN+1];
4984 char pv_id[GRUB_LVM_ID_STRLEN+1];
4985- char *metadatabuf, *p, *q, *vgname;
4986+ char *metadatabuf, *p, *q, *mda_end, *vgname;
4987 struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
4988 struct grub_lvm_pv_header *pvh;
4989 struct grub_lvm_disk_locn *dlocn;
4990@@ -205,19 +207,31 @@ grub_lvm_detect (grub_disk_t disk,
4991 grub_le_to_cpu64 (rlocn->size) -
4992 grub_le_to_cpu64 (mdah->size));
4993 }
4994- p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);
4995
4996- while (*q != ' ' && q < metadatabuf + mda_size)
4997- q++;
4998-
4999- if (q == metadatabuf + mda_size)
5000+ if (grub_add ((grub_size_t)metadatabuf,
5001+ (grub_size_t)grub_le_to_cpu64 (rlocn->offset),
5002+ &ptr))
5003 {
5004+error_parsing_metadata:
5005 #ifdef GRUB_UTIL
5006 grub_util_info ("error parsing metadata");
5007 #endif
5008 goto fail2;
5009 }
5010
5011+ p = q = (char *)ptr;
5012+
5013+ if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
5014+ goto error_parsing_metadata;
5015+
5016+ mda_end = (char *)ptr;
5017+
5018+ while (*q != ' ' && q < mda_end)
5019+ q++;
5020+
5021+ if (q == mda_end)
5022+ goto error_parsing_metadata;
5023+
5024 vgname_len = q - p;
5025 vgname = grub_malloc (vgname_len + 1);
5026 if (!vgname)
5027@@ -367,8 +381,25 @@ grub_lvm_detect (grub_disk_t disk,
5028 {
5029 const char *iptr;
5030 char *optr;
5031- lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len
5032- + 1 + 2 * s + 1);
5033+
5034+ /* this is kind of hard to read with our safe (but rather
5035+ * baroque) math primatives, but it boils down to:
5036+ *
5037+ * sz0 = vgname_len * 2 + 1
5038+ * + s * 2 + 1
5039+ * + sizeof ("lvm/") - 1;
5040+ */
5041+ grub_size_t sz0 = vgname_len, sz1 = s;
5042+
5043+ if (grub_mul (sz0, 2, &sz0) ||
5044+ grub_add (sz0, 1, &sz0) ||
5045+ grub_mul (sz1, 2, &sz1) ||
5046+ grub_add (sz1, 1, &sz1) ||
5047+ grub_add (sz0, sz1, &sz0) ||
5048+ grub_add (sz0, sizeof ("lvm/") - 1, &sz0))
5049+ goto lvs_fail;
5050+
5051+ lv->fullname = grub_malloc (sz0);
5052 if (!lv->fullname)
5053 goto lvs_fail;
5054
5055
5056From c0a2098a2d47a752f9416a655a7010973298f66f Mon Sep 17 00:00:00 2001
5057From: Peter Jones <pjones@redhat.com>
5058Date: Sun, 19 Jul 2020 16:08:08 -0400
5059Subject: emu: make grub_free(NULL) safe
5060
5061The grub_free() implementation in kern/mm.c safely handles NULL
5062pointers, and code at many places depends on this. We don't know that
5063the same is true on all host OSes, so we need to handle the same
5064behavior in grub-emu's implementation.
5065
5066Signed-off-by: Peter Jones <pjones@redhat.com>
5067Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
5068---
5069 grub-core/kern/emu/mm.c | 3 ++-
5070 1 file changed, 2 insertions(+), 1 deletion(-)
5071
5072diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
5073index 145b01d37..4d1046a21 100644
5074--- a/grub-core/kern/emu/mm.c
5075+++ b/grub-core/kern/emu/mm.c
5076@@ -60,7 +60,8 @@ grub_zalloc (grub_size_t size)
5077 void
5078 grub_free (void *ptr)
5079 {
5080- free (ptr);
5081+ if (ptr)
5082+ free (ptr);
5083 }
5084
5085 void *
5086
5087From 9735a4b2f52caf79e5804ca3e959f0f444a8716c Mon Sep 17 00:00:00 2001
5088From: Peter Jones <pjones@redhat.com>
5089Date: Sun, 19 Jul 2020 16:53:27 -0400
5090Subject: efi: fix some malformed device path arithmetic errors.
5091
5092Several places we take the length of a device path and subtract 4 from
5093it, without ever checking that it's >= 4. There are also cases where
5094this kind of malformation will result in unpredictable iteration,
5095including treating the length from one dp node as the type in the next
5096node. These are all errors, no matter where the data comes from.
5097
5098This patch adds a checking macro, GRUB_EFI_DEVICE_PATH_VALID(), which
5099can be used in several places, and makes GRUB_EFI_NEXT_DEVICE_PATH()
5100return NULL and GRUB_EFI_END_ENTIRE_DEVICE_PATH() evaluate as true when
5101the length is too small. Additionally, it makes several places in the
5102code check for and return errors in these cases.
5103
5104Signed-off-by: Peter Jones <pjones@redhat.com>
5105---
5106 grub-core/kern/efi/efi.c | 67 +++++++++++++++++++++++++-----
5107 grub-core/loader/efi/chainloader.c | 19 ++++++++-
5108 grub-core/loader/i386/xnu.c | 9 ++--
5109 include/grub/efi/api.h | 14 ++++---
5110 4 files changed, 88 insertions(+), 21 deletions(-)
5111
5112diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
5113index ad170c7ce..e12261fd5 100644
5114--- a/grub-core/kern/efi/efi.c
5115+++ b/grub-core/kern/efi/efi.c
5116@@ -360,7 +360,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
5117
5118 dp = dp0;
5119
5120- while (1)
5121+ while (dp)
5122 {
5123 grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
5124 grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
5125@@ -370,9 +370,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
5126 if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
5127 && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
5128 {
5129- grub_efi_uint16_t len;
5130- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
5131- / sizeof (grub_efi_char16_t));
5132+ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
5133+
5134+ if (len < 4)
5135+ {
5136+ grub_error (GRUB_ERR_OUT_OF_RANGE,
5137+ "malformed EFI Device Path node has length=%d", len);
5138+ return NULL;
5139+ }
5140+ len = (len - 4) / sizeof (grub_efi_char16_t);
5141 filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
5142 }
5143
5144@@ -388,7 +394,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
5145 if (!name)
5146 return NULL;
5147
5148- while (1)
5149+ while (dp)
5150 {
5151 grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
5152 grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
5153@@ -404,8 +410,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
5154
5155 *p++ = '/';
5156
5157- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
5158- / sizeof (grub_efi_char16_t));
5159+ len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
5160+ if (len < 4)
5161+ {
5162+ grub_error (GRUB_ERR_OUT_OF_RANGE,
5163+ "malformed EFI Device Path node has length=%d", len);
5164+ return NULL;
5165+ }
5166+
5167+ len = (len - 4) / sizeof (grub_efi_char16_t);
5168 fp = (grub_efi_file_path_device_path_t *) dp;
5169 /* According to EFI spec Path Name is NULL terminated */
5170 while (len > 0 && fp->path_name[len - 1] == 0)
5171@@ -480,7 +493,26 @@ grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
5172 ;
5173 p = GRUB_EFI_NEXT_DEVICE_PATH (p))
5174 {
5175- total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
5176+ grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p);
5177+
5178+ /*
5179+ * In the event that we find a node that's completely garbage, for
5180+ * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size
5181+ * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and
5182+ * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue,
5183+ * and neither should our consumers, but there won't be any error raised
5184+ * even though the device path is junk.
5185+ *
5186+ * This keeps us from passing junk down back to our caller.
5187+ */
5188+ if (len < 4)
5189+ {
5190+ grub_error (GRUB_ERR_OUT_OF_RANGE,
5191+ "malformed EFI Device Path node has length=%d", len);
5192+ return NULL;
5193+ }
5194+
5195+ total_size += len;
5196 if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
5197 break;
5198 }
5199@@ -525,7 +557,7 @@ dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
5200 void
5201 grub_efi_print_device_path (grub_efi_device_path_t *dp)
5202 {
5203- while (1)
5204+ while (GRUB_EFI_DEVICE_PATH_VALID (dp))
5205 {
5206 grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
5207 grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
5208@@ -937,7 +969,11 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
5209 /* Return non-zero. */
5210 return 1;
5211
5212- while (1)
5213+ if (dp1 == dp2)
5214+ return 0;
5215+
5216+ while (GRUB_EFI_DEVICE_PATH_VALID (dp1)
5217+ && GRUB_EFI_DEVICE_PATH_VALID (dp2))
5218 {
5219 grub_efi_uint8_t type1, type2;
5220 grub_efi_uint8_t subtype1, subtype2;
5221@@ -973,5 +1009,16 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
5222 dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
5223 }
5224
5225+ /*
5226+ * There's no "right" answer here, but we probably don't want to call a valid
5227+ * dp and an invalid dp equal, so pick one way or the other.
5228+ */
5229+ if (GRUB_EFI_DEVICE_PATH_VALID (dp1) &&
5230+ !GRUB_EFI_DEVICE_PATH_VALID (dp2))
5231+ return 1;
5232+ else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) &&
5233+ GRUB_EFI_DEVICE_PATH_VALID (dp2))
5234+ return -1;
5235+
5236 return 0;
5237 }
5238diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
5239index daf8c6b54..978fab002 100644
5240--- a/grub-core/loader/efi/chainloader.c
5241+++ b/grub-core/loader/efi/chainloader.c
5242@@ -116,6 +116,12 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
5243 fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
5244 fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
5245
5246+ if (!GRUB_EFI_DEVICE_PATH_VALID ((grub_efi_device_path_t *)fp))
5247+ {
5248+ grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI Device Path is invalid");
5249+ return;
5250+ }
5251+
5252 path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
5253 if (!path_name)
5254 return;
5255@@ -156,9 +162,18 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
5256
5257 size = 0;
5258 d = dp;
5259- while (1)
5260+ while (d)
5261 {
5262- size += GRUB_EFI_DEVICE_PATH_LENGTH (d);
5263+ grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (d);
5264+
5265+ if (len < 4)
5266+ {
5267+ grub_error (GRUB_ERR_OUT_OF_RANGE,
5268+ "malformed EFI Device Path node has length=%d", len);
5269+ return NULL;
5270+ }
5271+
5272+ size += len;
5273 if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d)))
5274 break;
5275 d = GRUB_EFI_NEXT_DEVICE_PATH (d);
5276diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
5277index e9e119259..a70093607 100644
5278--- a/grub-core/loader/i386/xnu.c
5279+++ b/grub-core/loader/i386/xnu.c
5280@@ -515,14 +515,15 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
5281
5282 devhead = buf;
5283 buf = devhead + 1;
5284- dpstart = buf;
5285+ dp = dpstart = buf;
5286
5287- do
5288+ while (GRUB_EFI_DEVICE_PATH_VALID (dp) && buf < bufend)
5289 {
5290- dp = buf;
5291 buf = (char *) buf + GRUB_EFI_DEVICE_PATH_LENGTH (dp);
5292+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
5293+ break;
5294+ dp = buf;
5295 }
5296- while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp) && buf < bufend);
5297
5298 dev = grub_xnu_devprop_add_device (dpstart, (char *) buf
5299 - (char *) dpstart);
5300diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
5301index 75befd10e..a3f4df91d 100644
5302--- a/include/grub/efi/api.h
5303+++ b/include/grub/efi/api.h
5304@@ -635,6 +635,7 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
5305 #define GRUB_EFI_DEVICE_PATH_TYPE(dp) ((dp)->type & 0x7f)
5306 #define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) ((dp)->subtype)
5307 #define GRUB_EFI_DEVICE_PATH_LENGTH(dp) ((dp)->length)
5308+#define GRUB_EFI_DEVICE_PATH_VALID(dp) ((dp) != NULL && GRUB_EFI_DEVICE_PATH_LENGTH (dp) >= 4)
5309
5310 /* The End of Device Path nodes. */
5311 #define GRUB_EFI_END_DEVICE_PATH_TYPE (0xff & 0x7f)
5312@@ -643,13 +644,16 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
5313 #define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE 0x01
5314
5315 #define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp) \
5316- (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
5317- && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
5318- == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE))
5319+ (!GRUB_EFI_DEVICE_PATH_VALID (dp) || \
5320+ (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
5321+ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
5322+ == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)))
5323
5324 #define GRUB_EFI_NEXT_DEVICE_PATH(dp) \
5325- ((grub_efi_device_path_t *) ((char *) (dp) \
5326- + GRUB_EFI_DEVICE_PATH_LENGTH (dp)))
5327+ (GRUB_EFI_DEVICE_PATH_VALID (dp) \
5328+ ? ((grub_efi_device_path_t *) \
5329+ ((char *) (dp) + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) \
5330+ : NULL)
5331
5332 /* Hardware Device Path. */
5333 #define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE 1
5334
5335From c5763039a630dee079f0afbd5ced9cd74efe0b71 Mon Sep 17 00:00:00 2001
5336From: Chris Coulson <chris.coulson@canonical.com>
5337Date: Wed, 22 Jul 2020 17:06:04 +0100
5338Subject: Fix a regression caused by "efi: fix some malformed
5339 device path arithmetic errors"
5340
5341This commit introduced a bogus check inside copy_file_path to
5342determine whether the destination grub_efi_file_path_device_path_t
5343was valid before anything was copied to it. Depending on the
5344contents of the heap buffer, this check could fail which would
5345result in copy_file_path returning early.
5346
5347Without any error propagated to the caller, make_file_path would
5348then try to advance the invalid device path node with
5349GRUB_EFI_NEXT_DEVICE_PATH, which would also fail, returning a NULL
5350pointer that would subsequently be dereferenced.
5351
5352Remove the bogus check, and also propagate errors from copy_file_path.
5353---
5354 grub-core/loader/efi/chainloader.c | 25 +++++++++++++------------
5355 1 file changed, 13 insertions(+), 12 deletions(-)
5356
5357diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
5358index 978fab002..e9b06242a 100644
5359--- a/grub-core/loader/efi/chainloader.c
5360+++ b/grub-core/loader/efi/chainloader.c
5361@@ -106,7 +106,7 @@ grub_chainloader_boot (void)
5362 return grub_errno;
5363 }
5364
5365-static void
5366+static grub_err_t
5367 copy_file_path (grub_efi_file_path_device_path_t *fp,
5368 const char *str, grub_efi_uint16_t len)
5369 {
5370@@ -116,15 +116,9 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
5371 fp->header.type = GRUB_EFI_MEDIA_DEVICE_PATH_TYPE;
5372 fp->header.subtype = GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE;
5373
5374- if (!GRUB_EFI_DEVICE_PATH_VALID ((grub_efi_device_path_t *)fp))
5375- {
5376- grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI Device Path is invalid");
5377- return;
5378- }
5379-
5380 path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
5381 if (!path_name)
5382- return;
5383+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate path buffer");
5384
5385 size = grub_utf8_to_utf16 (path_name, len * GRUB_MAX_UTF16_PER_UTF8,
5386 (const grub_uint8_t *) str, len, 0);
5387@@ -137,6 +131,7 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
5388 fp->path_name[size++] = '\0';
5389 fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
5390 grub_free (path_name);
5391+ return GRUB_ERR_NONE;
5392 }
5393
5394 static grub_efi_device_path_t *
5395@@ -195,13 +190,19 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
5396 d = (grub_efi_device_path_t *) ((char *) file_path
5397 + ((char *) d - (char *) dp));
5398 grub_efi_print_device_path (d);
5399- copy_file_path ((grub_efi_file_path_device_path_t *) d,
5400- dir_start, dir_end - dir_start);
5401+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
5402+ dir_start, dir_end - dir_start) != GRUB_ERR_NONE)
5403+ {
5404+ fail:
5405+ grub_free (file_path);
5406+ return 0;
5407+ }
5408
5409 /* Fill the file path for the file. */
5410 d = GRUB_EFI_NEXT_DEVICE_PATH (d);
5411- copy_file_path ((grub_efi_file_path_device_path_t *) d,
5412- dir_end + 1, grub_strlen (dir_end + 1));
5413+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
5414+ dir_end + 1, grub_strlen (dir_end + 1)) != GRUB_ERR_NONE)
5415+ goto fail;
5416
5417 /* Fill the end of device path nodes. */
5418 d = GRUB_EFI_NEXT_DEVICE_PATH (d);
5419
5420From 3e6aa687d9a2f8d172536a67d0d0f8bc7adb3108 Mon Sep 17 00:00:00 2001
5421From: Alexander Burmashev <alexander.burmashev@oracle.com>
5422Date: Wed, 22 Jul 2020 06:04:38 -0700
5423Subject: update safemath with fallback code for gcc older than
5424 5.1
5425
5426The code used in the header was taken from linux kernel commit
5427f0907827a8a9152aedac2833ed1b674a7b2a44f2. Rasmus Villemoes
5428<linux@rasmusvillemoes.dk>, the original author of the patch, was
5429contacted directly, confirmed his authorship of the code, and gave his
5430permission on treating that dual license as MIT and including into GRUB2
5431sources
5432
5433Signed-off-by: Alex Burmashev <alexander.burmashev@oracle.com>
5434---
5435 include/grub/safemath.h | 119 +++++++++++++++++++++++++++++++++++++++-
5436 1 file changed, 118 insertions(+), 1 deletion(-)
5437
5438diff --git a/include/grub/safemath.h b/include/grub/safemath.h
5439index c17b89bba..1ccac276b 100644
5440--- a/include/grub/safemath.h
5441+++ b/include/grub/safemath.h
5442@@ -31,7 +31,124 @@
5443 #define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
5444
5445 #else
5446-#error gcc 5.1 or newer or clang 3.8 or newer is required
5447+/*
5448+ * Copyright 2020 Rasmus Villemoes
5449+ *
5450+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5451+ * of this software and associated documentation files (the "Software"), to
5452+ * deal in the Software without restriction, including without limitation the
5453+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
5454+ * sell copies of the Software, and to permit persons to whom the Software is
5455+ * furnished to do so, subject to the following conditions:
5456+ *
5457+ * The above copyright notice and this permission notice shall be included in
5458+ * all copies or substantial portions of the Software.
5459+
5460+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5461+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5462+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5463+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5464+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
5465+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
5466+ * IN THE SOFTWARE.
5467+ */
5468+/*
5469+ * The code used in this header was taken from linux kernel commit
5470+ * f0907827a8a9152aedac2833ed1b674a7b2a44f2
5471+ * Rasmus Villemoes <linux@rasmusvillemoes.dk>, the original author of the
5472+ * patch, was contacted directly, confirmed his authorship of the code, and
5473+ * gave his permission on treating that dual license as MIT and including into
5474+ * GRUB2 sources
5475+ */
5476+
5477+#include <grub/types.h>
5478+#define is_signed_type(type) (((type)(-1)) < (type)1)
5479+#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
5480+#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
5481+#define type_min(T) ((T)((T)-type_max(T)-(T)1))
5482+
5483+#define __unsigned_add_overflow(a, b, d) ({ \
5484+ typeof(+(a)) __a = (a); \
5485+ typeof(+(b)) __b = (b); \
5486+ typeof(d) __d = (d); \
5487+ (void) (&__a == &__b); \
5488+ (void) (&__a == __d); \
5489+ *__d = __a + __b; \
5490+ *__d < __a; \
5491+})
5492+#define __unsigned_sub_overflow(a, b, d) ({ \
5493+ typeof(+(a)) __a = (a); \
5494+ typeof(+(b)) __b = (b); \
5495+ typeof(d) __d = (d); \
5496+ (void) (&__a == &__b); \
5497+ (void) (&__a == __d); \
5498+ *__d = __a - __b; \
5499+ __a < __b; \
5500+})
5501+#define __unsigned_mul_overflow(a, b, d) ({ \
5502+ typeof(+(a)) __a = (a); \
5503+ typeof(+(b)) __b = (b); \
5504+ typeof(d) __d = (d); \
5505+ (void) (&__a == &__b); \
5506+ (void) (&__a == __d); \
5507+ *__d = __a * __b; \
5508+ __builtin_constant_p(__b) ? \
5509+ __b > 0 && __a > type_max(typeof(__a)) / __b :\
5510+ __a > 0 && __b > type_max(typeof(__b)) / __a; \
5511+})
5512+
5513+#define __signed_add_overflow(a, b, d) ({ \
5514+ typeof(+(a)) __a = (a); \
5515+ typeof(+(b)) __b = (b); \
5516+ typeof(d) __d = (d); \
5517+ (void) (&__a == &__b); \
5518+ (void) (&__a == __d); \
5519+ *__d = (grub_uint64_t)__a + (grub_uint64_t)__b; \
5520+ (((~(__a ^ __b)) & (*__d ^ __a)) \
5521+ & type_min(typeof(__a))) != 0; \
5522+})
5523+
5524+#define __signed_sub_overflow(a, b, d) ({ \
5525+ typeof(+(a)) __a = (a); \
5526+ typeof(+(b)) __b = (b); \
5527+ typeof(d) __d = (d); \
5528+ (void) (&__a == &__b); \
5529+ (void) (&__a == __d); \
5530+ *__d = (grub_uint64_t)__a - (grub_uint64_t)__b; \
5531+ ((((__a ^ __b)) & (*__d ^ __a)) \
5532+ & type_min(typeof(__a))) != 0; \
5533+})
5534+
5535+#define __signed_mul_overflow(a, b, d) ({ \
5536+ typeof(+(a)) __a = (a); \
5537+ typeof(+(b)) __b = (b); \
5538+ typeof(d) __d = (d); \
5539+ typeof(+(a)) __tmax = type_max(typeof(+(a))); \
5540+ typeof(+(a)) __tmin = type_min(typeof(+(a))); \
5541+ (void) (&__a == &__b); \
5542+ (void) (&__a == __d); \
5543+ *__d = (grub_uint64_t)__a * (grub_uint64_t)__b; \
5544+ (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) ||\
5545+ (__b < (typeof(__b))-1 && \
5546+ (__a > __tmin/__b || __a < __tmax/__b)) || \
5547+ (__b == (typeof(__b))-1 && __a == __tmin); \
5548+})
5549+
5550+#define grub_add(a, b, d) \
5551+ __builtin_choose_expr(is_signed_type(typeof(+(a))), \
5552+ __signed_add_overflow(a, b, d), \
5553+ __unsigned_add_overflow(a, b, d))
5554+
5555+#define grub_sub(a, b, d) \
5556+ __builtin_choose_expr(is_signed_type(typeof(+(a))), \
5557+ __signed_sub_overflow(a, b, d), \
5558+ __unsigned_sub_overflow(a, b, d))
5559+
5560+#define grub_mul(a, b, d) \
5561+ __builtin_choose_expr(is_signed_type(typeof(+(a))), \
5562+ __signed_mul_overflow(a, b, d), \
5563+ __unsigned_mul_overflow(a, b, d))
5564+
5565 #endif
5566
5567 #endif /* GRUB_SAFEMATH_H */
5568
5569From bb5fc65035e82509b0565bfe2994fbe6cc11016e Mon Sep 17 00:00:00 2001
5570From: Alexey Makhalov <amakhalov@vmware.com>
5571Date: Mon, 20 Jul 2020 23:03:05 +0000
5572Subject: efi: Fix use-after-free in halt/reboot path
5573
5574commit 92bfc33db984 ("efi: Free malloc regions on exit")
5575introduced memory freeing in grub_efi_fini(), which is
5576used not only by exit path but by halt/reboot one as well.
5577As result of memory freeing, code and data regions used by
5578modules, such as halt, reboot, acpi (used by halt) also got
5579freed. After return to module code, CPU executes, filled
5580by UEFI firmware (tested with edk2), 0xAFAFAFAF pattern as
5581a code. Which leads to #UD exception later.
5582
5583grub> halt
5584!!!! X64 Exception Type - 06(#UD - Invalid Opcode) CPU Apic ID - 00000000 !!!!
5585RIP - 0000000003F4EC28, CS - 0000000000000038, RFLAGS - 0000000000200246
5586RAX - 0000000000000000, RCX - 00000000061DA188, RDX - 0A74C0854DC35D41
5587RBX - 0000000003E10E08, RSP - 0000000007F0F860, RBP - 0000000000000000
5588RSI - 00000000064DB768, RDI - 000000000832C5C3
5589R8 - 0000000000000002, R9 - 0000000000000000, R10 - 00000000061E2E52
5590R11 - 0000000000000020, R12 - 0000000003EE5C1F, R13 - 00000000061E0FF4
5591R14 - 0000000003E10D80, R15 - 00000000061E2F60
5592DS - 0000000000000030, ES - 0000000000000030, FS - 0000000000000030
5593GS - 0000000000000030, SS - 0000000000000030
5594CR0 - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
5595CR4 - 0000000000000668, CR8 - 0000000000000000
5596DR0 - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
5597DR3 - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
5598GDTR - 00000000079EEA98 0000000000000047, LDTR - 0000000000000000
5599IDTR - 0000000007598018 0000000000000FFF, TR - 0000000000000000
5600FXSAVE_STATE - 0000000007F0F4C0
5601
5602Proposal here is to continue to free allocated memory for
5603exit boot services path but keep it for halt/reboot path
5604as it won't be much security concern here.
5605Introduced GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY
5606loader flag to be used by efi halt/reboot path.
5607
5608Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
5609Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
5610---
5611 grub-core/kern/arm/efi/init.c | 3 +++
5612 grub-core/kern/arm64/efi/init.c | 3 +++
5613 grub-core/kern/efi/efi.c | 3 ++-
5614 grub-core/kern/efi/init.c | 1 -
5615 grub-core/kern/i386/efi/init.c | 9 +++++++--
5616 grub-core/kern/ia64/efi/init.c | 9 +++++++--
5617 grub-core/kern/riscv/efi/init.c | 3 +++
5618 grub-core/lib/efi/halt.c | 3 ++-
5619 include/grub/loader.h | 1 +
5620 9 files changed, 28 insertions(+), 7 deletions(-)
5621
5622diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
5623index 06df60e2f..40c3b467f 100644
5624--- a/grub-core/kern/arm/efi/init.c
5625+++ b/grub-core/kern/arm/efi/init.c
5626@@ -71,4 +71,7 @@ grub_machine_fini (int flags)
5627 efi_call_1 (b->close_event, tmr_evt);
5628
5629 grub_efi_fini ();
5630+
5631+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
5632+ grub_efi_memory_fini ();
5633 }
5634diff --git a/grub-core/kern/arm64/efi/init.c b/grub-core/kern/arm64/efi/init.c
5635index 6224999ec..5010caefd 100644
5636--- a/grub-core/kern/arm64/efi/init.c
5637+++ b/grub-core/kern/arm64/efi/init.c
5638@@ -57,4 +57,7 @@ grub_machine_fini (int flags)
5639 return;
5640
5641 grub_efi_fini ();
5642+
5643+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
5644+ grub_efi_memory_fini ();
5645 }
5646diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
5647index e12261fd5..acb38d61f 100644
5648--- a/grub-core/kern/efi/efi.c
5649+++ b/grub-core/kern/efi/efi.c
5650@@ -157,7 +157,8 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
5651 void
5652 grub_reboot (void)
5653 {
5654- grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
5655+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
5656+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
5657 efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
5658 GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
5659 for (;;) ;
5660diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
5661index 3dfdf2d22..2c31847bf 100644
5662--- a/grub-core/kern/efi/init.c
5663+++ b/grub-core/kern/efi/init.c
5664@@ -80,5 +80,4 @@ grub_efi_fini (void)
5665 {
5666 grub_efidisk_fini ();
5667 grub_console_fini ();
5668- grub_efi_memory_fini ();
5669 }
5670diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c
5671index da499aba0..deb2eacd8 100644
5672--- a/grub-core/kern/i386/efi/init.c
5673+++ b/grub-core/kern/i386/efi/init.c
5674@@ -39,6 +39,11 @@ grub_machine_init (void)
5675 void
5676 grub_machine_fini (int flags)
5677 {
5678- if (flags & GRUB_LOADER_FLAG_NORETURN)
5679- grub_efi_fini ();
5680+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
5681+ return;
5682+
5683+ grub_efi_fini ();
5684+
5685+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
5686+ grub_efi_memory_fini ();
5687 }
5688diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c
5689index b5ecbd091..f1965571b 100644
5690--- a/grub-core/kern/ia64/efi/init.c
5691+++ b/grub-core/kern/ia64/efi/init.c
5692@@ -70,6 +70,11 @@ grub_machine_init (void)
5693 void
5694 grub_machine_fini (int flags)
5695 {
5696- if (flags & GRUB_LOADER_FLAG_NORETURN)
5697- grub_efi_fini ();
5698+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
5699+ return;
5700+
5701+ grub_efi_fini ();
5702+
5703+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
5704+ grub_efi_memory_fini ();
5705 }
5706diff --git a/grub-core/kern/riscv/efi/init.c b/grub-core/kern/riscv/efi/init.c
5707index 7eb1969d0..38795fe67 100644
5708--- a/grub-core/kern/riscv/efi/init.c
5709+++ b/grub-core/kern/riscv/efi/init.c
5710@@ -73,4 +73,7 @@ grub_machine_fini (int flags)
5711 return;
5712
5713 grub_efi_fini ();
5714+
5715+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
5716+ grub_efi_memory_fini ();
5717 }
5718diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c
5719index 5859f0498..29d413641 100644
5720--- a/grub-core/lib/efi/halt.c
5721+++ b/grub-core/lib/efi/halt.c
5722@@ -28,7 +28,8 @@
5723 void
5724 grub_halt (void)
5725 {
5726- grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
5727+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
5728+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
5729 #if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \
5730 !defined(__riscv)
5731 grub_acpi_halt ();
5732diff --git a/include/grub/loader.h b/include/grub/loader.h
5733index 7f82a499f..b20864282 100644
5734--- a/include/grub/loader.h
5735+++ b/include/grub/loader.h
5736@@ -33,6 +33,7 @@ enum
5737 {
5738 GRUB_LOADER_FLAG_NORETURN = 1,
5739 GRUB_LOADER_FLAG_PXE_NOT_UNLOAD = 2,
5740+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY = 4,
5741 };
5742
5743 void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
5744
5745From 6d438b80c4cfe75a67f619918706630ccc2252b6 Mon Sep 17 00:00:00 2001
5746From: Peter Jones <pjones@redhat.com>
5747Date: Fri, 24 Jul 2020 13:57:27 -0400
5748Subject: linux loader: avoid overflow on initrd size calculation
5749
5750Signed-off-by: Peter Jones <pjones@redhat.com>
5751---
5752 grub-core/loader/linux.c | 4 ++--
5753 1 file changed, 2 insertions(+), 2 deletions(-)
5754
5755diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
5756index 471b214d6..25624ebc1 100644
5757--- a/grub-core/loader/linux.c
5758+++ b/grub-core/loader/linux.c
5759@@ -151,8 +151,8 @@ grub_initrd_init (int argc, char *argv[],
5760 initrd_ctx->nfiles = 0;
5761 initrd_ctx->components = 0;
5762
5763- initrd_ctx->components = grub_zalloc (argc
5764- * sizeof (initrd_ctx->components[0]));
5765+ initrd_ctx->components = grub_calloc (argc,
5766+ sizeof (initrd_ctx->components[0]));
5767 if (!initrd_ctx->components)
5768 return grub_errno;
5769
5770
5771From 81fae35a346bef8f7b27ba8d186a18ae21281755 Mon Sep 17 00:00:00 2001
5772From: Colin Watson <cjwatson@debian.org>
5773Date: Sat, 25 Jul 2020 12:15:37 +0100
5774Subject: linux: Fix integer overflows in initrd size handling
5775
5776These could be triggered by a crafted filesystem with very large files.
5777
5778Fixes: CVE-2020-15707
5779
5780Signed-off-by: Colin Watson <cjwatson@debian.org>
5781Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
5782---
5783 grub-core/loader/linux.c | 74 +++++++++++++++++++++++++++++-----------
5784 1 file changed, 54 insertions(+), 20 deletions(-)
5785
5786diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
5787index 25624ebc1..e9f819ee9 100644
5788--- a/grub-core/loader/linux.c
5789+++ b/grub-core/loader/linux.c
5790@@ -4,6 +4,7 @@
5791 #include <grub/misc.h>
5792 #include <grub/file.h>
5793 #include <grub/mm.h>
5794+#include <grub/safemath.h>
5795
5796 struct newc_head
5797 {
5798@@ -98,13 +99,13 @@ free_dir (struct dir *root)
5799 grub_free (root);
5800 }
5801
5802-static grub_size_t
5803+static grub_err_t
5804 insert_dir (const char *name, struct dir **root,
5805- grub_uint8_t *ptr)
5806+ grub_uint8_t *ptr, grub_size_t *size)
5807 {
5808 struct dir *cur, **head = root;
5809 const char *cb, *ce = name;
5810- grub_size_t size = 0;
5811+ *size = 0;
5812 while (1)
5813 {
5814 for (cb = ce; *cb == '/'; cb++);
5815@@ -130,14 +131,22 @@ insert_dir (const char *name, struct dir **root,
5816 ptr = make_header (ptr, name, ce - name,
5817 040777, 0);
5818 }
5819- size += ALIGN_UP ((ce - (char *) name)
5820- + sizeof (struct newc_head), 4);
5821+ if (grub_add (*size,
5822+ ALIGN_UP ((ce - (char *) name)
5823+ + sizeof (struct newc_head), 4),
5824+ size))
5825+ {
5826+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
5827+ grub_free (n->name);
5828+ grub_free (n);
5829+ return grub_errno;
5830+ }
5831 *head = n;
5832 cur = n;
5833 }
5834 root = &cur->next;
5835 }
5836- return size;
5837+ return GRUB_ERR_NONE;
5838 }
5839
5840 grub_err_t
5841@@ -173,26 +182,33 @@ grub_initrd_init (int argc, char *argv[],
5842 eptr = grub_strchr (ptr, ':');
5843 if (eptr)
5844 {
5845+ grub_size_t dir_size, name_len;
5846+
5847 initrd_ctx->components[i].newc_name = grub_strndup (ptr, eptr - ptr);
5848- if (!initrd_ctx->components[i].newc_name)
5849+ if (!initrd_ctx->components[i].newc_name ||
5850+ insert_dir (initrd_ctx->components[i].newc_name, &root, 0,
5851+ &dir_size))
5852 {
5853 grub_initrd_close (initrd_ctx);
5854 return grub_errno;
5855 }
5856- initrd_ctx->size
5857- += ALIGN_UP (sizeof (struct newc_head)
5858- + grub_strlen (initrd_ctx->components[i].newc_name),
5859- 4);
5860- initrd_ctx->size += insert_dir (initrd_ctx->components[i].newc_name,
5861- &root, 0);
5862+ name_len = grub_strlen (initrd_ctx->components[i].newc_name);
5863+ if (grub_add (initrd_ctx->size,
5864+ ALIGN_UP (sizeof (struct newc_head) + name_len, 4),
5865+ &initrd_ctx->size) ||
5866+ grub_add (initrd_ctx->size, dir_size, &initrd_ctx->size))
5867+ goto overflow;
5868 newc = 1;
5869 fname = eptr + 1;
5870 }
5871 }
5872 else if (newc)
5873 {
5874- initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
5875- + sizeof ("TRAILER!!!") - 1, 4);
5876+ if (grub_add (initrd_ctx->size,
5877+ ALIGN_UP (sizeof (struct newc_head)
5878+ + sizeof ("TRAILER!!!") - 1, 4),
5879+ &initrd_ctx->size))
5880+ goto overflow;
5881 free_dir (root);
5882 root = 0;
5883 newc = 0;
5884@@ -208,19 +224,29 @@ grub_initrd_init (int argc, char *argv[],
5885 initrd_ctx->nfiles++;
5886 initrd_ctx->components[i].size
5887 = grub_file_size (initrd_ctx->components[i].file);
5888- initrd_ctx->size += initrd_ctx->components[i].size;
5889+ if (grub_add (initrd_ctx->size, initrd_ctx->components[i].size,
5890+ &initrd_ctx->size))
5891+ goto overflow;
5892 }
5893
5894 if (newc)
5895 {
5896 initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
5897- initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
5898- + sizeof ("TRAILER!!!") - 1, 4);
5899+ if (grub_add (initrd_ctx->size,
5900+ ALIGN_UP (sizeof (struct newc_head)
5901+ + sizeof ("TRAILER!!!") - 1, 4),
5902+ &initrd_ctx->size))
5903+ goto overflow;
5904 free_dir (root);
5905 root = 0;
5906 }
5907
5908 return GRUB_ERR_NONE;
5909+
5910+overflow:
5911+ free_dir (root);
5912+ grub_initrd_close (initrd_ctx);
5913+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
5914 }
5915
5916 grub_size_t
5917@@ -261,8 +287,16 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
5918
5919 if (initrd_ctx->components[i].newc_name)
5920 {
5921- ptr += insert_dir (initrd_ctx->components[i].newc_name,
5922- &root, ptr);
5923+ grub_size_t dir_size;
5924+
5925+ if (insert_dir (initrd_ctx->components[i].newc_name, &root, ptr,
5926+ &dir_size))
5927+ {
5928+ free_dir (root);
5929+ grub_initrd_close (initrd_ctx);
5930+ return grub_errno;
5931+ }
5932+ ptr += dir_size;
5933 ptr = make_header (ptr, initrd_ctx->components[i].newc_name,
5934 grub_strlen (initrd_ctx->components[i].newc_name),
5935 0100777,
5936