boot/grub2: Backport Boothole securify fixes
Details: https://lists.gnu.org/archive/html/grub-devel/2020-07/msg00034.html Fixes the following security issues: * CVE-2020-10713 A flaw was found in grub2, prior to version 2.06. An attacker may use the GRUB 2 flaw to hijack and tamper the GRUB verification process. This flaw also allows the bypass of Secure Boot protections. In order to load an untrusted or modified kernel, an attacker would first need to establish access to the system such as gaining physical access, obtain the ability to alter a pxe-boot network, or have remote access to a networked system with root access. With this access, an attacker could then craft a string to cause a buffer overflow by injecting a malicious payload that leads to arbitrary code execution within GRUB. The highest threat from this vulnerability is to data confidentiality and integrity as well as system availability. * CVE-2020-14308 In grub2 versions before 2.06 the grub memory allocator doesn't check for possible arithmetic overflows on the requested allocation size. This leads the function to return invalid memory allocations which can be further used to cause possible integrity, confidentiality and availability impacts during the boot process. * CVE-2020-14309 There's an issue with grub2 in all versions before 2.06 when handling squashfs filesystems containing a symbolic link with name length of UINT32 bytes in size. The name size leads to an arithmetic overflow leading to a zero-size allocation further causing a heap-based buffer overflow with attacker controlled data. * CVE-2020-14310 An integer overflow in read_section_from_string may lead to a heap based buffer overflow. * CVE-2020-14311 An integer overflow in grub_ext2_read_link may lead to a heap-based buffer overflow. * CVE-2020-15706 GRUB2 contains a race condition in grub_script_function_create() leading to a use-after-free vulnerability which can be triggered by redefining a function whilst the same function is already executing, leading to arbitrary code execution and secure boot restriction bypass * CVE-2020-15707 Integer overflows were discovered in the functions grub_cmd_initrd and grub_initrd_init in the efilinux component of GRUB2, as shipped in Debian, Red Hat, and Ubuntu (the functionality is not included in GRUB2 upstream), leading to a heap-based buffer overflow. These could be triggered by an extremely large number of arguments to the initrd command on 32-bit architectures, or a crafted filesystem with very large files on any architecture. An attacker could use this to execute arbitrary code and bypass UEFI Secure Boot restrictions. This issue affects GRUB2 version 2.04 and prior versions. Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
This commit is contained in:
parent
ac841cc7ac
commit
2f7a8021b5
@ -0,0 +1,73 @@
|
||||
From a7ab0cc98fa89a3d5098c29cbe44bcd24b0a6454 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Wed, 15 Apr 2020 15:45:02 -0400
|
||||
Subject: [PATCH] yylex: Make lexer fatal errors actually be fatal
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When presented with a command that can't be tokenized to anything
|
||||
smaller than YYLMAX characters, the parser calls YY_FATAL_ERROR(errmsg),
|
||||
expecting that will stop further processing, as such:
|
||||
|
||||
#define YY_DO_BEFORE_ACTION \
|
||||
yyg->yytext_ptr = yy_bp; \
|
||||
yyleng = (int) (yy_cp - yy_bp); \
|
||||
yyg->yy_hold_char = *yy_cp; \
|
||||
*yy_cp = '\0'; \
|
||||
if ( yyleng >= YYLMAX ) \
|
||||
YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \
|
||||
yy_flex_strncpy( yytext, yyg->yytext_ptr, yyleng + 1 , yyscanner); \
|
||||
yyg->yy_c_buf_p = yy_cp;
|
||||
|
||||
The code flex generates expects that YY_FATAL_ERROR() will either return
|
||||
for it or do some form of longjmp(), or handle the error in some way at
|
||||
least, and so the strncpy() call isn't in an "else" clause, and thus if
|
||||
YY_FATAL_ERROR() is *not* actually fatal, it does the call with the
|
||||
questionable limit, and predictable results ensue.
|
||||
|
||||
Unfortunately, our implementation of YY_FATAL_ERROR() is:
|
||||
|
||||
#define YY_FATAL_ERROR(msg) \
|
||||
do { \
|
||||
grub_printf (_("fatal error: %s\n"), _(msg)); \
|
||||
} while (0)
|
||||
|
||||
The same pattern exists in yyless(), and similar problems exist in users
|
||||
of YY_INPUT(), several places in the main parsing loop,
|
||||
yy_get_next_buffer(), yy_load_buffer_state(), yyensure_buffer_stack,
|
||||
yy_scan_buffer(), etc.
|
||||
|
||||
All of these callers expect YY_FATAL_ERROR() to actually be fatal, and
|
||||
the things they do if it returns after calling it are wildly unsafe.
|
||||
|
||||
Fixes: CVE-2020-10713
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/script/yylex.l | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l
|
||||
index 7b44c37b7..b7203c823 100644
|
||||
--- a/grub-core/script/yylex.l
|
||||
+++ b/grub-core/script/yylex.l
|
||||
@@ -37,11 +37,11 @@
|
||||
|
||||
/*
|
||||
* As we don't have access to yyscanner, we cannot do much except to
|
||||
- * print the fatal error.
|
||||
+ * print the fatal error and exit.
|
||||
*/
|
||||
#define YY_FATAL_ERROR(msg) \
|
||||
do { \
|
||||
- grub_printf (_("fatal error: %s\n"), _(msg)); \
|
||||
+ grub_fatal (_("fatal error: %s\n"), _(msg));\
|
||||
} while (0)
|
||||
|
||||
#define COPY(str, hint) \
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,128 @@
|
||||
From 782a4580a5e347793443aa8e9152db1bf4a0fff8 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Mon, 15 Jun 2020 10:58:42 -0400
|
||||
Subject: [PATCH] safemath: Add some arithmetic primitives that check for
|
||||
overflow
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This adds a new header, include/grub/safemath.h, that includes easy to
|
||||
use wrappers for __builtin_{add,sub,mul}_overflow() declared like:
|
||||
|
||||
bool OP(a, b, res)
|
||||
|
||||
where OP is grub_add, grub_sub or grub_mul. OP() returns true in the
|
||||
case where the operation would overflow and res is not modified.
|
||||
Otherwise, false is returned and the operation is executed.
|
||||
|
||||
These arithmetic primitives require newer compiler versions. So, bump
|
||||
these requirements in the INSTALL file too.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
INSTALL | 22 ++--------------------
|
||||
include/grub/compiler.h | 8 ++++++++
|
||||
include/grub/safemath.h | 37 +++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 47 insertions(+), 20 deletions(-)
|
||||
create mode 100644 include/grub/safemath.h
|
||||
|
||||
diff --git a/INSTALL b/INSTALL
|
||||
index 8acb40902..dcb9b7d7b 100644
|
||||
--- a/INSTALL
|
||||
+++ b/INSTALL
|
||||
@@ -11,27 +11,9 @@ GRUB depends on some software packages installed into your system. If
|
||||
you don't have any of them, please obtain and install them before
|
||||
configuring the GRUB.
|
||||
|
||||
-* GCC 4.1.3 or later
|
||||
- Note: older versions may work but support is limited
|
||||
-
|
||||
- Experimental support for clang 3.3 or later (results in much bigger binaries)
|
||||
+* GCC 5.1.0 or later
|
||||
+ Experimental support for clang 3.8.0 or later (results in much bigger binaries)
|
||||
for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64
|
||||
- Note: clang 3.2 or later works for i386 and x86_64 targets but results in
|
||||
- much bigger binaries.
|
||||
- earlier versions not tested
|
||||
- Note: clang 3.2 or later works for arm
|
||||
- earlier versions not tested
|
||||
- Note: clang on arm64 is not supported due to
|
||||
- https://llvm.org/bugs/show_bug.cgi?id=26030
|
||||
- Note: clang 3.3 or later works for mips(el)
|
||||
- earlier versions fail to generate .reginfo and hence gprel relocations
|
||||
- fail.
|
||||
- Note: clang 3.2 or later works for powerpc
|
||||
- earlier versions not tested
|
||||
- Note: clang 3.5 or later works for sparc64
|
||||
- earlier versions return "error: unable to interface with target machine"
|
||||
- Note: clang has no support for ia64 and hence you can't compile GRUB
|
||||
- for ia64 with clang
|
||||
* GNU Make
|
||||
* GNU Bison 2.3 or later
|
||||
* GNU gettext 0.17 or later
|
||||
diff --git a/include/grub/compiler.h b/include/grub/compiler.h
|
||||
index c9e1d7a73..8f3be3ae7 100644
|
||||
--- a/include/grub/compiler.h
|
||||
+++ b/include/grub/compiler.h
|
||||
@@ -48,4 +48,12 @@
|
||||
# define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
+#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
|
||||
+# define CLANG_PREREQ(maj,min) \
|
||||
+ ((__clang_major__ > (maj)) || \
|
||||
+ (__clang_major__ == (maj) && __clang_minor__ >= (min)))
|
||||
+#else
|
||||
+# define CLANG_PREREQ(maj,min) 0
|
||||
+#endif
|
||||
+
|
||||
#endif /* ! GRUB_COMPILER_HEADER */
|
||||
diff --git a/include/grub/safemath.h b/include/grub/safemath.h
|
||||
new file mode 100644
|
||||
index 000000000..c17b89bba
|
||||
--- /dev/null
|
||||
+++ b/include/grub/safemath.h
|
||||
@@ -0,0 +1,37 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
+ *
|
||||
+ * GRUB is free software: you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation, either version 3 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * GRUB is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
+ *
|
||||
+ * Arithmetic operations that protect against overflow.
|
||||
+ */
|
||||
+
|
||||
+#ifndef GRUB_SAFEMATH_H
|
||||
+#define GRUB_SAFEMATH_H 1
|
||||
+
|
||||
+#include <grub/compiler.h>
|
||||
+
|
||||
+/* These appear in gcc 5.1 and clang 3.8. */
|
||||
+#if GNUC_PREREQ(5, 1) || CLANG_PREREQ(3, 8)
|
||||
+
|
||||
+#define grub_add(a, b, res) __builtin_add_overflow(a, b, res)
|
||||
+#define grub_sub(a, b, res) __builtin_sub_overflow(a, b, res)
|
||||
+#define grub_mul(a, b, res) __builtin_mul_overflow(a, b, res)
|
||||
+
|
||||
+#else
|
||||
+#error gcc 5.1 or newer or clang 3.8 or newer is required
|
||||
+#endif
|
||||
+
|
||||
+#endif /* GRUB_SAFEMATH_H */
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,246 @@
|
||||
From 5775eb40862b67468ced816e6d7560dbe22a3670 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Mon, 15 Jun 2020 12:15:29 -0400
|
||||
Subject: [PATCH] calloc: Make sure we always have an overflow-checking
|
||||
calloc() available
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This tries to make sure that everywhere in this source tree, we always have
|
||||
an appropriate version of calloc() (i.e. grub_calloc(), xcalloc(), etc.)
|
||||
available, and that they all safely check for overflow and return NULL when
|
||||
it would occur.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/kern/emu/misc.c | 12 +++++++++
|
||||
grub-core/kern/emu/mm.c | 10 ++++++++
|
||||
grub-core/kern/mm.c | 40 ++++++++++++++++++++++++++++++
|
||||
grub-core/lib/libgcrypt_wrap/mem.c | 11 ++++++--
|
||||
grub-core/lib/posix_wrap/stdlib.h | 8 +++++-
|
||||
include/grub/emu/misc.h | 1 +
|
||||
include/grub/mm.h | 6 +++++
|
||||
7 files changed, 85 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
|
||||
index 65db79baa..dfd8a8ec4 100644
|
||||
--- a/grub-core/kern/emu/misc.c
|
||||
+++ b/grub-core/kern/emu/misc.c
|
||||
@@ -85,6 +85,18 @@ grub_util_error (const char *fmt, ...)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
+void *
|
||||
+xcalloc (grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *p;
|
||||
+
|
||||
+ p = calloc (nmemb, size);
|
||||
+ if (!p)
|
||||
+ grub_util_error ("%s", _("out of memory"));
|
||||
+
|
||||
+ return p;
|
||||
+}
|
||||
+
|
||||
void *
|
||||
xmalloc (grub_size_t size)
|
||||
{
|
||||
diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
|
||||
index f262e95e3..145b01d37 100644
|
||||
--- a/grub-core/kern/emu/mm.c
|
||||
+++ b/grub-core/kern/emu/mm.c
|
||||
@@ -25,6 +25,16 @@
|
||||
#include <string.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
+void *
|
||||
+grub_calloc (grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *ret;
|
||||
+ ret = calloc (nmemb, size);
|
||||
+ if (!ret)
|
||||
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void *
|
||||
grub_malloc (grub_size_t size)
|
||||
{
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index ee88ff611..f2822a836 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -67,8 +67,10 @@
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/mm_private.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
#ifdef MM_DEBUG
|
||||
+# undef grub_calloc
|
||||
# undef grub_malloc
|
||||
# undef grub_zalloc
|
||||
# undef grub_realloc
|
||||
@@ -375,6 +377,30 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
|
||||
+ * integer overflow.
|
||||
+ */
|
||||
+void *
|
||||
+grub_calloc (grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *ret;
|
||||
+ grub_size_t sz = 0;
|
||||
+
|
||||
+ if (grub_mul (nmemb, size, &sz))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ ret = grub_memalign (0, sz);
|
||||
+ if (!ret)
|
||||
+ return NULL;
|
||||
+
|
||||
+ grub_memset (ret, 0, sz);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/* Allocate SIZE bytes and return the pointer. */
|
||||
void *
|
||||
grub_malloc (grub_size_t size)
|
||||
@@ -561,6 +587,20 @@ grub_mm_dump (unsigned lineno)
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
||||
+void *
|
||||
+grub_debug_calloc (const char *file, int line, grub_size_t nmemb, grub_size_t size)
|
||||
+{
|
||||
+ void *ptr;
|
||||
+
|
||||
+ if (grub_mm_debug)
|
||||
+ grub_printf ("%s:%d: calloc (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ",
|
||||
+ file, line, size);
|
||||
+ ptr = grub_calloc (nmemb, size);
|
||||
+ if (grub_mm_debug)
|
||||
+ grub_printf ("%p\n", ptr);
|
||||
+ return ptr;
|
||||
+}
|
||||
+
|
||||
void *
|
||||
grub_debug_malloc (const char *file, int line, grub_size_t size)
|
||||
{
|
||||
diff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c
|
||||
index beeb661a3..74c6eafe5 100644
|
||||
--- a/grub-core/lib/libgcrypt_wrap/mem.c
|
||||
+++ b/grub-core/lib/libgcrypt_wrap/mem.c
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/env.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -36,7 +37,10 @@ void *
|
||||
gcry_xcalloc (size_t n, size_t m)
|
||||
{
|
||||
void *ret;
|
||||
- ret = grub_zalloc (n * m);
|
||||
+ size_t sz;
|
||||
+ if (grub_mul (n, m, &sz))
|
||||
+ grub_fatal ("gcry_xcalloc would overflow");
|
||||
+ ret = grub_zalloc (sz);
|
||||
if (!ret)
|
||||
grub_fatal ("gcry_xcalloc failed");
|
||||
return ret;
|
||||
@@ -56,7 +60,10 @@ void *
|
||||
gcry_xcalloc_secure (size_t n, size_t m)
|
||||
{
|
||||
void *ret;
|
||||
- ret = grub_zalloc (n * m);
|
||||
+ size_t sz;
|
||||
+ if (grub_mul (n, m, &sz))
|
||||
+ grub_fatal ("gcry_xcalloc would overflow");
|
||||
+ ret = grub_zalloc (sz);
|
||||
if (!ret)
|
||||
grub_fatal ("gcry_xcalloc failed");
|
||||
return ret;
|
||||
diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h
|
||||
index 3b46f47ff..7a8d385e9 100644
|
||||
--- a/grub-core/lib/posix_wrap/stdlib.h
|
||||
+++ b/grub-core/lib/posix_wrap/stdlib.h
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
static inline void
|
||||
free (void *ptr)
|
||||
@@ -37,7 +38,12 @@ malloc (grub_size_t size)
|
||||
static inline void *
|
||||
calloc (grub_size_t size, grub_size_t nelem)
|
||||
{
|
||||
- return grub_zalloc (size * nelem);
|
||||
+ grub_size_t sz;
|
||||
+
|
||||
+ if (grub_mul (size, nelem, &sz))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return grub_zalloc (sz);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
|
||||
index ce464cfd0..ff9c48a64 100644
|
||||
--- a/include/grub/emu/misc.h
|
||||
+++ b/include/grub/emu/misc.h
|
||||
@@ -47,6 +47,7 @@ grub_util_device_is_mapped (const char *dev);
|
||||
#define GRUB_HOST_PRIuLONG_LONG "llu"
|
||||
#define GRUB_HOST_PRIxLONG_LONG "llx"
|
||||
|
||||
+void * EXPORT_FUNC(xcalloc) (grub_size_t nmemb, grub_size_t size) WARN_UNUSED_RESULT;
|
||||
void * EXPORT_FUNC(xmalloc) (grub_size_t size) WARN_UNUSED_RESULT;
|
||||
void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) WARN_UNUSED_RESULT;
|
||||
char * EXPORT_FUNC(xstrdup) (const char *str) WARN_UNUSED_RESULT;
|
||||
diff --git a/include/grub/mm.h b/include/grub/mm.h
|
||||
index 28e2e53eb..9c38dd3ca 100644
|
||||
--- a/include/grub/mm.h
|
||||
+++ b/include/grub/mm.h
|
||||
@@ -29,6 +29,7 @@
|
||||
#endif
|
||||
|
||||
void grub_mm_init_region (void *addr, grub_size_t size);
|
||||
+void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
|
||||
void EXPORT_FUNC(grub_free) (void *ptr);
|
||||
@@ -48,6 +49,9 @@ extern int EXPORT_VAR(grub_mm_debug);
|
||||
void grub_mm_dump_free (void);
|
||||
void grub_mm_dump (unsigned lineno);
|
||||
|
||||
+#define grub_calloc(nmemb, size) \
|
||||
+ grub_debug_calloc (GRUB_FILE, __LINE__, nmemb, size)
|
||||
+
|
||||
#define grub_malloc(size) \
|
||||
grub_debug_malloc (GRUB_FILE, __LINE__, size)
|
||||
|
||||
@@ -63,6 +67,8 @@ void grub_mm_dump (unsigned lineno);
|
||||
#define grub_free(ptr) \
|
||||
grub_debug_free (GRUB_FILE, __LINE__, ptr)
|
||||
|
||||
+void *EXPORT_FUNC(grub_debug_calloc) (const char *file, int line,
|
||||
+ grub_size_t nmemb, grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
|
||||
grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_debug_zalloc) (const char *file, int line,
|
||||
--
|
||||
2.26.2
|
||||
|
1840
boot/grub2/0005-calloc-Use-calloc-at-most-places.patch
Normal file
1840
boot/grub2/0005-calloc-Use-calloc-at-most-places.patch
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,72 @@
|
||||
From e0dd17a3ce79c6622dc78c96e1f2ef1b20e2bf7b Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sat, 4 Jul 2020 12:25:09 -0400
|
||||
Subject: [PATCH] iso9660: Don't leak memory on realloc() failures
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/fs/iso9660.c | 24 ++++++++++++++++++++----
|
||||
1 file changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
|
||||
index 7ba5b300b..5ec4433b8 100644
|
||||
--- a/grub-core/fs/iso9660.c
|
||||
+++ b/grub-core/fs/iso9660.c
|
||||
@@ -533,14 +533,20 @@ add_part (struct iterate_dir_ctx *ctx,
|
||||
{
|
||||
int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0;
|
||||
grub_size_t sz;
|
||||
+ char *new;
|
||||
|
||||
if (grub_add (size, len2, &sz) ||
|
||||
grub_add (sz, 1, &sz))
|
||||
return;
|
||||
|
||||
- ctx->symlink = grub_realloc (ctx->symlink, sz);
|
||||
- if (! ctx->symlink)
|
||||
- return;
|
||||
+ new = grub_realloc (ctx->symlink, sz);
|
||||
+ if (!new)
|
||||
+ {
|
||||
+ grub_free (ctx->symlink);
|
||||
+ ctx->symlink = NULL;
|
||||
+ return;
|
||||
+ }
|
||||
+ ctx->symlink = new;
|
||||
|
||||
grub_memcpy (ctx->symlink + size, part, len2);
|
||||
ctx->symlink[size + len2] = 0;
|
||||
@@ -634,7 +640,12 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
||||
is the length. Both are part of the `Component
|
||||
Record'. */
|
||||
if (ctx->symlink && !ctx->was_continue)
|
||||
- add_part (ctx, "/", 1);
|
||||
+ {
|
||||
+ add_part (ctx, "/", 1);
|
||||
+ if (grub_errno)
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+
|
||||
add_part (ctx, (char *) &entry->data[pos + 2],
|
||||
entry->data[pos + 1]);
|
||||
ctx->was_continue = (entry->data[pos] & 1);
|
||||
@@ -653,6 +664,11 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry,
|
||||
add_part (ctx, "/", 1);
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ /* Check if grub_realloc() failed in add_part(). */
|
||||
+ if (grub_errno)
|
||||
+ return grub_errno;
|
||||
+
|
||||
/* In pos + 1 the length of the `Component Record' is
|
||||
stored. */
|
||||
pos += entry->data[pos + 1] + 2;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 73bc7a964c9496d5b0f00dbd69959dacf5adcebe Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Date: Tue, 7 Jul 2020 15:36:26 +0200
|
||||
Subject: [PATCH] font: Do not load more than one NAME section
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The GRUB font file can have one NAME section only. Though if somebody
|
||||
crafts a broken font file with many NAME sections and loads it then the
|
||||
GRUB leaks memory. So, prevent against that by loading first NAME
|
||||
section and failing in controlled way on following one.
|
||||
|
||||
Reported-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/font/font.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
|
||||
index 5edb477ac..d09bb38d8 100644
|
||||
--- a/grub-core/font/font.c
|
||||
+++ b/grub-core/font/font.c
|
||||
@@ -532,6 +532,12 @@ grub_font_load (const char *filename)
|
||||
if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME,
|
||||
sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
|
||||
{
|
||||
+ if (font->name != NULL)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FONT, "invalid font file: too many NAME sections");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
font->name = read_section_as_string (§ion);
|
||||
if (!font->name)
|
||||
goto fail;
|
||||
--
|
||||
2.26.2
|
||||
|
39
boot/grub2/0009-gfxmenu-Fix-double-free-in-load_image.patch
Normal file
39
boot/grub2/0009-gfxmenu-Fix-double-free-in-load_image.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 9ff609f0e7798bc5fb04f791131c98e7693bdd9b Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 8 Jul 2020 20:41:56 +0000
|
||||
Subject: [PATCH] gfxmenu: Fix double free in load_image()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
self->bitmap should be zeroed after free. Otherwise, there is a chance
|
||||
to double free (USE_AFTER_FREE) it later in rescale_image().
|
||||
|
||||
Fixes: CID 292472
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/gfxmenu/gui_image.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c
|
||||
index 29784ed2d..6b2e976f1 100644
|
||||
--- a/grub-core/gfxmenu/gui_image.c
|
||||
+++ b/grub-core/gfxmenu/gui_image.c
|
||||
@@ -195,7 +195,10 @@ load_image (grub_gui_image_t self, const char *path)
|
||||
return grub_errno;
|
||||
|
||||
if (self->bitmap && (self->bitmap != self->raw_bitmap))
|
||||
- grub_video_bitmap_destroy (self->bitmap);
|
||||
+ {
|
||||
+ grub_video_bitmap_destroy (self->bitmap);
|
||||
+ self->bitmap = 0;
|
||||
+ }
|
||||
if (self->raw_bitmap)
|
||||
grub_video_bitmap_destroy (self->raw_bitmap);
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,58 @@
|
||||
From dc9777dc17697b196c415c53187a55861d41fd2a Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 8 Jul 2020 21:30:43 +0000
|
||||
Subject: [PATCH] xnu: Fix double free in grub_xnu_devprop_add_property()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
grub_xnu_devprop_add_property() should not free utf8 and utf16 as it get
|
||||
allocated and freed in the caller.
|
||||
|
||||
Minor improvement: do prop fields initialization after memory allocations.
|
||||
|
||||
Fixes: CID 292442, CID 292457, CID 292460, CID 292466
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/loader/i386/xnu.c | 17 ++++++++---------
|
||||
1 file changed, 8 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
|
||||
index b7d176b5d..e9e119259 100644
|
||||
--- a/grub-core/loader/i386/xnu.c
|
||||
+++ b/grub-core/loader/i386/xnu.c
|
||||
@@ -262,20 +262,19 @@ grub_xnu_devprop_add_property (struct grub_xnu_devprop_device_descriptor *dev,
|
||||
if (!prop)
|
||||
return grub_errno;
|
||||
|
||||
- prop->name = utf8;
|
||||
- prop->name16 = utf16;
|
||||
- prop->name16len = utf16len;
|
||||
-
|
||||
- prop->length = datalen;
|
||||
- prop->data = grub_malloc (prop->length);
|
||||
+ prop->data = grub_malloc (datalen);
|
||||
if (!prop->data)
|
||||
{
|
||||
- grub_free (prop->name);
|
||||
- grub_free (prop->name16);
|
||||
grub_free (prop);
|
||||
return grub_errno;
|
||||
}
|
||||
- grub_memcpy (prop->data, data, prop->length);
|
||||
+ grub_memcpy (prop->data, data, datalen);
|
||||
+
|
||||
+ prop->name = utf8;
|
||||
+ prop->name16 = utf16;
|
||||
+ prop->name16len = utf16len;
|
||||
+ prop->length = datalen;
|
||||
+
|
||||
grub_list_push (GRUB_AS_LIST_P (&dev->properties),
|
||||
GRUB_AS_LIST (prop));
|
||||
return GRUB_ERR_NONE;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 78829f0c230680e386fff9f420bb1631bc20f761 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Thu, 9 Jul 2020 03:05:23 +0000
|
||||
Subject: [PATCH] lzma: Make sure we don't dereference past array
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The two dimensional array p->posSlotEncoder[4][64] is being dereferenced
|
||||
using the GetLenToPosState() macro which checks if len is less than 5,
|
||||
and if so subtracts 2 from it. If len = 0, that is 0 - 2 = 4294967294.
|
||||
Obviously we don't want to dereference that far out so we check if the
|
||||
position found is greater or equal kNumLenToPosStates (4) and bail out.
|
||||
|
||||
N.B.: Upstream LZMA 18.05 and later has this function completely rewritten
|
||||
without any history.
|
||||
|
||||
Fixes: CID 51526
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/lib/LzmaEnc.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c
|
||||
index f2ec04a8c..753e56a95 100644
|
||||
--- a/grub-core/lib/LzmaEnc.c
|
||||
+++ b/grub-core/lib/LzmaEnc.c
|
||||
@@ -1877,13 +1877,19 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize
|
||||
}
|
||||
else
|
||||
{
|
||||
- UInt32 posSlot;
|
||||
+ UInt32 posSlot, lenToPosState;
|
||||
RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
|
||||
p->state = kMatchNextStates[p->state];
|
||||
LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
|
||||
pos -= LZMA_NUM_REPS;
|
||||
GetPosSlot(pos, posSlot);
|
||||
- RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
|
||||
+ lenToPosState = GetLenToPosState(len);
|
||||
+ if (lenToPosState >= kNumLenToPosStates)
|
||||
+ {
|
||||
+ p->result = SZ_ERROR_DATA;
|
||||
+ return CheckErrors(p);
|
||||
+ }
|
||||
+ RcTree_Encode(&p->rc, p->posSlotEncoder[lenToPosState], kNumPosSlotBits, posSlot);
|
||||
|
||||
if (posSlot >= kStartPosModelIndex)
|
||||
{
|
||||
--
|
||||
2.26.2
|
||||
|
69
boot/grub2/0012-term-Fix-overflow-on-user-inputs.patch
Normal file
69
boot/grub2/0012-term-Fix-overflow-on-user-inputs.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From 8d3b6f9da468f666e3a7976657f2ab5c52762a21 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Tue, 7 Jul 2020 15:12:25 -0400
|
||||
Subject: [PATCH] term: Fix overflow on user inputs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This requires a very weird input from the serial interface but can cause
|
||||
an overflow in input_buf (keys) overwriting the next variable (npending)
|
||||
with the user choice:
|
||||
|
||||
(pahole output)
|
||||
|
||||
struct grub_terminfo_input_state {
|
||||
int input_buf[6]; /* 0 24 */
|
||||
int npending; /* 24 4 */ <- CORRUPT
|
||||
...snip...
|
||||
|
||||
The magic string requires causing this is "ESC,O,],0,1,2,q" and we overflow
|
||||
npending with "q" (aka increase npending to 161). The simplest fix is to
|
||||
just to disallow overwrites input_buf, which exactly what this patch does.
|
||||
|
||||
Fixes: CID 292449
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/term/terminfo.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c
|
||||
index d317efa36..5fa94c0c3 100644
|
||||
--- a/grub-core/term/terminfo.c
|
||||
+++ b/grub-core/term/terminfo.c
|
||||
@@ -398,7 +398,7 @@ grub_terminfo_getwh (struct grub_term_output *term)
|
||||
}
|
||||
|
||||
static void
|
||||
-grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
|
||||
+grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, int max_len,
|
||||
int (*readkey) (struct grub_term_input *term))
|
||||
{
|
||||
int c;
|
||||
@@ -414,6 +414,9 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len,
|
||||
if (c == -1) \
|
||||
return; \
|
||||
\
|
||||
+ if (*len >= max_len) \
|
||||
+ return; \
|
||||
+ \
|
||||
keys[*len] = c; \
|
||||
(*len)++; \
|
||||
}
|
||||
@@ -602,8 +605,8 @@ grub_terminfo_getkey (struct grub_term_input *termi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- grub_terminfo_readkey (termi, data->input_buf,
|
||||
- &data->npending, data->readkey);
|
||||
+ grub_terminfo_readkey (termi, data->input_buf, &data->npending,
|
||||
+ GRUB_TERMINFO_READKEY_MAX_LEN, data->readkey);
|
||||
|
||||
#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)
|
||||
if (data->npending == 1 && data->input_buf[0] == GRUB_TERM_ESC
|
||||
--
|
||||
2.26.2
|
||||
|
59
boot/grub2/0013-udf-Fix-memory-leak.patch
Normal file
59
boot/grub2/0013-udf-Fix-memory-leak.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 748b691761d31bfff7e9d0d210caa606294c2b52 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Tue, 7 Jul 2020 22:02:31 -0400
|
||||
Subject: [PATCH] udf: Fix memory leak
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fixes: CID 73796
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/fs/udf.c | 17 +++++++++++++----
|
||||
1 file changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
|
||||
index 21ac7f446..2ac5c1d00 100644
|
||||
--- a/grub-core/fs/udf.c
|
||||
+++ b/grub-core/fs/udf.c
|
||||
@@ -965,8 +965,10 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||
return 0;
|
||||
|
||||
if (grub_udf_read_icb (dir->data, &dirent.icb, child))
|
||||
- return 0;
|
||||
-
|
||||
+ {
|
||||
+ grub_free (child);
|
||||
+ return 0;
|
||||
+ }
|
||||
if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT)
|
||||
{
|
||||
/* This is the parent directory. */
|
||||
@@ -988,11 +990,18 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
||||
dirent.file_ident_length,
|
||||
(char *) raw))
|
||||
!= dirent.file_ident_length)
|
||||
- return 0;
|
||||
+ {
|
||||
+ grub_free (child);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
filename = read_string (raw, dirent.file_ident_length, 0);
|
||||
if (!filename)
|
||||
- grub_print_error ();
|
||||
+ {
|
||||
+ /* As the hook won't get called. */
|
||||
+ grub_free (child);
|
||||
+ grub_print_error ();
|
||||
+ }
|
||||
|
||||
if (filename && hook (filename, type, child, hook_data))
|
||||
{
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 49bf3faa106498e151306fc780c63194a14751e3 Mon Sep 17 00:00:00 2001
|
||||
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Date: Fri, 26 Jun 2020 10:51:43 -0400
|
||||
Subject: [PATCH] multiboot2: Fix memory leak if
|
||||
grub_create_loader_cmdline() fails
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fixes: CID 292468
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/loader/multiboot_mbi2.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
|
||||
index 53da78615..0efc66062 100644
|
||||
--- a/grub-core/loader/multiboot_mbi2.c
|
||||
+++ b/grub-core/loader/multiboot_mbi2.c
|
||||
@@ -1070,7 +1070,11 @@ grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
|
||||
err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
|
||||
newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ {
|
||||
+ grub_free (newmod->cmdline);
|
||||
+ grub_free (newmod);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
if (modules_last)
|
||||
modules_last->next = newmod;
|
||||
--
|
||||
2.26.2
|
||||
|
283
boot/grub2/0015-tftp-Do-not-use-priority-queue.patch
Normal file
283
boot/grub2/0015-tftp-Do-not-use-priority-queue.patch
Normal file
@ -0,0 +1,283 @@
|
||||
From b6c4a1b204740fe52b32e7f530831a59f4038e20 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Thu, 9 Jul 2020 08:10:40 +0000
|
||||
Subject: [PATCH] tftp: Do not use priority queue
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
There is not need to reassemble the order of blocks. Per RFC 1350,
|
||||
server must wait for the ACK, before sending next block. Data packets
|
||||
can be served immediately without putting them to priority queue.
|
||||
|
||||
Logic to handle incoming packet is this:
|
||||
- if packet block id equal to expected block id, then
|
||||
process the packet,
|
||||
- if packet block id is less than expected - this is retransmit
|
||||
of old packet, then ACK it and drop the packet,
|
||||
- if packet block id is more than expected - that shouldn't
|
||||
happen, just drop the packet.
|
||||
|
||||
It makes the tftp receive path code simpler, smaller and faster.
|
||||
As a benefit, this change fixes CID# 73624 and CID# 96690, caused
|
||||
by following while loop:
|
||||
|
||||
while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
|
||||
|
||||
where tftph pointer is not moving from one iteration to another, causing
|
||||
to serve same packet again. Luckily, double serving didn't happen due to
|
||||
data->block++ during the first iteration.
|
||||
|
||||
Fixes: CID 73624, CID 96690
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/net/tftp.c | 168 ++++++++++++++-----------------------------
|
||||
1 file changed, 53 insertions(+), 115 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
||||
index 7d90bf66e..b4297bc8d 100644
|
||||
--- a/grub-core/net/tftp.c
|
||||
+++ b/grub-core/net/tftp.c
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/file.h>
|
||||
-#include <grub/priority_queue.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
@@ -106,31 +105,8 @@ typedef struct tftp_data
|
||||
int have_oack;
|
||||
struct grub_error_saved save_err;
|
||||
grub_net_udp_socket_t sock;
|
||||
- grub_priority_queue_t pq;
|
||||
} *tftp_data_t;
|
||||
|
||||
-static int
|
||||
-cmp_block (grub_uint16_t a, grub_uint16_t b)
|
||||
-{
|
||||
- grub_int16_t i = (grub_int16_t) (a - b);
|
||||
- if (i > 0)
|
||||
- return +1;
|
||||
- if (i < 0)
|
||||
- return -1;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-cmp (const void *a__, const void *b__)
|
||||
-{
|
||||
- struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
|
||||
- struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
|
||||
- struct tftphdr *a = (struct tftphdr *) a_->data;
|
||||
- struct tftphdr *b = (struct tftphdr *) b_->data;
|
||||
- /* We want the first elements to be on top. */
|
||||
- return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block));
|
||||
-}
|
||||
-
|
||||
static grub_err_t
|
||||
ack (tftp_data_t data, grub_uint64_t block)
|
||||
{
|
||||
@@ -207,73 +183,60 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
- err = grub_priority_queue_push (data->pq, &nb);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- {
|
||||
- struct grub_net_buff **nb_top_p, *nb_top;
|
||||
- while (1)
|
||||
- {
|
||||
- nb_top_p = grub_priority_queue_top (data->pq);
|
||||
- if (!nb_top_p)
|
||||
- return GRUB_ERR_NONE;
|
||||
- nb_top = *nb_top_p;
|
||||
- tftph = (struct tftphdr *) nb_top->data;
|
||||
- if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0)
|
||||
- break;
|
||||
- ack (data, grub_be_to_cpu16 (tftph->u.data.block));
|
||||
- grub_netbuff_free (nb_top);
|
||||
- grub_priority_queue_pop (data->pq);
|
||||
- }
|
||||
- while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0)
|
||||
- {
|
||||
- unsigned size;
|
||||
-
|
||||
- grub_priority_queue_pop (data->pq);
|
||||
-
|
||||
- if (file->device->net->packs.count < 50)
|
||||
+ /* Ack old/retransmitted block. */
|
||||
+ if (grub_be_to_cpu16 (tftph->u.data.block) < data->block + 1)
|
||||
+ ack (data, grub_be_to_cpu16 (tftph->u.data.block));
|
||||
+ /* Ignore unexpected block. */
|
||||
+ else if (grub_be_to_cpu16 (tftph->u.data.block) > data->block + 1)
|
||||
+ grub_dprintf ("tftp", "TFTP unexpected block # %d\n", tftph->u.data.block);
|
||||
+ else
|
||||
+ {
|
||||
+ unsigned size;
|
||||
+
|
||||
+ if (file->device->net->packs.count < 50)
|
||||
+ {
|
||||
err = ack (data, data->block + 1);
|
||||
- else
|
||||
- {
|
||||
- file->device->net->stall = 1;
|
||||
- err = 0;
|
||||
- }
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) +
|
||||
- sizeof (tftph->u.data.block));
|
||||
- if (err)
|
||||
- return err;
|
||||
- size = nb_top->tail - nb_top->data;
|
||||
-
|
||||
- data->block++;
|
||||
- if (size < data->block_size)
|
||||
- {
|
||||
- if (data->ack_sent < data->block)
|
||||
- ack (data, data->block);
|
||||
- file->device->net->eof = 1;
|
||||
- file->device->net->stall = 1;
|
||||
- grub_net_udp_close (data->sock);
|
||||
- data->sock = NULL;
|
||||
- }
|
||||
- /* Prevent garbage in broken cards. Is it still necessary
|
||||
- given that IP implementation has been fixed?
|
||||
- */
|
||||
- if (size > data->block_size)
|
||||
- {
|
||||
- err = grub_netbuff_unput (nb_top, size - data->block_size);
|
||||
- if (err)
|
||||
- return err;
|
||||
- }
|
||||
- /* If there is data, puts packet in socket list. */
|
||||
- if ((nb_top->tail - nb_top->data) > 0)
|
||||
- grub_net_put_packet (&file->device->net->packs, nb_top);
|
||||
- else
|
||||
- grub_netbuff_free (nb_top);
|
||||
- }
|
||||
- }
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+ else
|
||||
+ file->device->net->stall = 1;
|
||||
+
|
||||
+ err = grub_netbuff_pull (nb, sizeof (tftph->opcode) +
|
||||
+ sizeof (tftph->u.data.block));
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ size = nb->tail - nb->data;
|
||||
+
|
||||
+ data->block++;
|
||||
+ if (size < data->block_size)
|
||||
+ {
|
||||
+ if (data->ack_sent < data->block)
|
||||
+ ack (data, data->block);
|
||||
+ file->device->net->eof = 1;
|
||||
+ file->device->net->stall = 1;
|
||||
+ grub_net_udp_close (data->sock);
|
||||
+ data->sock = NULL;
|
||||
+ }
|
||||
+ /*
|
||||
+ * Prevent garbage in broken cards. Is it still necessary
|
||||
+ * given that IP implementation has been fixed?
|
||||
+ */
|
||||
+ if (size > data->block_size)
|
||||
+ {
|
||||
+ err = grub_netbuff_unput (nb, size - data->block_size);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+ /* If there is data, puts packet in socket list. */
|
||||
+ if ((nb->tail - nb->data) > 0)
|
||||
+ {
|
||||
+ grub_net_put_packet (&file->device->net->packs, nb);
|
||||
+ /* Do not free nb. */
|
||||
+ return GRUB_ERR_NONE;
|
||||
+ }
|
||||
+ }
|
||||
+ grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
case TFTP_ERROR:
|
||||
data->have_oack = 1;
|
||||
@@ -287,19 +250,6 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||
}
|
||||
}
|
||||
|
||||
-static void
|
||||
-destroy_pq (tftp_data_t data)
|
||||
-{
|
||||
- struct grub_net_buff **nb_p;
|
||||
- while ((nb_p = grub_priority_queue_top (data->pq)))
|
||||
- {
|
||||
- grub_netbuff_free (*nb_p);
|
||||
- grub_priority_queue_pop (data->pq);
|
||||
- }
|
||||
-
|
||||
- grub_priority_queue_destroy (data->pq);
|
||||
-}
|
||||
-
|
||||
static grub_err_t
|
||||
tftp_open (struct grub_file *file, const char *filename)
|
||||
{
|
||||
@@ -372,17 +322,9 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
file->not_easily_seekable = 1;
|
||||
file->data = data;
|
||||
|
||||
- data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
|
||||
- if (!data->pq)
|
||||
- {
|
||||
- grub_free (data);
|
||||
- return grub_errno;
|
||||
- }
|
||||
-
|
||||
err = grub_net_resolve_address (file->device->net->server, &addr);
|
||||
if (err)
|
||||
{
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
@@ -392,7 +334,6 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
file);
|
||||
if (!data->sock)
|
||||
{
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
@@ -406,7 +347,6 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
if (err)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
@@ -423,7 +363,6 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
if (grub_errno)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
@@ -466,7 +405,6 @@ tftp_close (struct grub_file *file)
|
||||
grub_print_error ();
|
||||
grub_net_udp_close (data->sock);
|
||||
}
|
||||
- destroy_pq (data);
|
||||
grub_free (data);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,153 @@
|
||||
From 1c7b619c84f229c1602c1958bcd054b6d9937562 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 15 Jul 2020 06:42:37 +0000
|
||||
Subject: [PATCH] relocator: Protect grub_relocator_alloc_chunk_addr()
|
||||
input args against integer underflow/overflow
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Use arithmetic macros from safemath.h to accomplish it. In this commit,
|
||||
I didn't want to be too paranoid to check every possible math equation
|
||||
for overflow/underflow. Only obvious places (with non zero chance of
|
||||
overflow/underflow) were refactored.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/loader/i386/linux.c | 9 +++++++--
|
||||
grub-core/loader/i386/pc/linux.c | 9 +++++++--
|
||||
grub-core/loader/i386/xen.c | 12 ++++++++++--
|
||||
grub-core/loader/xnu.c | 11 +++++++----
|
||||
4 files changed, 31 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
|
||||
index d0501e229..02a73463a 100644
|
||||
--- a/grub-core/loader/i386/linux.c
|
||||
+++ b/grub-core/loader/i386/linux.c
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/linux.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -547,9 +548,13 @@ grub_linux_boot (void)
|
||||
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
+ grub_size_t sz;
|
||||
+
|
||||
+ if (grub_add (ctx.real_size, efi_mmap_size, &sz))
|
||||
+ return GRUB_ERR_OUT_OF_RANGE;
|
||||
+
|
||||
err = grub_relocator_alloc_chunk_addr (relocator, &ch,
|
||||
- ctx.real_mode_target,
|
||||
- (ctx.real_size + efi_mmap_size));
|
||||
+ ctx.real_mode_target, sz);
|
||||
if (err)
|
||||
return err;
|
||||
real_mode_mem = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
|
||||
index 47ea2945e..31f09922b 100644
|
||||
--- a/grub-core/loader/i386/pc/linux.c
|
||||
+++ b/grub-core/loader/i386/pc/linux.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <grub/i386/floppy.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/linux.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -218,8 +219,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
||||
setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
|
||||
|
||||
real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
|
||||
- grub_linux16_prot_size = grub_file_size (file)
|
||||
- - real_size - GRUB_DISK_SECTOR_SIZE;
|
||||
+ if (grub_sub (grub_file_size (file), real_size, &grub_linux16_prot_size) ||
|
||||
+ grub_sub (grub_linux16_prot_size, GRUB_DISK_SECTOR_SIZE, &grub_linux16_prot_size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
if (! grub_linux_is_bzimage
|
||||
&& GRUB_LINUX_ZIMAGE_ADDR + grub_linux16_prot_size
|
||||
diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
|
||||
index 8f662c8ac..cd24874ca 100644
|
||||
--- a/grub-core/loader/i386/xen.c
|
||||
+++ b/grub-core/loader/i386/xen.c
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <grub/linux.h>
|
||||
#include <grub/i386/memory.h>
|
||||
#include <grub/verify.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -636,6 +637,7 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_relocator_chunk_t ch;
|
||||
grub_addr_t kern_start;
|
||||
grub_addr_t kern_end;
|
||||
+ grub_size_t sz;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
@@ -703,8 +705,14 @@ grub_cmd_xen (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
xen_state.max_addr = ALIGN_UP (kern_end, PAGE_SIZE);
|
||||
|
||||
- err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start,
|
||||
- kern_end - kern_start);
|
||||
+
|
||||
+ if (grub_sub (kern_end, kern_start, &sz))
|
||||
+ {
|
||||
+ err = GRUB_ERR_OUT_OF_RANGE;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch, kern_start, sz);
|
||||
if (err)
|
||||
goto fail;
|
||||
kern_chunk_src = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
|
||||
index 77d7060e1..9ae4ceb35 100644
|
||||
--- a/grub-core/loader/xnu.c
|
||||
+++ b/grub-core/loader/xnu.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <grub/env.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/verify.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -59,15 +60,17 @@ grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_relocator_chunk_t ch;
|
||||
+ grub_addr_t tgt;
|
||||
+
|
||||
+ if (grub_add (grub_xnu_heap_target_start, grub_xnu_heap_size, &tgt))
|
||||
+ return GRUB_ERR_OUT_OF_RANGE;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch,
|
||||
- grub_xnu_heap_target_start
|
||||
- + grub_xnu_heap_size, size);
|
||||
+ err = grub_relocator_alloc_chunk_addr (grub_xnu_relocator, &ch, tgt, size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*src = get_virtual_current_address (ch);
|
||||
- *target = grub_xnu_heap_target_start + grub_xnu_heap_size;
|
||||
+ *target = tgt;
|
||||
grub_xnu_heap_size += size;
|
||||
grub_dprintf ("xnu", "val=%p\n", *src);
|
||||
return GRUB_ERR_NONE;
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,341 @@
|
||||
From 0cfbbca3ccd84d36ffb1bcd6644ada7c73b19fc0 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Wed, 8 Jul 2020 01:44:38 +0000
|
||||
Subject: [PATCH] relocator: Protect grub_relocator_alloc_chunk_align()
|
||||
max_addr against integer underflow
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This commit introduces integer underflow mitigation in max_addr calculation
|
||||
in grub_relocator_alloc_chunk_align() invocation.
|
||||
|
||||
It consists of 2 fixes:
|
||||
1. Introduced grub_relocator_alloc_chunk_align_safe() wrapper function to perform
|
||||
sanity check for min/max and size values, and to make safe invocation of
|
||||
grub_relocator_alloc_chunk_align() with validated max_addr value. Replace all
|
||||
invocations such as grub_relocator_alloc_chunk_align(..., min_addr, max_addr - size, size, ...)
|
||||
by grub_relocator_alloc_chunk_align_safe(..., min_addr, max_addr, size, ...).
|
||||
2. Introduced UP_TO_TOP32(s) macro for the cases where max_addr is 32-bit top
|
||||
address (0xffffffff - size + 1) or similar.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/lib/i386/relocator.c | 28 ++++++++++----------------
|
||||
grub-core/lib/mips/relocator.c | 6 ++----
|
||||
grub-core/lib/powerpc/relocator.c | 6 ++----
|
||||
grub-core/lib/x86_64/efi/relocator.c | 7 +++----
|
||||
grub-core/loader/i386/linux.c | 5 ++---
|
||||
grub-core/loader/i386/multiboot_mbi.c | 7 +++----
|
||||
grub-core/loader/i386/pc/linux.c | 6 ++----
|
||||
grub-core/loader/mips/linux.c | 9 +++------
|
||||
grub-core/loader/multiboot.c | 2 +-
|
||||
grub-core/loader/multiboot_elfxx.c | 10 ++++-----
|
||||
grub-core/loader/multiboot_mbi2.c | 10 ++++-----
|
||||
grub-core/loader/xnu_resume.c | 2 +-
|
||||
include/grub/relocator.h | 29 +++++++++++++++++++++++++++
|
||||
13 files changed, 69 insertions(+), 58 deletions(-)
|
||||
|
||||
diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c
|
||||
index 71dd4f0ab..34cbe834f 100644
|
||||
--- a/grub-core/lib/i386/relocator.c
|
||||
+++ b/grub-core/lib/i386/relocator.c
|
||||
@@ -83,11 +83,10 @@ grub_relocator32_boot (struct grub_relocator *rel,
|
||||
/* Specific memory range due to Global Descriptor Table for use by payload
|
||||
that we will store in returned chunk. The address range and preference
|
||||
are based on "THE LINUX/x86 BOOT PROTOCOL" specification. */
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0x1000,
|
||||
- 0x9a000 - RELOCATOR_SIZEOF (32),
|
||||
- RELOCATOR_SIZEOF (32), 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_LOW,
|
||||
- avoid_efi_bootservices);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x1000, 0x9a000,
|
||||
+ RELOCATOR_SIZEOF (32), 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_LOW,
|
||||
+ avoid_efi_bootservices);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -125,13 +124,10 @@ grub_relocator16_boot (struct grub_relocator *rel,
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
/* Put it higher than the byte it checks for A20 check. */
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
|
||||
- 0xa0000 - RELOCATOR_SIZEOF (16)
|
||||
- - GRUB_RELOCATOR16_STACK_SIZE,
|
||||
- RELOCATOR_SIZEOF (16)
|
||||
- + GRUB_RELOCATOR16_STACK_SIZE, 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE,
|
||||
- 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x8010, 0xa0000,
|
||||
+ RELOCATOR_SIZEOF (16) +
|
||||
+ GRUB_RELOCATOR16_STACK_SIZE, 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -183,11 +179,9 @@ grub_relocator64_boot (struct grub_relocator *rel,
|
||||
void *relst;
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr,
|
||||
- max_addr - RELOCATOR_SIZEOF (64),
|
||||
- RELOCATOR_SIZEOF (64), 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE,
|
||||
- 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, min_addr, max_addr,
|
||||
+ RELOCATOR_SIZEOF (64), 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
diff --git a/grub-core/lib/mips/relocator.c b/grub-core/lib/mips/relocator.c
|
||||
index 9d5f49cb9..743b213e6 100644
|
||||
--- a/grub-core/lib/mips/relocator.c
|
||||
+++ b/grub-core/lib/mips/relocator.c
|
||||
@@ -120,10 +120,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
|
||||
unsigned i;
|
||||
grub_addr_t vtarget;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
|
||||
- (0xffffffff - stateset_size)
|
||||
- + 1, stateset_size,
|
||||
- sizeof (grub_uint32_t),
|
||||
+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
|
||||
+ stateset_size, sizeof (grub_uint32_t),
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
diff --git a/grub-core/lib/powerpc/relocator.c b/grub-core/lib/powerpc/relocator.c
|
||||
index bdf2b111b..8ffb8b686 100644
|
||||
--- a/grub-core/lib/powerpc/relocator.c
|
||||
+++ b/grub-core/lib/powerpc/relocator.c
|
||||
@@ -115,10 +115,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
|
||||
unsigned i;
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
|
||||
- (0xffffffff - stateset_size)
|
||||
- + 1, stateset_size,
|
||||
- sizeof (grub_uint32_t),
|
||||
+ err = grub_relocator_alloc_chunk_align (rel, &ch, 0, UP_TO_TOP32 (stateset_size),
|
||||
+ stateset_size, sizeof (grub_uint32_t),
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
diff --git a/grub-core/lib/x86_64/efi/relocator.c b/grub-core/lib/x86_64/efi/relocator.c
|
||||
index 3caef7a40..7d200a125 100644
|
||||
--- a/grub-core/lib/x86_64/efi/relocator.c
|
||||
+++ b/grub-core/lib/x86_64/efi/relocator.c
|
||||
@@ -50,10 +50,9 @@ grub_relocator64_efi_boot (struct grub_relocator *rel,
|
||||
* 64-bit relocator code may live above 4 GiB quite well.
|
||||
* However, I do not want ask for problems. Just in case.
|
||||
*/
|
||||
- err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
|
||||
- 0x100000000 - RELOCATOR_SIZEOF (64_efi),
|
||||
- RELOCATOR_SIZEOF (64_efi), 16,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0, 0x100000000,
|
||||
+ RELOCATOR_SIZEOF (64_efi), 16,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
|
||||
index 02a73463a..efbb99307 100644
|
||||
--- a/grub-core/loader/i386/linux.c
|
||||
+++ b/grub-core/loader/i386/linux.c
|
||||
@@ -181,9 +181,8 @@ allocate_pages (grub_size_t prot_size, grub_size_t *align,
|
||||
for (; err && *align + 1 > min_align; (*align)--)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
- err = grub_relocator_alloc_chunk_align (relocator, &ch,
|
||||
- 0x1000000,
|
||||
- 0xffffffff & ~prot_size,
|
||||
+ err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000000,
|
||||
+ UP_TO_TOP32 (prot_size),
|
||||
prot_size, 1 << *align,
|
||||
GRUB_RELOCATOR_PREFERENCE_LOW,
|
||||
1);
|
||||
diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c
|
||||
index ad3cc292f..a67d9d0a8 100644
|
||||
--- a/grub-core/loader/i386/multiboot_mbi.c
|
||||
+++ b/grub-core/loader/i386/multiboot_mbi.c
|
||||
@@ -466,10 +466,9 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
|
||||
|
||||
bufsize = grub_multiboot_get_mbi_size ();
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
|
||||
- 0x10000, 0xa0000 - bufsize,
|
||||
- bufsize, 4,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (grub_multiboot_relocator, &ch,
|
||||
+ 0x10000, 0xa0000, bufsize, 4,
|
||||
+ GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
if (err)
|
||||
return err;
|
||||
ptrorig = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
|
||||
index 31f09922b..5fed5ffdf 100644
|
||||
--- a/grub-core/loader/i386/pc/linux.c
|
||||
+++ b/grub-core/loader/i386/pc/linux.c
|
||||
@@ -453,10 +453,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
- err = grub_relocator_alloc_chunk_align (relocator, &ch,
|
||||
- addr_min, addr_max - size,
|
||||
- size, 0x1000,
|
||||
- GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, addr_min, addr_max, size,
|
||||
+ 0x1000, GRUB_RELOCATOR_PREFERENCE_HIGH, 0);
|
||||
if (err)
|
||||
return err;
|
||||
initrd_chunk = get_virtual_current_address (ch);
|
||||
diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c
|
||||
index 7b723bf18..e4ed95921 100644
|
||||
--- a/grub-core/loader/mips/linux.c
|
||||
+++ b/grub-core/loader/mips/linux.c
|
||||
@@ -442,12 +442,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (relocator, &ch,
|
||||
- (target_addr & 0x1fffffff)
|
||||
- + linux_size + 0x10000,
|
||||
- (0x10000000 - size),
|
||||
- size, 0x10000,
|
||||
- GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (relocator, &ch, (target_addr & 0x1fffffff) +
|
||||
+ linux_size + 0x10000, 0x10000000, size,
|
||||
+ 0x10000, GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
|
||||
if (err)
|
||||
goto fail;
|
||||
diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c
|
||||
index 4a98d7082..facb13f3d 100644
|
||||
--- a/grub-core/loader/multiboot.c
|
||||
+++ b/grub-core/loader/multiboot.c
|
||||
@@ -403,7 +403,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
|
||||
- lowest_addr, (0xffffffff - size) + 1,
|
||||
+ lowest_addr, UP_TO_TOP32 (size),
|
||||
size, MULTIBOOT_MOD_ALIGN,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
if (err)
|
||||
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
|
||||
index cc6853692..f2318e0d1 100644
|
||||
--- a/grub-core/loader/multiboot_elfxx.c
|
||||
+++ b/grub-core/loader/multiboot_elfxx.c
|
||||
@@ -109,10 +109,10 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||
if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch,
|
||||
- mld->min_addr, mld->max_addr - load_size,
|
||||
- load_size, mld->align ? mld->align : 1,
|
||||
- mld->preference, mld->avoid_efi_boot_services);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (GRUB_MULTIBOOT (relocator), &ch,
|
||||
+ mld->min_addr, mld->max_addr,
|
||||
+ load_size, mld->align ? mld->align : 1,
|
||||
+ mld->preference, mld->avoid_efi_boot_services);
|
||||
|
||||
if (err)
|
||||
{
|
||||
@@ -256,7 +256,7 @@ CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
|
||||
continue;
|
||||
|
||||
err = grub_relocator_alloc_chunk_align (GRUB_MULTIBOOT (relocator), &ch, 0,
|
||||
- (0xffffffff - sh->sh_size) + 1,
|
||||
+ UP_TO_TOP32 (sh->sh_size),
|
||||
sh->sh_size, sh->sh_addralign,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE,
|
||||
mld->avoid_efi_boot_services);
|
||||
diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c
|
||||
index 0efc66062..03967839c 100644
|
||||
--- a/grub-core/loader/multiboot_mbi2.c
|
||||
+++ b/grub-core/loader/multiboot_mbi2.c
|
||||
@@ -295,10 +295,10 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
|
||||
}
|
||||
|
||||
- err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
|
||||
- mld.min_addr, mld.max_addr - code_size,
|
||||
- code_size, mld.align ? mld.align : 1,
|
||||
- mld.preference, keep_bs);
|
||||
+ err = grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch,
|
||||
+ mld.min_addr, mld.max_addr,
|
||||
+ code_size, mld.align ? mld.align : 1,
|
||||
+ mld.preference, keep_bs);
|
||||
}
|
||||
else
|
||||
err = grub_relocator_alloc_chunk_addr (grub_multiboot2_relocator,
|
||||
@@ -708,7 +708,7 @@ grub_multiboot2_make_mbi (grub_uint32_t *target)
|
||||
COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);
|
||||
|
||||
err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
|
||||
- 0, 0xffffffff - bufsize,
|
||||
+ 0, UP_TO_TOP32 (bufsize),
|
||||
bufsize, MULTIBOOT_TAG_ALIGN,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
|
||||
if (err)
|
||||
diff --git a/grub-core/loader/xnu_resume.c b/grub-core/loader/xnu_resume.c
|
||||
index 8089804d4..d648ef0cd 100644
|
||||
--- a/grub-core/loader/xnu_resume.c
|
||||
+++ b/grub-core/loader/xnu_resume.c
|
||||
@@ -129,7 +129,7 @@ grub_xnu_resume (char *imagename)
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
err = grub_relocator_alloc_chunk_align (grub_xnu_relocator, &ch, 0,
|
||||
- (0xffffffff - hibhead.image_size) + 1,
|
||||
+ UP_TO_TOP32 (hibhead.image_size),
|
||||
hibhead.image_size,
|
||||
GRUB_XNU_PAGESIZE,
|
||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||
diff --git a/include/grub/relocator.h b/include/grub/relocator.h
|
||||
index 24d8672d2..1b3bdd92a 100644
|
||||
--- a/include/grub/relocator.h
|
||||
+++ b/include/grub/relocator.h
|
||||
@@ -49,6 +49,35 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
|
||||
int preference,
|
||||
int avoid_efi_boot_services);
|
||||
|
||||
+/*
|
||||
+ * Wrapper for grub_relocator_alloc_chunk_align() with purpose of
|
||||
+ * protecting against integer underflow.
|
||||
+ *
|
||||
+ * Compare to its callee, max_addr has different meaning here.
|
||||
+ * It covers entire chunk and not just start address of the chunk.
|
||||
+ */
|
||||
+static inline grub_err_t
|
||||
+grub_relocator_alloc_chunk_align_safe (struct grub_relocator *rel,
|
||||
+ grub_relocator_chunk_t *out,
|
||||
+ grub_phys_addr_t min_addr,
|
||||
+ grub_phys_addr_t max_addr,
|
||||
+ grub_size_t size, grub_size_t align,
|
||||
+ int preference,
|
||||
+ int avoid_efi_boot_services)
|
||||
+{
|
||||
+ /* Sanity check and ensure following equation (max_addr - size) is safe. */
|
||||
+ if (max_addr < size || (max_addr - size) < min_addr)
|
||||
+ return GRUB_ERR_OUT_OF_RANGE;
|
||||
+
|
||||
+ return grub_relocator_alloc_chunk_align (rel, out, min_addr,
|
||||
+ max_addr - size,
|
||||
+ size, align, preference,
|
||||
+ avoid_efi_boot_services);
|
||||
+}
|
||||
+
|
||||
+/* Top 32-bit address minus s bytes and plus 1 byte. */
|
||||
+#define UP_TO_TOP32(s) ((~(s) & 0xffffffff) + 1)
|
||||
+
|
||||
#define GRUB_RELOCATOR_PREFERENCE_NONE 0
|
||||
#define GRUB_RELOCATOR_PREFERENCE_LOW 1
|
||||
#define GRUB_RELOCATOR_PREFERENCE_HIGH 2
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,37 @@
|
||||
From 73aa0776457066ee6ebc93486c3cf0e6b755d1b8 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Fri, 10 Jul 2020 11:21:14 +0100
|
||||
Subject: [PATCH] script: Remove unused fields from grub_script_function
|
||||
struct
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
include/grub/script_sh.h | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
|
||||
index 360c2be1f..b382bcf09 100644
|
||||
--- a/include/grub/script_sh.h
|
||||
+++ b/include/grub/script_sh.h
|
||||
@@ -359,13 +359,8 @@ struct grub_script_function
|
||||
/* The script function. */
|
||||
struct grub_script *func;
|
||||
|
||||
- /* The flags. */
|
||||
- unsigned flags;
|
||||
-
|
||||
/* The next element. */
|
||||
struct grub_script_function *next;
|
||||
-
|
||||
- int references;
|
||||
};
|
||||
typedef struct grub_script_function *grub_script_function_t;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,113 @@
|
||||
From 26349fcf80982b4d0120b73b2836e88bcf16853c Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Fri, 10 Jul 2020 14:41:45 +0100
|
||||
Subject: [PATCH] script: Avoid a use-after-free when redefining a
|
||||
function during execution
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Defining a new function with the same name as a previously defined
|
||||
function causes the grub_script and associated resources for the
|
||||
previous function to be freed. If the previous function is currently
|
||||
executing when a function with the same name is defined, this results
|
||||
in use-after-frees when processing subsequent commands in the original
|
||||
function.
|
||||
|
||||
Instead, reject a new function definition if it has the same name as
|
||||
a previously defined function, and that function is currently being
|
||||
executed. Although a behavioural change, this should be backwards
|
||||
compatible with existing configurations because they can't be
|
||||
dependent on the current behaviour without being broken.
|
||||
|
||||
Fixes: CVE-2020-15706
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/script/execute.c | 2 ++
|
||||
grub-core/script/function.c | 16 +++++++++++++---
|
||||
grub-core/script/parser.y | 3 ++-
|
||||
include/grub/script_sh.h | 2 ++
|
||||
4 files changed, 19 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
|
||||
index c8d6806fe..7e028e135 100644
|
||||
--- a/grub-core/script/execute.c
|
||||
+++ b/grub-core/script/execute.c
|
||||
@@ -838,7 +838,9 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
|
||||
old_scope = scope;
|
||||
scope = &new_scope;
|
||||
|
||||
+ func->executing++;
|
||||
ret = grub_script_execute (func->func);
|
||||
+ func->executing--;
|
||||
|
||||
function_return = 0;
|
||||
active_loops = loops;
|
||||
diff --git a/grub-core/script/function.c b/grub-core/script/function.c
|
||||
index d36655e51..3aad04bf9 100644
|
||||
--- a/grub-core/script/function.c
|
||||
+++ b/grub-core/script/function.c
|
||||
@@ -34,6 +34,7 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
|
||||
func = (grub_script_function_t) grub_malloc (sizeof (*func));
|
||||
if (! func)
|
||||
return 0;
|
||||
+ func->executing = 0;
|
||||
|
||||
func->name = grub_strdup (functionname_arg->str);
|
||||
if (! func->name)
|
||||
@@ -60,10 +61,19 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
|
||||
grub_script_function_t q;
|
||||
|
||||
q = *p;
|
||||
- grub_script_free (q->func);
|
||||
- q->func = cmd;
|
||||
grub_free (func);
|
||||
- func = q;
|
||||
+ if (q->executing > 0)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
+ N_("attempt to redefine a function being executed"));
|
||||
+ func = NULL;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ grub_script_free (q->func);
|
||||
+ q->func = cmd;
|
||||
+ func = q;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y
|
||||
index 4f0ab8319..f80b86b6f 100644
|
||||
--- a/grub-core/script/parser.y
|
||||
+++ b/grub-core/script/parser.y
|
||||
@@ -289,7 +289,8 @@ function: "function" "name"
|
||||
grub_script_mem_free (state->func_mem);
|
||||
else {
|
||||
script->children = state->scripts;
|
||||
- grub_script_function_create ($2, script);
|
||||
+ if (!grub_script_function_create ($2, script))
|
||||
+ grub_script_free (script);
|
||||
}
|
||||
|
||||
state->scripts = $<scripts>3;
|
||||
diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
|
||||
index b382bcf09..6c48e0751 100644
|
||||
--- a/include/grub/script_sh.h
|
||||
+++ b/include/grub/script_sh.h
|
||||
@@ -361,6 +361,8 @@ struct grub_script_function
|
||||
|
||||
/* The next element. */
|
||||
struct grub_script_function *next;
|
||||
+
|
||||
+ unsigned executing;
|
||||
};
|
||||
typedef struct grub_script_function *grub_script_function_t;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,49 @@
|
||||
From 06aa91f79f902752cb7e5d22ac0ea8e13bffd056 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Fri, 17 Jul 2020 05:17:26 +0000
|
||||
Subject: [PATCH] relocator: Fix grub_relocator_alloc_chunk_align() top
|
||||
memory allocation
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Current implementation of grub_relocator_alloc_chunk_align()
|
||||
does not allow allocation of the top byte.
|
||||
|
||||
Assuming input args are:
|
||||
max_addr = 0xfffff000;
|
||||
size = 0x1000;
|
||||
|
||||
And this is valid. But following overflow protection will
|
||||
unnecessarily move max_addr one byte down (to 0xffffefff):
|
||||
if (max_addr > ~size)
|
||||
max_addr = ~size;
|
||||
|
||||
~size + 1 will fix the situation. In addition, check size
|
||||
for non zero to do not zero max_addr.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/lib/relocator.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c
|
||||
index 5847aac36..f2c1944c2 100644
|
||||
--- a/grub-core/lib/relocator.c
|
||||
+++ b/grub-core/lib/relocator.c
|
||||
@@ -1386,8 +1386,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel,
|
||||
};
|
||||
grub_addr_t min_addr2 = 0, max_addr2;
|
||||
|
||||
- if (max_addr > ~size)
|
||||
- max_addr = ~size;
|
||||
+ if (size && (max_addr > ~size))
|
||||
+ max_addr = ~size + 1;
|
||||
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
if (min_addr < 0x1000)
|
||||
--
|
||||
2.26.2
|
||||
|
61
boot/grub2/0021-hfsplus-Fix-two-more-overflows.patch
Normal file
61
boot/grub2/0021-hfsplus-Fix-two-more-overflows.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From feec993673d8e13fcf22fe2389ac29222b6daebd Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 14:43:31 -0400
|
||||
Subject: [PATCH] hfsplus: Fix two more overflows
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Both node->size and node->namelen come from the supplied filesystem,
|
||||
which may be user-supplied. We can't trust them for the math unless we
|
||||
know they don't overflow. Making sure they go through grub_add() or
|
||||
grub_calloc() first will give us that.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/fs/hfsplus.c | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
|
||||
index dae43becc..9c4e4c88c 100644
|
||||
--- a/grub-core/fs/hfsplus.c
|
||||
+++ b/grub-core/fs/hfsplus.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <grub/hfs.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/hfsplus.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -475,8 +476,12 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
char *symlink;
|
||||
grub_ssize_t numread;
|
||||
+ grub_size_t sz = node->size;
|
||||
|
||||
- symlink = grub_malloc (node->size + 1);
|
||||
+ if (grub_add (sz, 1, &sz))
|
||||
+ return NULL;
|
||||
+
|
||||
+ symlink = grub_malloc (sz);
|
||||
if (!symlink)
|
||||
return 0;
|
||||
|
||||
@@ -715,8 +720,8 @@ list_nodes (void *record, void *hook_arg)
|
||||
if (type == GRUB_FSHELP_UNKNOWN)
|
||||
return 0;
|
||||
|
||||
- filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen)
|
||||
- * GRUB_MAX_UTF8_PER_UTF16 + 1);
|
||||
+ filename = grub_calloc (grub_be_to_cpu16 (catkey->namelen),
|
||||
+ GRUB_MAX_UTF8_PER_UTF16 + 1);
|
||||
if (! filename)
|
||||
return 0;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,116 @@
|
||||
From a1845e90fc19fb5e904091bad8a378f458798e4a Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 15:48:20 -0400
|
||||
Subject: [PATCH] lvm: Fix two more potential data-dependent alloc
|
||||
overflows
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It appears to be possible to make a (possibly invalid) lvm PV with
|
||||
a metadata size field that overflows our type when adding it to the
|
||||
address we've allocated. Even if it doesn't, it may be possible to do so
|
||||
with the math using the outcome of that as an operand. Check them both.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/disk/lvm.c | 48 ++++++++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 40 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
|
||||
index d1df640b3..139fafd47 100644
|
||||
--- a/grub-core/disk/lvm.c
|
||||
+++ b/grub-core/disk/lvm.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/lvm.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/i18n.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/emu/misc.h>
|
||||
@@ -102,10 +103,11 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_uint64_t mda_offset, mda_size;
|
||||
+ grub_size_t ptr;
|
||||
char buf[GRUB_LVM_LABEL_SIZE];
|
||||
char vg_id[GRUB_LVM_ID_STRLEN+1];
|
||||
char pv_id[GRUB_LVM_ID_STRLEN+1];
|
||||
- char *metadatabuf, *p, *q, *vgname;
|
||||
+ char *metadatabuf, *p, *q, *mda_end, *vgname;
|
||||
struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf;
|
||||
struct grub_lvm_pv_header *pvh;
|
||||
struct grub_lvm_disk_locn *dlocn;
|
||||
@@ -205,19 +207,31 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
grub_le_to_cpu64 (rlocn->size) -
|
||||
grub_le_to_cpu64 (mdah->size));
|
||||
}
|
||||
- p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset);
|
||||
|
||||
- while (*q != ' ' && q < metadatabuf + mda_size)
|
||||
- q++;
|
||||
-
|
||||
- if (q == metadatabuf + mda_size)
|
||||
+ if (grub_add ((grub_size_t)metadatabuf,
|
||||
+ (grub_size_t)grub_le_to_cpu64 (rlocn->offset),
|
||||
+ &ptr))
|
||||
{
|
||||
+ error_parsing_metadata:
|
||||
#ifdef GRUB_UTIL
|
||||
grub_util_info ("error parsing metadata");
|
||||
#endif
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
+ p = q = (char *)ptr;
|
||||
+
|
||||
+ if (grub_add ((grub_size_t)metadatabuf, (grub_size_t)mda_size, &ptr))
|
||||
+ goto error_parsing_metadata;
|
||||
+
|
||||
+ mda_end = (char *)ptr;
|
||||
+
|
||||
+ while (*q != ' ' && q < mda_end)
|
||||
+ q++;
|
||||
+
|
||||
+ if (q == mda_end)
|
||||
+ goto error_parsing_metadata;
|
||||
+
|
||||
vgname_len = q - p;
|
||||
vgname = grub_malloc (vgname_len + 1);
|
||||
if (!vgname)
|
||||
@@ -367,8 +381,26 @@ grub_lvm_detect (grub_disk_t disk,
|
||||
{
|
||||
const char *iptr;
|
||||
char *optr;
|
||||
- lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len
|
||||
- + 1 + 2 * s + 1);
|
||||
+
|
||||
+ /*
|
||||
+ * This is kind of hard to read with our safe (but rather
|
||||
+ * baroque) math primatives, but it boils down to:
|
||||
+ *
|
||||
+ * sz0 = vgname_len * 2 + 1 +
|
||||
+ * s * 2 + 1 +
|
||||
+ * sizeof ("lvm/") - 1;
|
||||
+ */
|
||||
+ grub_size_t sz0 = vgname_len, sz1 = s;
|
||||
+
|
||||
+ if (grub_mul (sz0, 2, &sz0) ||
|
||||
+ grub_add (sz0, 1, &sz0) ||
|
||||
+ grub_mul (sz1, 2, &sz1) ||
|
||||
+ grub_add (sz1, 1, &sz1) ||
|
||||
+ grub_add (sz0, sz1, &sz0) ||
|
||||
+ grub_add (sz0, sizeof ("lvm/") - 1, &sz0))
|
||||
+ goto lvs_fail;
|
||||
+
|
||||
+ lv->fullname = grub_malloc (sz0);
|
||||
if (!lv->fullname)
|
||||
goto lvs_fail;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
38
boot/grub2/0023-emu-Make-grub_free-NULL-safe.patch
Normal file
38
boot/grub2/0023-emu-Make-grub_free-NULL-safe.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From 320e86747a32e4d46d24ee4b64493741c161da50 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 16:08:08 -0400
|
||||
Subject: [PATCH] emu: Make grub_free(NULL) safe
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The grub_free() implementation in grub-core/kern/mm.c safely handles
|
||||
NULL pointers, and code at many places depends on this. We don't know
|
||||
that the same is true on all host OSes, so we need to handle the same
|
||||
behavior in grub-emu's implementation.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/kern/emu/mm.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
|
||||
index 145b01d37..4d1046a21 100644
|
||||
--- a/grub-core/kern/emu/mm.c
|
||||
+++ b/grub-core/kern/emu/mm.c
|
||||
@@ -60,7 +60,8 @@ grub_zalloc (grub_size_t size)
|
||||
void
|
||||
grub_free (void *ptr)
|
||||
{
|
||||
- free (ptr);
|
||||
+ if (ptr)
|
||||
+ free (ptr);
|
||||
}
|
||||
|
||||
void *
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,239 @@
|
||||
From c330aa099a38bc5c4d3066954fe35767cc06adb1 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Sun, 19 Jul 2020 16:53:27 -0400
|
||||
Subject: [PATCH] efi: Fix some malformed device path arithmetic errors
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Several places we take the length of a device path and subtract 4 from
|
||||
it, without ever checking that it's >= 4. There are also cases where
|
||||
this kind of malformation will result in unpredictable iteration,
|
||||
including treating the length from one dp node as the type in the next
|
||||
node. These are all errors, no matter where the data comes from.
|
||||
|
||||
This patch adds a checking macro, GRUB_EFI_DEVICE_PATH_VALID(), which
|
||||
can be used in several places, and makes GRUB_EFI_NEXT_DEVICE_PATH()
|
||||
return NULL and GRUB_EFI_END_ENTIRE_DEVICE_PATH() evaluate as true when
|
||||
the length is too small. Additionally, it makes several places in the
|
||||
code check for and return errors in these cases.
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/kern/efi/efi.c | 64 +++++++++++++++++++++++++-----
|
||||
grub-core/loader/efi/chainloader.c | 13 +++++-
|
||||
grub-core/loader/i386/xnu.c | 9 +++--
|
||||
include/grub/efi/api.h | 14 ++++---
|
||||
4 files changed, 79 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
|
||||
index dc31caa21..c97969a65 100644
|
||||
--- a/grub-core/kern/efi/efi.c
|
||||
+++ b/grub-core/kern/efi/efi.c
|
||||
@@ -332,7 +332,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
|
||||
dp = dp0;
|
||||
|
||||
- while (1)
|
||||
+ while (dp)
|
||||
{
|
||||
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
|
||||
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
|
||||
@@ -342,9 +342,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
|
||||
&& subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
|
||||
{
|
||||
- grub_efi_uint16_t len;
|
||||
- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
|
||||
- / sizeof (grub_efi_char16_t));
|
||||
+ grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
|
||||
+
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ len = (len - 4) / sizeof (grub_efi_char16_t);
|
||||
filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
|
||||
}
|
||||
|
||||
@@ -360,7 +366,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
- while (1)
|
||||
+ while (dp)
|
||||
{
|
||||
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
|
||||
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
|
||||
@@ -376,8 +382,15 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
|
||||
|
||||
*p++ = '/';
|
||||
|
||||
- len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
|
||||
- / sizeof (grub_efi_char16_t));
|
||||
+ len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ len = (len - 4) / sizeof (grub_efi_char16_t);
|
||||
fp = (grub_efi_file_path_device_path_t *) dp;
|
||||
/* According to EFI spec Path Name is NULL terminated */
|
||||
while (len > 0 && fp->path_name[len - 1] == 0)
|
||||
@@ -452,7 +465,26 @@ grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
|
||||
;
|
||||
p = GRUB_EFI_NEXT_DEVICE_PATH (p))
|
||||
{
|
||||
- total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p);
|
||||
+ grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p);
|
||||
+
|
||||
+ /*
|
||||
+ * In the event that we find a node that's completely garbage, for
|
||||
+ * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size
|
||||
+ * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and
|
||||
+ * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue,
|
||||
+ * and neither should our consumers, but there won't be any error raised
|
||||
+ * even though the device path is junk.
|
||||
+ *
|
||||
+ * This keeps us from passing junk down back to our caller.
|
||||
+ */
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ total_size += len;
|
||||
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
|
||||
break;
|
||||
}
|
||||
@@ -497,7 +529,7 @@ dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
|
||||
void
|
||||
grub_efi_print_device_path (grub_efi_device_path_t *dp)
|
||||
{
|
||||
- while (1)
|
||||
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp))
|
||||
{
|
||||
grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
|
||||
grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
|
||||
@@ -909,7 +941,10 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
|
||||
/* Return non-zero. */
|
||||
return 1;
|
||||
|
||||
- while (1)
|
||||
+ if (dp1 == dp2)
|
||||
+ return 0;
|
||||
+
|
||||
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2))
|
||||
{
|
||||
grub_efi_uint8_t type1, type2;
|
||||
grub_efi_uint8_t subtype1, subtype2;
|
||||
@@ -945,5 +980,14 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
|
||||
dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * There's no "right" answer here, but we probably don't want to call a valid
|
||||
+ * dp and an invalid dp equal, so pick one way or the other.
|
||||
+ */
|
||||
+ if (GRUB_EFI_DEVICE_PATH_VALID (dp1) && !GRUB_EFI_DEVICE_PATH_VALID (dp2))
|
||||
+ return 1;
|
||||
+ else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2))
|
||||
+ return -1;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index daf8c6b54..a8d7b9155 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -156,9 +156,18 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
|
||||
|
||||
size = 0;
|
||||
d = dp;
|
||||
- while (1)
|
||||
+ while (d)
|
||||
{
|
||||
- size += GRUB_EFI_DEVICE_PATH_LENGTH (d);
|
||||
+ grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (d);
|
||||
+
|
||||
+ if (len < 4)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ "malformed EFI Device Path node has length=%d", len);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ size += len;
|
||||
if ((GRUB_EFI_END_ENTIRE_DEVICE_PATH (d)))
|
||||
break;
|
||||
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||
diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c
|
||||
index e9e119259..a70093607 100644
|
||||
--- a/grub-core/loader/i386/xnu.c
|
||||
+++ b/grub-core/loader/i386/xnu.c
|
||||
@@ -515,14 +515,15 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
devhead = buf;
|
||||
buf = devhead + 1;
|
||||
- dpstart = buf;
|
||||
+ dp = dpstart = buf;
|
||||
|
||||
- do
|
||||
+ while (GRUB_EFI_DEVICE_PATH_VALID (dp) && buf < bufend)
|
||||
{
|
||||
- dp = buf;
|
||||
buf = (char *) buf + GRUB_EFI_DEVICE_PATH_LENGTH (dp);
|
||||
+ if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
|
||||
+ break;
|
||||
+ dp = buf;
|
||||
}
|
||||
- while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp) && buf < bufend);
|
||||
|
||||
dev = grub_xnu_devprop_add_device (dpstart, (char *) buf
|
||||
- (char *) dpstart);
|
||||
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
||||
index addcbfa8f..cf1355a8c 100644
|
||||
--- a/include/grub/efi/api.h
|
||||
+++ b/include/grub/efi/api.h
|
||||
@@ -625,6 +625,7 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
|
||||
#define GRUB_EFI_DEVICE_PATH_TYPE(dp) ((dp)->type & 0x7f)
|
||||
#define GRUB_EFI_DEVICE_PATH_SUBTYPE(dp) ((dp)->subtype)
|
||||
#define GRUB_EFI_DEVICE_PATH_LENGTH(dp) ((dp)->length)
|
||||
+#define GRUB_EFI_DEVICE_PATH_VALID(dp) ((dp) != NULL && GRUB_EFI_DEVICE_PATH_LENGTH (dp) >= 4)
|
||||
|
||||
/* The End of Device Path nodes. */
|
||||
#define GRUB_EFI_END_DEVICE_PATH_TYPE (0xff & 0x7f)
|
||||
@@ -633,13 +634,16 @@ typedef struct grub_efi_device_path grub_efi_device_path_protocol_t;
|
||||
#define GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE 0x01
|
||||
|
||||
#define GRUB_EFI_END_ENTIRE_DEVICE_PATH(dp) \
|
||||
- (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
|
||||
- && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
|
||||
- == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE))
|
||||
+ (!GRUB_EFI_DEVICE_PATH_VALID (dp) || \
|
||||
+ (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_END_DEVICE_PATH_TYPE \
|
||||
+ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) \
|
||||
+ == GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)))
|
||||
|
||||
#define GRUB_EFI_NEXT_DEVICE_PATH(dp) \
|
||||
- ((grub_efi_device_path_t *) ((char *) (dp) \
|
||||
- + GRUB_EFI_DEVICE_PATH_LENGTH (dp)))
|
||||
+ (GRUB_EFI_DEVICE_PATH_VALID (dp) \
|
||||
+ ? ((grub_efi_device_path_t *) \
|
||||
+ ((char *) (dp) + GRUB_EFI_DEVICE_PATH_LENGTH (dp))) \
|
||||
+ : NULL)
|
||||
|
||||
/* Hardware Device Path. */
|
||||
#define GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE 1
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,78 @@
|
||||
From fb55bc37dd510911df4eaf649da939f5fafdc7ce Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Date: Wed, 29 Jul 2020 13:38:31 +0200
|
||||
Subject: [PATCH] efi/chainloader: Propagate errors from copy_file_path()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Without any error propagated to the caller, make_file_path()
|
||||
would then try to advance the invalid device path node with
|
||||
GRUB_EFI_NEXT_DEVICE_PATH(), which would fail, returning a NULL
|
||||
pointer that would subsequently be dereferenced. Hence, propagate
|
||||
errors from copy_file_path().
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/loader/efi/chainloader.c | 19 +++++++++++++------
|
||||
1 file changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index a8d7b9155..7b31c3fb9 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -106,7 +106,7 @@ grub_chainloader_boot (void)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static grub_err_t
|
||||
copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||
const char *str, grub_efi_uint16_t len)
|
||||
{
|
||||
@@ -118,7 +118,7 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||
|
||||
path_name = grub_calloc (len, GRUB_MAX_UTF16_PER_UTF8 * sizeof (*path_name));
|
||||
if (!path_name)
|
||||
- return;
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate path buffer");
|
||||
|
||||
size = grub_utf8_to_utf16 (path_name, len * GRUB_MAX_UTF16_PER_UTF8,
|
||||
(const grub_uint8_t *) str, len, 0);
|
||||
@@ -131,6 +131,7 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
|
||||
fp->path_name[size++] = '\0';
|
||||
fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
|
||||
grub_free (path_name);
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_efi_device_path_t *
|
||||
@@ -189,13 +190,19 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
|
||||
d = (grub_efi_device_path_t *) ((char *) file_path
|
||||
+ ((char *) d - (char *) dp));
|
||||
grub_efi_print_device_path (d);
|
||||
- copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
- dir_start, dir_end - dir_start);
|
||||
+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
+ dir_start, dir_end - dir_start) != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ fail:
|
||||
+ grub_free (file_path);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
/* Fill the file path for the file. */
|
||||
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||
- copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
- dir_end + 1, grub_strlen (dir_end + 1));
|
||||
+ if (copy_file_path ((grub_efi_file_path_device_path_t *) d,
|
||||
+ dir_end + 1, grub_strlen (dir_end + 1)) != GRUB_ERR_NONE)
|
||||
+ goto fail;
|
||||
|
||||
/* Fill the end of device path nodes. */
|
||||
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
|
||||
--
|
||||
2.26.2
|
||||
|
183
boot/grub2/0026-efi-Fix-use-after-free-in-halt-reboot-path.patch
Normal file
183
boot/grub2/0026-efi-Fix-use-after-free-in-halt-reboot-path.patch
Normal file
@ -0,0 +1,183 @@
|
||||
From 8a6d6299efcffd14c1130942195e6c0d9b50cacd Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Date: Mon, 20 Jul 2020 23:03:05 +0000
|
||||
Subject: [PATCH] efi: Fix use-after-free in halt/reboot path
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
commit 92bfc33db984 ("efi: Free malloc regions on exit")
|
||||
introduced memory freeing in grub_efi_fini(), which is
|
||||
used not only by exit path but by halt/reboot one as well.
|
||||
As result of memory freeing, code and data regions used by
|
||||
modules, such as halt, reboot, acpi (used by halt) also got
|
||||
freed. After return to module code, CPU executes, filled
|
||||
by UEFI firmware (tested with edk2), 0xAFAFAFAF pattern as
|
||||
a code. Which leads to #UD exception later.
|
||||
|
||||
grub> halt
|
||||
!!!! X64 Exception Type - 06(#UD - Invalid Opcode) CPU Apic ID - 00000000 !!!!
|
||||
RIP - 0000000003F4EC28, CS - 0000000000000038, RFLAGS - 0000000000200246
|
||||
RAX - 0000000000000000, RCX - 00000000061DA188, RDX - 0A74C0854DC35D41
|
||||
RBX - 0000000003E10E08, RSP - 0000000007F0F860, RBP - 0000000000000000
|
||||
RSI - 00000000064DB768, RDI - 000000000832C5C3
|
||||
R8 - 0000000000000002, R9 - 0000000000000000, R10 - 00000000061E2E52
|
||||
R11 - 0000000000000020, R12 - 0000000003EE5C1F, R13 - 00000000061E0FF4
|
||||
R14 - 0000000003E10D80, R15 - 00000000061E2F60
|
||||
DS - 0000000000000030, ES - 0000000000000030, FS - 0000000000000030
|
||||
GS - 0000000000000030, SS - 0000000000000030
|
||||
CR0 - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
|
||||
CR4 - 0000000000000668, CR8 - 0000000000000000
|
||||
DR0 - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
|
||||
DR3 - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
|
||||
GDTR - 00000000079EEA98 0000000000000047, LDTR - 0000000000000000
|
||||
IDTR - 0000000007598018 0000000000000FFF, TR - 0000000000000000
|
||||
FXSAVE_STATE - 0000000007F0F4C0
|
||||
|
||||
Proposal here is to continue to free allocated memory for
|
||||
exit boot services path but keep it for halt/reboot path
|
||||
as it won't be much security concern here.
|
||||
Introduced GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY
|
||||
loader flag to be used by efi halt/reboot path.
|
||||
|
||||
Signed-off-by: Alexey Makhalov <amakhalov@vmware.com>
|
||||
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/kern/arm/efi/init.c | 3 +++
|
||||
grub-core/kern/arm64/efi/init.c | 3 +++
|
||||
grub-core/kern/efi/efi.c | 3 ++-
|
||||
grub-core/kern/efi/init.c | 1 -
|
||||
grub-core/kern/i386/efi/init.c | 9 +++++++--
|
||||
grub-core/kern/ia64/efi/init.c | 9 +++++++--
|
||||
grub-core/kern/riscv/efi/init.c | 3 +++
|
||||
grub-core/lib/efi/halt.c | 3 ++-
|
||||
include/grub/loader.h | 1 +
|
||||
9 files changed, 28 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
|
||||
index 06df60e2f..40c3b467f 100644
|
||||
--- a/grub-core/kern/arm/efi/init.c
|
||||
+++ b/grub-core/kern/arm/efi/init.c
|
||||
@@ -71,4 +71,7 @@ grub_machine_fini (int flags)
|
||||
efi_call_1 (b->close_event, tmr_evt);
|
||||
|
||||
grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/arm64/efi/init.c b/grub-core/kern/arm64/efi/init.c
|
||||
index 6224999ec..5010caefd 100644
|
||||
--- a/grub-core/kern/arm64/efi/init.c
|
||||
+++ b/grub-core/kern/arm64/efi/init.c
|
||||
@@ -57,4 +57,7 @@ grub_machine_fini (int flags)
|
||||
return;
|
||||
|
||||
grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
|
||||
index c97969a65..9cfd88d77 100644
|
||||
--- a/grub-core/kern/efi/efi.c
|
||||
+++ b/grub-core/kern/efi/efi.c
|
||||
@@ -157,7 +157,8 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
- grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
|
||||
+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
|
||||
+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
|
||||
efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
|
||||
GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
|
||||
for (;;) ;
|
||||
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
|
||||
index 3dfdf2d22..2c31847bf 100644
|
||||
--- a/grub-core/kern/efi/init.c
|
||||
+++ b/grub-core/kern/efi/init.c
|
||||
@@ -80,5 +80,4 @@ grub_efi_fini (void)
|
||||
{
|
||||
grub_efidisk_fini ();
|
||||
grub_console_fini ();
|
||||
- grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c
|
||||
index da499aba0..deb2eacd8 100644
|
||||
--- a/grub-core/kern/i386/efi/init.c
|
||||
+++ b/grub-core/kern/i386/efi/init.c
|
||||
@@ -39,6 +39,11 @@ grub_machine_init (void)
|
||||
void
|
||||
grub_machine_fini (int flags)
|
||||
{
|
||||
- if (flags & GRUB_LOADER_FLAG_NORETURN)
|
||||
- grub_efi_fini ();
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
|
||||
+ return;
|
||||
+
|
||||
+ grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c
|
||||
index b5ecbd091..f1965571b 100644
|
||||
--- a/grub-core/kern/ia64/efi/init.c
|
||||
+++ b/grub-core/kern/ia64/efi/init.c
|
||||
@@ -70,6 +70,11 @@ grub_machine_init (void)
|
||||
void
|
||||
grub_machine_fini (int flags)
|
||||
{
|
||||
- if (flags & GRUB_LOADER_FLAG_NORETURN)
|
||||
- grub_efi_fini ();
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_NORETURN))
|
||||
+ return;
|
||||
+
|
||||
+ grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/kern/riscv/efi/init.c b/grub-core/kern/riscv/efi/init.c
|
||||
index 7eb1969d0..38795fe67 100644
|
||||
--- a/grub-core/kern/riscv/efi/init.c
|
||||
+++ b/grub-core/kern/riscv/efi/init.c
|
||||
@@ -73,4 +73,7 @@ grub_machine_fini (int flags)
|
||||
return;
|
||||
|
||||
grub_efi_fini ();
|
||||
+
|
||||
+ if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY))
|
||||
+ grub_efi_memory_fini ();
|
||||
}
|
||||
diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c
|
||||
index 5859f0498..29d413641 100644
|
||||
--- a/grub-core/lib/efi/halt.c
|
||||
+++ b/grub-core/lib/efi/halt.c
|
||||
@@ -28,7 +28,8 @@
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
- grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
|
||||
+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
|
||||
+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
|
||||
#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \
|
||||
!defined(__riscv)
|
||||
grub_acpi_halt ();
|
||||
diff --git a/include/grub/loader.h b/include/grub/loader.h
|
||||
index 7f82a499f..b20864282 100644
|
||||
--- a/include/grub/loader.h
|
||||
+++ b/include/grub/loader.h
|
||||
@@ -33,6 +33,7 @@ enum
|
||||
{
|
||||
GRUB_LOADER_FLAG_NORETURN = 1,
|
||||
GRUB_LOADER_FLAG_PXE_NOT_UNLOAD = 2,
|
||||
+ GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY = 4,
|
||||
};
|
||||
|
||||
void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,32 @@
|
||||
From a2a7464e9f10a677d6f91e1c4fa527d084c22e7c Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Fri, 24 Jul 2020 13:57:27 -0400
|
||||
Subject: [PATCH] loader/linux: Avoid overflow on initrd size calculation
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/loader/linux.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
|
||||
index 471b214d6..4cd8c20c7 100644
|
||||
--- a/grub-core/loader/linux.c
|
||||
+++ b/grub-core/loader/linux.c
|
||||
@@ -151,8 +151,7 @@ grub_initrd_init (int argc, char *argv[],
|
||||
initrd_ctx->nfiles = 0;
|
||||
initrd_ctx->components = 0;
|
||||
|
||||
- initrd_ctx->components = grub_zalloc (argc
|
||||
- * sizeof (initrd_ctx->components[0]));
|
||||
+ initrd_ctx->components = grub_calloc (argc, sizeof (initrd_ctx->components[0]));
|
||||
if (!initrd_ctx->components)
|
||||
return grub_errno;
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,173 @@
|
||||
From 0367e7d1b9bac3a78608a672bf6e4ace6a28b964 Mon Sep 17 00:00:00 2001
|
||||
From: Colin Watson <cjwatson@debian.org>
|
||||
Date: Sat, 25 Jul 2020 12:15:37 +0100
|
||||
Subject: [PATCH] linux: Fix integer overflows in initrd size handling
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
These could be triggered by a crafted filesystem with very large files.
|
||||
|
||||
Fixes: CVE-2020-15707
|
||||
|
||||
Signed-off-by: Colin Watson <cjwatson@debian.org>
|
||||
Reviewed-by: Jan Setje-Eilers <jan.setjeeilers@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
|
||||
---
|
||||
grub-core/loader/linux.c | 74 +++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 54 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c
|
||||
index 4cd8c20c7..3fe390f17 100644
|
||||
--- a/grub-core/loader/linux.c
|
||||
+++ b/grub-core/loader/linux.c
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
struct newc_head
|
||||
{
|
||||
@@ -98,13 +99,13 @@ free_dir (struct dir *root)
|
||||
grub_free (root);
|
||||
}
|
||||
|
||||
-static grub_size_t
|
||||
+static grub_err_t
|
||||
insert_dir (const char *name, struct dir **root,
|
||||
- grub_uint8_t *ptr)
|
||||
+ grub_uint8_t *ptr, grub_size_t *size)
|
||||
{
|
||||
struct dir *cur, **head = root;
|
||||
const char *cb, *ce = name;
|
||||
- grub_size_t size = 0;
|
||||
+ *size = 0;
|
||||
while (1)
|
||||
{
|
||||
for (cb = ce; *cb == '/'; cb++);
|
||||
@@ -130,14 +131,22 @@ insert_dir (const char *name, struct dir **root,
|
||||
ptr = make_header (ptr, name, ce - name,
|
||||
040777, 0);
|
||||
}
|
||||
- size += ALIGN_UP ((ce - (char *) name)
|
||||
- + sizeof (struct newc_head), 4);
|
||||
+ if (grub_add (*size,
|
||||
+ ALIGN_UP ((ce - (char *) name)
|
||||
+ + sizeof (struct newc_head), 4),
|
||||
+ size))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
+ grub_free (n->name);
|
||||
+ grub_free (n);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
*head = n;
|
||||
cur = n;
|
||||
}
|
||||
root = &cur->next;
|
||||
}
|
||||
- return size;
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
@@ -172,26 +181,33 @@ grub_initrd_init (int argc, char *argv[],
|
||||
eptr = grub_strchr (ptr, ':');
|
||||
if (eptr)
|
||||
{
|
||||
+ grub_size_t dir_size, name_len;
|
||||
+
|
||||
initrd_ctx->components[i].newc_name = grub_strndup (ptr, eptr - ptr);
|
||||
- if (!initrd_ctx->components[i].newc_name)
|
||||
+ if (!initrd_ctx->components[i].newc_name ||
|
||||
+ insert_dir (initrd_ctx->components[i].newc_name, &root, 0,
|
||||
+ &dir_size))
|
||||
{
|
||||
grub_initrd_close (initrd_ctx);
|
||||
return grub_errno;
|
||||
}
|
||||
- initrd_ctx->size
|
||||
- += ALIGN_UP (sizeof (struct newc_head)
|
||||
- + grub_strlen (initrd_ctx->components[i].newc_name),
|
||||
- 4);
|
||||
- initrd_ctx->size += insert_dir (initrd_ctx->components[i].newc_name,
|
||||
- &root, 0);
|
||||
+ name_len = grub_strlen (initrd_ctx->components[i].newc_name);
|
||||
+ if (grub_add (initrd_ctx->size,
|
||||
+ ALIGN_UP (sizeof (struct newc_head) + name_len, 4),
|
||||
+ &initrd_ctx->size) ||
|
||||
+ grub_add (initrd_ctx->size, dir_size, &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
newc = 1;
|
||||
fname = eptr + 1;
|
||||
}
|
||||
}
|
||||
else if (newc)
|
||||
{
|
||||
- initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
|
||||
- + sizeof ("TRAILER!!!") - 1, 4);
|
||||
+ if (grub_add (initrd_ctx->size,
|
||||
+ ALIGN_UP (sizeof (struct newc_head)
|
||||
+ + sizeof ("TRAILER!!!") - 1, 4),
|
||||
+ &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
free_dir (root);
|
||||
root = 0;
|
||||
newc = 0;
|
||||
@@ -207,19 +223,29 @@ grub_initrd_init (int argc, char *argv[],
|
||||
initrd_ctx->nfiles++;
|
||||
initrd_ctx->components[i].size
|
||||
= grub_file_size (initrd_ctx->components[i].file);
|
||||
- initrd_ctx->size += initrd_ctx->components[i].size;
|
||||
+ if (grub_add (initrd_ctx->size, initrd_ctx->components[i].size,
|
||||
+ &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
}
|
||||
|
||||
if (newc)
|
||||
{
|
||||
initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
|
||||
- initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head)
|
||||
- + sizeof ("TRAILER!!!") - 1, 4);
|
||||
+ if (grub_add (initrd_ctx->size,
|
||||
+ ALIGN_UP (sizeof (struct newc_head)
|
||||
+ + sizeof ("TRAILER!!!") - 1, 4),
|
||||
+ &initrd_ctx->size))
|
||||
+ goto overflow;
|
||||
free_dir (root);
|
||||
root = 0;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
+
|
||||
+ overflow:
|
||||
+ free_dir (root);
|
||||
+ grub_initrd_close (initrd_ctx);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
|
||||
}
|
||||
|
||||
grub_size_t
|
||||
@@ -260,8 +286,16 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
|
||||
|
||||
if (initrd_ctx->components[i].newc_name)
|
||||
{
|
||||
- ptr += insert_dir (initrd_ctx->components[i].newc_name,
|
||||
- &root, ptr);
|
||||
+ grub_size_t dir_size;
|
||||
+
|
||||
+ if (insert_dir (initrd_ctx->components[i].newc_name, &root, ptr,
|
||||
+ &dir_size))
|
||||
+ {
|
||||
+ free_dir (root);
|
||||
+ grub_initrd_close (initrd_ctx);
|
||||
+ return grub_errno;
|
||||
+ }
|
||||
+ ptr += dir_size;
|
||||
ptr = make_header (ptr, initrd_ctx->components[i].newc_name,
|
||||
grub_strlen (initrd_ctx->components[i].newc_name),
|
||||
0100777,
|
||||
--
|
||||
2.26.2
|
||||
|
@ -21,6 +21,17 @@ endef
|
||||
GRUB2_POST_PATCH_HOOKS += GRUB2_AVOID_AUTORECONF
|
||||
HOST_GRUB2_POST_PATCH_HOOKS += GRUB2_AVOID_AUTORECONF
|
||||
|
||||
# 0002-yylex-Make-lexer-fatal-errors-actually-be-fatal.patch
|
||||
GRUB2_IGNORE_CVES += CVE-2020-10713
|
||||
# 0005-calloc-Use-calloc-at-most-places.patch
|
||||
GRUB2_IGNORE_CVES += CVE-2020-14308
|
||||
# 0006-malloc-Use-overflow-checking-primitives-where-we-do-.patch
|
||||
GRUB2_IGNORE_CVES += CVE-2020-14309 CVE-2020-14310 CVE-2020-14311
|
||||
# 0019-script-Avoid-a-use-after-free-when-redefining-a-func.patch
|
||||
GRUB2_IGNORE_CVES += CVE-2020-15706
|
||||
# 0028-linux-Fix-integer-overflows-in-initrd-size-handling.patch
|
||||
GRUB2_IGNORE_CVES += CVE-2020-15707
|
||||
|
||||
ifeq ($(BR2_TARGET_GRUB2_INSTALL_TOOLS),y)
|
||||
GRUB2_INSTALL_TARGET = YES
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user