All of lore.kernel.org
 help / color / mirror / Atom feed
* [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-18  1:22   ` Colin Watson
  2021-03-02 18:00 ` [SECURITY PATCH 002/117] efi: Move the shim_lock verifier to the GRUB core Daniel Kiper
                   ` (117 subsequent siblings)
  118 siblings, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Marco A Benatto <mbenatto@redhat.com>

Move verifiers API from a module to the kernel image, so it can be
used there as well. There are no functional changes in this patch.

Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/Makefile.am                    | 1 +
 grub-core/Makefile.core.def              | 6 +-----
 grub-core/kern/main.c                    | 4 ++++
 grub-core/{commands => kern}/verifiers.c | 8 ++------
 include/grub/verify.h                    | 9 ++++++---
 5 files changed, 14 insertions(+), 14 deletions(-)
 rename grub-core/{commands => kern}/verifiers.c (97%)

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index c6ba5b2d7..cc6fc7dfa 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -91,6 +91,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/verify.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 68b9e9f68..0cecc3875 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -140,6 +140,7 @@ kernel = {
   common = kern/rescue_parser.c;
   common = kern/rescue_reader.c;
   common = kern/term.c;
+  common = kern/verifiers.c;
 
   noemu = kern/compiler-rt.c;
   noemu = kern/mm.c;
@@ -944,11 +945,6 @@ module = {
 };
 
 module = {
-  name = verifiers;
-  common = commands/verifiers.c;
-};
-
-module = {
   name = shim_lock;
   common = commands/efi/shim_lock.c;
   enable = efi;
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 9cad0c448..73967e2f5 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -29,6 +29,7 @@
 #include <grub/command.h>
 #include <grub/reader.h>
 #include <grub/parser.h>
+#include <grub/verify.h>
 
 #ifdef GRUB_MACHINE_PCBIOS
 #include <grub/machine/memory.h>
@@ -274,6 +275,9 @@ grub_main (void)
   grub_printf ("Welcome to GRUB!\n\n");
   grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
 
+  /* Init verifiers API. */
+  grub_verifiers_init ();
+
   grub_load_config ();
 
   grub_boot_time ("Before loading embedded modules.");
diff --git a/grub-core/commands/verifiers.c b/grub-core/kern/verifiers.c
similarity index 97%
rename from grub-core/commands/verifiers.c
rename to grub-core/kern/verifiers.c
index aae4d84bb..75d7994cf 100644
--- a/grub-core/commands/verifiers.c
+++ b/grub-core/kern/verifiers.c
@@ -221,12 +221,8 @@ grub_verify_string (char *str, enum grub_verify_string_type type)
   return GRUB_ERR_NONE;
 }
 
-GRUB_MOD_INIT(verifiers)
+void
+grub_verifiers_init (void)
 {
   grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);
 }
-
-GRUB_MOD_FINI(verifiers)
-{
-  grub_file_filter_unregister (GRUB_FILE_FILTER_VERIFY);
-}
diff --git a/include/grub/verify.h b/include/grub/verify.h
index ea0491433..cd129c398 100644
--- a/include/grub/verify.h
+++ b/include/grub/verify.h
@@ -64,7 +64,10 @@ struct grub_file_verifier
   grub_err_t (*verify_string) (char *str, enum grub_verify_string_type type);
 };
 
-extern struct grub_file_verifier *grub_file_verifiers;
+extern struct grub_file_verifier *EXPORT_VAR (grub_file_verifiers);
+
+extern void
+grub_verifiers_init (void);
 
 static inline void
 grub_verifier_register (struct grub_file_verifier *ver)
@@ -78,7 +81,7 @@ grub_verifier_unregister (struct grub_file_verifier *ver)
   grub_list_remove (GRUB_AS_LIST (ver));
 }
 
-grub_err_t
-grub_verify_string (char *str, enum grub_verify_string_type type);
+extern grub_err_t
+EXPORT_FUNC (grub_verify_string) (char *str, enum grub_verify_string_type type);
 
 #endif /* ! GRUB_VERIFY_HEADER */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 002/117] efi: Move the shim_lock verifier to the GRUB core
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 003/117] kern: Add lockdown support Daniel Kiper
                   ` (116 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Marco A Benatto <mbenatto@redhat.com>

Move the shim_lock verifier from its own module into the core image. The
Secure Boot lockdown mechanism has the intent to prevent the load of any
unsigned code or binary when Secure Boot is enabled.

The reason is that GRUB must be able to prevent executing untrusted code
if UEFI Secure Boot is enabled, without depending on external modules.

Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi                     |   9 +--
 grub-core/Makefile.core.def        |   6 --
 grub-core/commands/efi/shim_lock.c | 133 -------------------------------------
 grub-core/kern/efi/init.c          |   4 ++
 grub-core/kern/efi/sb.c            | 105 +++++++++++++++++++++++++++++
 include/grub/efi/sb.h              |   3 +
 6 files changed, 117 insertions(+), 143 deletions(-)
 delete mode 100644 grub-core/commands/efi/shim_lock.c

diff --git a/docs/grub.texi b/docs/grub.texi
index eeac9b2ce..e3de2a4dc 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5910,15 +5910,16 @@ secure boot chain.
 @section UEFI secure boot and shim support
 
 The GRUB, except the @command{chainloader} command, works with the UEFI secure
-boot and the shim. This functionality is provided by the shim_lock module. It
-is recommend to build in this and other required modules into the @file{core.img}.
+boot and the shim. This functionality is provided by the shim_lock verifier. It
+is built into the @file{core.img} and is registered if the UEFI secure boot is
+enabled.
+
 All modules not stored in the @file{core.img} and the ACPI tables for the
 @command{acpi} command have to be signed, e.g. using PGP. Additionally, the
 @command{iorw}, the @command{memrw} and the @command{wrmsr} commands are
 prohibited if the UEFI secure boot is enabled. This is done due to
 security reasons. All above mentioned requirements are enforced by the
-shim_lock module. And itself it is a persistent module which means that
-it cannot be unloaded if it was loaded into the memory.
+shim_lock verifier logic.
 
 @node Measured Boot
 @section Measuring boot components
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 0cecc3875..2b98fe1fc 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -945,12 +945,6 @@ module = {
 };
 
 module = {
-  name = shim_lock;
-  common = commands/efi/shim_lock.c;
-  enable = efi;
-};
-
-module = {
   name = hdparm;
   common = commands/hdparm.c;
   enable = pci;
diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c
deleted file mode 100644
index f7f3109d6..000000000
--- a/grub-core/commands/efi/shim_lock.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2017  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/>.
- *
- *  EFI shim lock verifier.
- */
-
-#include <grub/dl.h>
-#include <grub/efi/efi.h>
-#include <grub/efi/sb.h>
-#include <grub/err.h>
-#include <grub/file.h>
-#include <grub/misc.h>
-#include <grub/verify.h>
-
-GRUB_MOD_LICENSE ("GPLv3+");
-
-static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
-
-/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */
-static const char * const disabled_mods[] = {"iorw", "memrw", "wrmsr", NULL};
-
-static grub_err_t
-shim_lock_init (grub_file_t io, enum grub_file_type type,
-		void **context __attribute__ ((unused)),
-		enum grub_verify_flags *flags)
-{
-  const char *b, *e;
-  int i;
-
-  *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
-
-  switch (type & GRUB_FILE_TYPE_MASK)
-    {
-    case GRUB_FILE_TYPE_GRUB_MODULE:
-      /* Establish GRUB module name. */
-      b = grub_strrchr (io->name, '/');
-      e = grub_strrchr (io->name, '.');
-
-      b = b ? (b + 1) : io->name;
-      e = e ? e : io->name + grub_strlen (io->name);
-      e = (e > b) ? e : io->name + grub_strlen (io->name);
-
-      for (i = 0; disabled_mods[i]; i++)
-	if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen (e)))
-	  {
-	    grub_error (GRUB_ERR_ACCESS_DENIED,
-			N_("module cannot be loaded in UEFI secure boot mode: %s"),
-			io->name);
-	    return GRUB_ERR_ACCESS_DENIED;
-	  }
-
-      /* Fall through. */
-
-    case GRUB_FILE_TYPE_ACPI_TABLE:
-    case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
-      *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
-
-      return GRUB_ERR_NONE;
-
-    case GRUB_FILE_TYPE_LINUX_KERNEL:
-    case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
-    case GRUB_FILE_TYPE_BSD_KERNEL:
-    case GRUB_FILE_TYPE_XNU_KERNEL:
-    case GRUB_FILE_TYPE_PLAN9_KERNEL:
-      for (i = 0; disabled_mods[i]; i++)
-	if (grub_dl_get (disabled_mods[i]))
-	  {
-	    grub_error (GRUB_ERR_ACCESS_DENIED,
-			N_("cannot boot due to dangerous module in memory: %s"),
-			disabled_mods[i]);
-	    return GRUB_ERR_ACCESS_DENIED;
-	  }
-
-      *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
-
-      /* Fall through. */
-
-    default:
-      return GRUB_ERR_NONE;
-    }
-}
-
-static grub_err_t
-shim_lock_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size)
-{
-  grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
-
-  if (sl == NULL)
-    return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found"));
-
-  if (sl->verify (buf, size) != GRUB_EFI_SUCCESS)
-    return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature"));
-
-  return GRUB_ERR_NONE;
-}
-
-struct grub_file_verifier shim_lock =
-  {
-    .name = "shim_lock",
-    .init = shim_lock_init,
-    .write = shim_lock_write
-  };
-
-GRUB_MOD_INIT(shim_lock)
-{
-  grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
-
-  if (sl == NULL || grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
-    return;
-
-  grub_verifier_register (&shim_lock);
-
-  grub_dl_set_persistent (mod);
-}
-
-GRUB_MOD_FINI(shim_lock)
-{
-  grub_verifier_unregister (&shim_lock);
-}
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index 2c31847bf..b683bec5a 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -20,6 +20,7 @@
 #include <grub/efi/efi.h>
 #include <grub/efi/console.h>
 #include <grub/efi/disk.h>
+#include <grub/efi/sb.h>
 #include <grub/term.h>
 #include <grub/misc.h>
 #include <grub/env.h>
@@ -39,6 +40,9 @@ grub_efi_init (void)
   /* Initialize the memory management system.  */
   grub_efi_mm_init ();
 
+  /* Register the shim_lock verifier if UEFI Secure Boot is enabled. */
+  grub_shim_lock_verifier_setup ();
+
   efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
 	      0, 0, 0, NULL);
 
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 19658d962..8bd5e936d 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -22,9 +22,16 @@
 #include <grub/efi/pe32.h>
 #include <grub/efi/sb.h>
 #include <grub/err.h>
+#include <grub/file.h>
 #include <grub/i386/linux.h>
 #include <grub/mm.h>
 #include <grub/types.h>
+#include <grub/verify.h>
+
+static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
+
+/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */
+static const char * const disabled_mods[] = {"iorw", "memrw", "wrmsr", NULL};
 
 /*
  * Determine whether we're in secure boot mode.
@@ -107,3 +114,101 @@ grub_efi_get_secureboot (void)
 
   return secureboot;
 }
+
+static grub_err_t
+shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
+			 enum grub_file_type type,
+			 void **context __attribute__ ((unused)),
+			 enum grub_verify_flags *flags)
+{
+  const char *b, *e;
+  int i;
+
+  *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+
+  switch (type & GRUB_FILE_TYPE_MASK)
+    {
+    case GRUB_FILE_TYPE_GRUB_MODULE:
+      /* Establish GRUB module name. */
+      b = grub_strrchr (io->name, '/');
+      e = grub_strrchr (io->name, '.');
+
+      b = b ? (b + 1) : io->name;
+      e = e ? e : io->name + grub_strlen (io->name);
+      e = (e > b) ? e : io->name + grub_strlen (io->name);
+
+      for (i = 0; disabled_mods[i]; i++)
+	if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen (e)))
+	  {
+	    grub_error (GRUB_ERR_ACCESS_DENIED,
+			N_("module cannot be loaded in UEFI secure boot mode: %s"),
+			io->name);
+	    return GRUB_ERR_ACCESS_DENIED;
+	  }
+
+      /* Fall through. */
+
+    case GRUB_FILE_TYPE_ACPI_TABLE:
+    case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
+      *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+
+      return GRUB_ERR_NONE;
+
+    case GRUB_FILE_TYPE_LINUX_KERNEL:
+    case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
+    case GRUB_FILE_TYPE_BSD_KERNEL:
+    case GRUB_FILE_TYPE_XNU_KERNEL:
+    case GRUB_FILE_TYPE_PLAN9_KERNEL:
+      for (i = 0; disabled_mods[i]; i++)
+	if (grub_dl_get (disabled_mods[i]))
+	  {
+	    grub_error (GRUB_ERR_ACCESS_DENIED,
+			N_("cannot boot due to dangerous module in memory: %s"),
+			disabled_mods[i]);
+	    return GRUB_ERR_ACCESS_DENIED;
+	  }
+
+      *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
+
+      /* Fall through. */
+
+    default:
+      return GRUB_ERR_NONE;
+    }
+}
+
+static grub_err_t
+shim_lock_verifier_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size)
+{
+  grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
+
+  if (!sl)
+    return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found"));
+
+  if (sl->verify (buf, size) != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature"));
+
+  return GRUB_ERR_NONE;
+}
+
+struct grub_file_verifier shim_lock_verifier =
+  {
+    .name = "shim_lock_verifier",
+    .init = shim_lock_verifier_init,
+    .write = shim_lock_verifier_write
+  };
+
+void
+grub_shim_lock_verifier_setup (void)
+{
+  grub_efi_shim_lock_protocol_t *sl =
+    grub_efi_locate_protocol (&shim_lock_guid, 0);
+
+  if (!sl)
+    return;
+
+  if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+    return;
+
+  grub_verifier_register (&shim_lock_verifier);
+}
diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
index a33d985e3..30c4335bb 100644
--- a/include/grub/efi/sb.h
+++ b/include/grub/efi/sb.h
@@ -30,6 +30,9 @@
 #ifdef GRUB_MACHINE_EFI
 extern grub_uint8_t
 EXPORT_FUNC (grub_efi_get_secureboot) (void);
+
+extern void
+grub_shim_lock_verifier_setup (void);
 #else
 static inline grub_uint8_t
 grub_efi_get_secureboot (void)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 003/117] kern: Add lockdown support
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 002/117] efi: Move the shim_lock verifier to the GRUB core Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 004/117] kern/lockdown: Set a variable if the GRUB is locked down Daniel Kiper
                   ` (115 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

When the GRUB starts on a secure boot platform, some commands can be
used to subvert the protections provided by the verification mechanism and
could lead to booting untrusted system.

To prevent that situation, allow GRUB to be locked down. That way the code
may check if GRUB has been locked down and further restrict the commands
that are registered or what subset of their functionality could be used.

The lockdown support adds the following components:

* The grub_lockdown() function which can be used to lockdown GRUB if,
  e.g., UEFI Secure Boot is enabled.

* The grub_is_lockdown() function which can be used to check if the GRUB
  was locked down.

* A verifier that flags OS kernels, the GRUB modules, Device Trees and ACPI
  tables as GRUB_VERIFY_FLAGS_DEFER_AUTH to defer verification to other
  verifiers. These files are only successfully verified if another registered
  verifier returns success. Otherwise, the whole verification process fails.

  For example, PE/COFF binaries verification can be done by the shim_lock
  verifier which validates the signatures using the shim_lock protocol.
  However, the verification is not deferred directly to the shim_lock verifier.
  The shim_lock verifier is hooked into the verification process instead.

* A set of grub_{command,extcmd}_lockdown functions that can be used by
  code registering command handlers, to only register unsafe commands if
  the GRUB has not been locked down.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 conf/Makefile.common        |  2 ++
 docs/grub-dev.texi          | 27 +++++++++++++++
 docs/grub.texi              |  8 +++++
 grub-core/Makefile.am       |  5 ++-
 grub-core/Makefile.core.def |  1 +
 grub-core/commands/extcmd.c | 23 +++++++++++++
 grub-core/kern/command.c    | 24 ++++++++++++++
 grub-core/kern/lockdown.c   | 80 +++++++++++++++++++++++++++++++++++++++++++++
 include/grub/command.h      |  5 +++
 include/grub/extcmd.h       |  7 ++++
 include/grub/lockdown.h     | 44 +++++++++++++++++++++++++
 11 files changed, 225 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/kern/lockdown.c
 create mode 100644 include/grub/lockdown.h

diff --git a/conf/Makefile.common b/conf/Makefile.common
index 6cd71cbb2..2a1a886f6 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -84,7 +84,9 @@ CPPFLAGS_PARTTOOL_LIST = -Dgrub_parttool_register=PARTTOOL_LIST_MARKER
 CPPFLAGS_TERMINAL_LIST = '-Dgrub_term_register_input(...)=INPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)'
+CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_lockdown(...)=COMMAND_LOCKDOWN_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_LIST_MARKER(__VA_ARGS__)'
+CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd_lockdown(...)=EXTCOMMAND_LOCKDOWN_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_p1(...)=P1COMMAND_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_FDT_LIST := '-Dgrub_fdtbus_register(...)=FDT_DRIVER_LIST_MARKER(__VA_ARGS__)'
 CPPFLAGS_MARKER = $(CPPFLAGS_FS_LIST) $(CPPFLAGS_VIDEO_LIST) \
diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
index 24d17b8ec..a834b3a9c 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -86,6 +86,7 @@ This edition documents version @value{VERSION}.
 * PFF2 Font File Format::
 * Graphical Menu Software Design::
 * Verifiers framework::
+* Lockdown framework::
 * Copying This Manual::         Copying This Manual
 * Index::
 @end menu
@@ -2123,6 +2124,32 @@ Optionally at the end of the file @samp{fini}, if it exists, is called with just
 the context. If you return no error during any of @samp{init}, @samp{write} and
 @samp{fini} then the file is considered as having succeded verification.
 
+@node Lockdown framework
+@chapter Lockdown framework
+
+The GRUB can be locked down, which is a restricted mode where some operations
+are not allowed. For instance, some commands cannot be used when the GRUB is
+locked down.
+
+The function
+@code{grub_lockdown()} is used to lockdown GRUB and the function
+@code{grub_is_lockdown()} function can be used to check whether lockdown is
+enabled or not. When enabled, the function returns @samp{GRUB_LOCKDOWN_ENABLED}
+and @samp{GRUB_LOCKDOWN_DISABLED} when is not enabled.
+
+The following functions can be used to register the commands that can only be
+used when lockdown is disabled:
+
+@itemize
+
+@item @code{grub_cmd_lockdown()} registers command which should not run when the
+GRUB is in lockdown mode.
+
+@item @code{grub_cmd_lockdown()} registers extended command which should not run
+when the GRUB is in lockdown mode.
+
+@end itemize
+
 @node Copying This Manual
 @appendix Copying This Manual
 
diff --git a/docs/grub.texi b/docs/grub.texi
index e3de2a4dc..fd3c78054 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5749,6 +5749,7 @@ environment variables and commands are listed in the same order.
 * Using digital signatures::         Booting digitally signed code
 * UEFI secure boot and shim::        Booting digitally signed PE files
 * Measured Boot::                    Measuring boot components
+* Lockdown::                         Lockdown when booting on a secure setup
 @end menu
 
 @node Authentication and authorisation
@@ -5958,6 +5959,13 @@ into @file{core.img} in order to avoid a potential gap in measurement between
 
 Measured boot is currently only supported on EFI platforms.
 
+@node Lockdown
+@section Lockdown when booting on a secure setup
+
+The GRUB can be locked down when booted on a secure boot environment, for example
+if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will
+be restricted and some operations/commands cannot be executed.
+
 @node Platform limitations
 @chapter Platform limitations
 
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index cc6fc7dfa..30e23ada2 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -80,6 +80,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lockdown.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
 if COND_emu
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h
@@ -377,8 +378,10 @@ command.lst: $(MARKER_FILES)
 	  b=`basename $$pp .marker`; \
 	  sed -n \
 	    -e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
+	    -e "/EXTCOMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
 	    -e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-	    -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
+	    -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" \
+	    -e "/COMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
 	done) | sort -u > $@
 platform_DATA += command.lst
 CLEANFILES += command.lst
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2b98fe1fc..1f450a98f 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -205,6 +205,7 @@ kernel = {
   efi = kern/acpi.c;
   efi = kern/efi/acpi.c;
   efi = kern/efi/sb.c;
+  efi = kern/lockdown.c;
   i386_coreboot = kern/i386/pc/acpi.c;
   i386_multiboot = kern/i386/pc/acpi.c;
   i386_coreboot = kern/acpi.c;
diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c
index 69574e2b0..90a5ca24a 100644
--- a/grub-core/commands/extcmd.c
+++ b/grub-core/commands/extcmd.c
@@ -19,6 +19,7 @@
 
 #include <grub/mm.h>
 #include <grub/list.h>
+#include <grub/lockdown.h>
 #include <grub/misc.h>
 #include <grub/extcmd.h>
 #include <grub/script_sh.h>
@@ -110,6 +111,28 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func,
 				    summary, description, parser, 1);
 }
 
+static grub_err_t
+grub_extcmd_lockdown (grub_extcmd_context_t ctxt __attribute__ ((unused)),
+                      int argc __attribute__ ((unused)),
+                      char **argv __attribute__ ((unused)))
+{
+  return grub_error (GRUB_ERR_ACCESS_DENIED,
+                     N_("%s: the command is not allowed when lockdown is enforced"),
+                     ctxt->extcmd->cmd->name);
+}
+
+grub_extcmd_t
+grub_register_extcmd_lockdown (const char *name, grub_extcmd_func_t func,
+                               grub_command_flags_t flags, const char *summary,
+                               const char *description,
+                               const struct grub_arg_option *parser)
+{
+  if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
+    func = grub_extcmd_lockdown;
+
+  return grub_register_extcmd (name, func, flags, summary, description, parser);
+}
+
 void
 grub_unregister_extcmd (grub_extcmd_t ext)
 {
diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c
index acd721879..4aabcd4b5 100644
--- a/grub-core/kern/command.c
+++ b/grub-core/kern/command.c
@@ -17,6 +17,7 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <grub/lockdown.h>
 #include <grub/mm.h>
 #include <grub/command.h>
 
@@ -77,6 +78,29 @@ grub_register_command_prio (const char *name,
   return cmd;
 }
 
+static grub_err_t
+grub_cmd_lockdown (grub_command_t cmd __attribute__ ((unused)),
+                   int argc __attribute__ ((unused)),
+                   char **argv __attribute__ ((unused)))
+
+{
+  return grub_error (GRUB_ERR_ACCESS_DENIED,
+                     N_("%s: the command is not allowed when lockdown is enforced"),
+                     cmd->name);
+}
+
+grub_command_t
+grub_register_command_lockdown (const char *name,
+                                grub_command_func_t func,
+                                const char *summary,
+                                const char *description)
+{
+  if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
+    func = grub_cmd_lockdown;
+
+  return grub_register_command_prio (name, func, summary, description, 0);
+}
+
 void
 grub_unregister_command (grub_command_t cmd)
 {
diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
new file mode 100644
index 000000000..1e56c0b80
--- /dev/null
+++ b/grub-core/kern/lockdown.c
@@ -0,0 +1,80 @@
+/*
+ *  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/>.
+ *
+ */
+
+#include <grub/dl.h>
+#include <grub/file.h>
+#include <grub/lockdown.h>
+#include <grub/verify.h>
+
+static int lockdown = GRUB_LOCKDOWN_DISABLED;
+
+static grub_err_t
+lockdown_verifier_init (grub_file_t io __attribute__ ((unused)),
+                    enum grub_file_type type,
+                    void **context __attribute__ ((unused)),
+                    enum grub_verify_flags *flags)
+{
+  *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+
+  switch (type & GRUB_FILE_TYPE_MASK)
+    {
+    case GRUB_FILE_TYPE_GRUB_MODULE:
+    case GRUB_FILE_TYPE_LINUX_KERNEL:
+    case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
+    case GRUB_FILE_TYPE_XEN_HYPERVISOR:
+    case GRUB_FILE_TYPE_BSD_KERNEL:
+    case GRUB_FILE_TYPE_XNU_KERNEL:
+    case GRUB_FILE_TYPE_PLAN9_KERNEL:
+    case GRUB_FILE_TYPE_NTLDR:
+    case GRUB_FILE_TYPE_TRUECRYPT:
+    case GRUB_FILE_TYPE_FREEDOS:
+    case GRUB_FILE_TYPE_PXECHAINLOADER:
+    case GRUB_FILE_TYPE_PCCHAINLOADER:
+    case GRUB_FILE_TYPE_COREBOOT_CHAINLOADER:
+    case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
+    case GRUB_FILE_TYPE_ACPI_TABLE:
+    case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
+      *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+
+      /* Fall through. */
+
+    default:
+      return GRUB_ERR_NONE;
+    }
+}
+
+struct grub_file_verifier lockdown_verifier =
+  {
+    .name = "lockdown_verifier",
+    .init = lockdown_verifier_init,
+  };
+
+void
+grub_lockdown (void)
+{
+  lockdown = GRUB_LOCKDOWN_ENABLED;
+
+  grub_verifier_register (&lockdown_verifier);
+}
+
+int
+grub_is_lockdown (void)
+{
+  return lockdown;
+}
diff --git a/include/grub/command.h b/include/grub/command.h
index eee4e847e..2a6f7f846 100644
--- a/include/grub/command.h
+++ b/include/grub/command.h
@@ -86,6 +86,11 @@ EXPORT_FUNC(grub_register_command_prio) (const char *name,
 					 const char *summary,
 					 const char *description,
 					 int prio);
+grub_command_t
+EXPORT_FUNC(grub_register_command_lockdown) (const char *name,
+                                             grub_command_func_t func,
+                                             const char *summary,
+                                             const char *description);
 void EXPORT_FUNC(grub_unregister_command) (grub_command_t cmd);
 
 static inline grub_command_t
diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h
index 19fe59266..fe9248b8b 100644
--- a/include/grub/extcmd.h
+++ b/include/grub/extcmd.h
@@ -62,6 +62,13 @@ grub_extcmd_t EXPORT_FUNC(grub_register_extcmd) (const char *name,
 						 const char *description,
 						 const struct grub_arg_option *parser);
 
+grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_lockdown) (const char *name,
+                                                          grub_extcmd_func_t func,
+                                                          grub_command_flags_t flags,
+                                                          const char *summary,
+                                                          const char *description,
+                                                          const struct grub_arg_option *parser);
+
 grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_prio) (const char *name,
 						      grub_extcmd_func_t func,
 						      grub_command_flags_t flags,
diff --git a/include/grub/lockdown.h b/include/grub/lockdown.h
new file mode 100644
index 000000000..40531fa82
--- /dev/null
+++ b/include/grub/lockdown.h
@@ -0,0 +1,44 @@
+/*
+ *  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/>.
+ */
+
+#ifndef GRUB_LOCKDOWN_H
+#define GRUB_LOCKDOWN_H 1
+
+#include <grub/symbol.h>
+
+#define GRUB_LOCKDOWN_DISABLED       0
+#define GRUB_LOCKDOWN_ENABLED        1
+
+#ifdef GRUB_MACHINE_EFI
+extern void
+EXPORT_FUNC (grub_lockdown) (void);
+extern int
+EXPORT_FUNC (grub_is_lockdown) (void);
+#else
+static inline void
+grub_lockdown (void)
+{
+}
+
+static inline int
+grub_is_lockdown (void)
+{
+  return GRUB_LOCKDOWN_DISABLED;
+}
+#endif
+#endif /* ! GRUB_LOCKDOWN_H */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 004/117] kern/lockdown: Set a variable if the GRUB is locked down
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (2 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 003/117] kern: Add lockdown support Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 005/117] efi: Lockdown the GRUB when the UEFI Secure Boot is enabled Daniel Kiper
                   ` (114 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

It may be useful for scripts to determine whether the GRUB is locked
down or not. Add the lockdown variable which is set to "y" when the GRUB
is locked down.

Suggested-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi            | 3 +++
 grub-core/kern/lockdown.c | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index fd3c78054..4c980d356 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5966,6 +5966,9 @@ The GRUB can be locked down when booted on a secure boot environment, for exampl
 if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will
 be restricted and some operations/commands cannot be executed.
 
+The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down.
+Otherwise it does not exit.
+
 @node Platform limitations
 @chapter Platform limitations
 
diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
index 1e56c0b80..0bc70fd42 100644
--- a/grub-core/kern/lockdown.c
+++ b/grub-core/kern/lockdown.c
@@ -18,6 +18,7 @@
  */
 
 #include <grub/dl.h>
+#include <grub/env.h>
 #include <grub/file.h>
 #include <grub/lockdown.h>
 #include <grub/verify.h>
@@ -71,6 +72,9 @@ grub_lockdown (void)
   lockdown = GRUB_LOCKDOWN_ENABLED;
 
   grub_verifier_register (&lockdown_verifier);
+
+  grub_env_set ("lockdown", "y");
+  grub_env_export ("lockdown");
 }
 
 int
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 005/117] efi: Lockdown the GRUB when the UEFI Secure Boot is enabled
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (3 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 004/117] kern/lockdown: Set a variable if the GRUB is locked down Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 006/117] efi: Use grub_is_lockdown() instead of hardcoding a disabled modules list Daniel Kiper
                   ` (113 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

If the UEFI Secure Boot is enabled then the GRUB must be locked down
to prevent executing code that can potentially be used to subvert its
verification mechanisms.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/efi/init.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index b683bec5a..133346509 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -21,6 +21,7 @@
 #include <grub/efi/console.h>
 #include <grub/efi/disk.h>
 #include <grub/efi/sb.h>
+#include <grub/lockdown.h>
 #include <grub/term.h>
 #include <grub/misc.h>
 #include <grub/env.h>
@@ -40,8 +41,15 @@ grub_efi_init (void)
   /* Initialize the memory management system.  */
   grub_efi_mm_init ();
 
-  /* Register the shim_lock verifier if UEFI Secure Boot is enabled. */
-  grub_shim_lock_verifier_setup ();
+  /*
+   * Lockdown the GRUB and register the shim_lock verifier
+   * if the UEFI Secure Boot is enabled.
+   */
+  if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+    {
+      grub_lockdown ();
+      grub_shim_lock_verifier_setup ();
+    }
 
   efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
 	      0, 0, 0, NULL);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 006/117] efi: Use grub_is_lockdown() instead of hardcoding a disabled modules list
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (4 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 005/117] efi: Lockdown the GRUB when the UEFI Secure Boot is enabled Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 007/117] acpi: Don't register the acpi command when locked down Daniel Kiper
                   ` (112 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

Now the GRUB can check if it has been locked down and this can be used to
prevent executing commands that can be utilized to circumvent the UEFI
Secure Boot mechanisms. So, instead of hardcoding a list of modules that
have to be disabled, prevent the usage of commands that can be dangerous.

This not only allows the commands to be disabled on other platforms, but
also properly separate the concerns. Since the shim_lock verifier logic
should be only about preventing to run untrusted binaries and not about
defining these kind of policies.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi                  | 15 +++++++++------
 grub-core/commands/i386/wrmsr.c |  5 +++--
 grub-core/commands/iorw.c       | 19 ++++++++++---------
 grub-core/commands/memrw.c      | 19 ++++++++++---------
 grub-core/kern/efi/sb.c         | 41 -----------------------------------------
 5 files changed, 32 insertions(+), 67 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 4c980d356..c3e015d4f 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5405,6 +5405,9 @@ only applies to the particular cpu/core/thread that runs the command.
 Also, if you specify a reserved or unimplemented MSR address, it will
 cause a general protection exception (which is not currently being handled)
 and the system will reboot.
+
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+      This is done to prevent subverting various security mechanisms.
 @end deffn
 
 @node xen_hypervisor
@@ -5915,12 +5918,12 @@ boot and the shim. This functionality is provided by the shim_lock verifier. It
 is built into the @file{core.img} and is registered if the UEFI secure boot is
 enabled.
 
-All modules not stored in the @file{core.img} and the ACPI tables for the
-@command{acpi} command have to be signed, e.g. using PGP. Additionally, the
-@command{iorw}, the @command{memrw} and the @command{wrmsr} commands are
-prohibited if the UEFI secure boot is enabled. This is done due to
-security reasons. All above mentioned requirements are enforced by the
-shim_lock verifier logic.
+All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables,
+Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands
+that can be used to subvert the UEFI secure boot mechanism, such as @command{iorw}
+and @command{memrw} will not be available when the UEFI secure boot is enabled.
+This is done for security reasons and are enforced by the GRUB Lockdown mechanism
+(@pxref{Lockdown}).
 
 @node Measured Boot
 @section Measuring boot components
diff --git a/grub-core/commands/i386/wrmsr.c b/grub-core/commands/i386/wrmsr.c
index fa76f5aed..1b143b888 100644
--- a/grub-core/commands/i386/wrmsr.c
+++ b/grub-core/commands/i386/wrmsr.c
@@ -24,6 +24,7 @@
 #include <grub/env.h>
 #include <grub/command.h>
 #include <grub/extcmd.h>
+#include <grub/lockdown.h>
 #include <grub/i18n.h>
 #include <grub/i386/cpuid.h>
 #include <grub/i386/wrmsr.h>
@@ -83,8 +84,8 @@ grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char
 
 GRUB_MOD_INIT(wrmsr)
 {
-  cmd_write = grub_register_command ("wrmsr", grub_cmd_msr_write, N_("ADDR VALUE"),
-				     N_("Write a value to a CPU model specific register."));
+  cmd_write = grub_register_command_lockdown ("wrmsr", grub_cmd_msr_write, N_("ADDR VALUE"),
+                                              N_("Write a value to a CPU model specific register."));
 }
 
 GRUB_MOD_FINI(wrmsr)
diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c
index a0c164e54..584baec8f 100644
--- a/grub-core/commands/iorw.c
+++ b/grub-core/commands/iorw.c
@@ -23,6 +23,7 @@
 #include <grub/env.h>
 #include <grub/cpu/io.h>
 #include <grub/i18n.h>
+#include <grub/lockdown.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -131,17 +132,17 @@ GRUB_MOD_INIT(memrw)
 			  N_("PORT"), N_("Read 32-bit value from PORT."),
 			  options);
   cmd_write_byte =
-    grub_register_command ("outb", grub_cmd_write,
-			   N_("PORT VALUE [MASK]"),
-			   N_("Write 8-bit VALUE to PORT."));
+    grub_register_command_lockdown ("outb", grub_cmd_write,
+                                    N_("PORT VALUE [MASK]"),
+                                    N_("Write 8-bit VALUE to PORT."));
   cmd_write_word =
-    grub_register_command ("outw", grub_cmd_write,
-			   N_("PORT VALUE [MASK]"),
-			   N_("Write 16-bit VALUE to PORT."));
+    grub_register_command_lockdown ("outw", grub_cmd_write,
+                                    N_("PORT VALUE [MASK]"),
+                                    N_("Write 16-bit VALUE to PORT."));
   cmd_write_dword =
-    grub_register_command ("outl", grub_cmd_write,
-			   N_("ADDR VALUE [MASK]"),
-			   N_("Write 32-bit VALUE to PORT."));
+    grub_register_command_lockdown ("outl", grub_cmd_write,
+                                    N_("ADDR VALUE [MASK]"),
+                                    N_("Write 32-bit VALUE to PORT."));
 }
 
 GRUB_MOD_FINI(memrw)
diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c
index 98769eadb..d401a6db0 100644
--- a/grub-core/commands/memrw.c
+++ b/grub-core/commands/memrw.c
@@ -22,6 +22,7 @@
 #include <grub/extcmd.h>
 #include <grub/env.h>
 #include <grub/i18n.h>
+#include <grub/lockdown.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -133,17 +134,17 @@ GRUB_MOD_INIT(memrw)
 			  N_("ADDR"), N_("Read 32-bit value from ADDR."),
 			  options);
   cmd_write_byte =
-    grub_register_command ("write_byte", grub_cmd_write,
-			   N_("ADDR VALUE [MASK]"),
-			   N_("Write 8-bit VALUE to ADDR."));
+    grub_register_command_lockdown ("write_byte", grub_cmd_write,
+                                    N_("ADDR VALUE [MASK]"),
+                                    N_("Write 8-bit VALUE to ADDR."));
   cmd_write_word =
-    grub_register_command ("write_word", grub_cmd_write,
-			   N_("ADDR VALUE [MASK]"),
-			   N_("Write 16-bit VALUE to ADDR."));
+    grub_register_command_lockdown ("write_word", grub_cmd_write,
+                                    N_("ADDR VALUE [MASK]"),
+                                    N_("Write 16-bit VALUE to ADDR."));
   cmd_write_dword =
-    grub_register_command ("write_dword", grub_cmd_write,
-			   N_("ADDR VALUE [MASK]"),
-			   N_("Write 32-bit VALUE to ADDR."));
+    grub_register_command_lockdown ("write_dword", grub_cmd_write,
+                                    N_("ADDR VALUE [MASK]"),
+                                    N_("Write 32-bit VALUE to ADDR."));
 }
 
 GRUB_MOD_FINI(memrw)
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 8bd5e936d..5d7210a82 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -30,9 +30,6 @@
 
 static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
 
-/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */
-static const char * const disabled_mods[] = {"iorw", "memrw", "wrmsr", NULL};
-
 /*
  * Determine whether we're in secure boot mode.
  *
@@ -121,53 +118,15 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
 			 void **context __attribute__ ((unused)),
 			 enum grub_verify_flags *flags)
 {
-  const char *b, *e;
-  int i;
-
   *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
 
   switch (type & GRUB_FILE_TYPE_MASK)
     {
-    case GRUB_FILE_TYPE_GRUB_MODULE:
-      /* Establish GRUB module name. */
-      b = grub_strrchr (io->name, '/');
-      e = grub_strrchr (io->name, '.');
-
-      b = b ? (b + 1) : io->name;
-      e = e ? e : io->name + grub_strlen (io->name);
-      e = (e > b) ? e : io->name + grub_strlen (io->name);
-
-      for (i = 0; disabled_mods[i]; i++)
-	if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen (e)))
-	  {
-	    grub_error (GRUB_ERR_ACCESS_DENIED,
-			N_("module cannot be loaded in UEFI secure boot mode: %s"),
-			io->name);
-	    return GRUB_ERR_ACCESS_DENIED;
-	  }
-
-      /* Fall through. */
-
-    case GRUB_FILE_TYPE_ACPI_TABLE:
-    case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
-      *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
-
-      return GRUB_ERR_NONE;
-
     case GRUB_FILE_TYPE_LINUX_KERNEL:
     case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
     case GRUB_FILE_TYPE_BSD_KERNEL:
     case GRUB_FILE_TYPE_XNU_KERNEL:
     case GRUB_FILE_TYPE_PLAN9_KERNEL:
-      for (i = 0; disabled_mods[i]; i++)
-	if (grub_dl_get (disabled_mods[i]))
-	  {
-	    grub_error (GRUB_ERR_ACCESS_DENIED,
-			N_("cannot boot due to dangerous module in memory: %s"),
-			disabled_mods[i]);
-	    return GRUB_ERR_ACCESS_DENIED;
-	  }
-
       *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
 
       /* Fall through. */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 007/117] acpi: Don't register the acpi command when locked down
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (5 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 006/117] efi: Use grub_is_lockdown() instead of hardcoding a disabled modules list Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 008/117] mmap: Don't register cutmem and badram commands when lockdown is enforced Daniel Kiper
                   ` (111 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The command is not allowed when lockdown is enforced. Otherwise an
attacker can instruct the GRUB to load an SSDT table to overwrite
the kernel lockdown configuration and later load and execute
unsigned code.

Fixes: CVE-2020-14372

Reported-by: Máté Kukri <km@mkukri.xyz>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi            |  5 +++++
 grub-core/commands/acpi.c | 15 ++++++++-------
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index c3e015d4f..4ce31c2d4 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4074,6 +4074,11 @@ Normally, this command will replace the Root System Description Pointer
 (RSDP) in the Extended BIOS Data Area to point to the new tables. If the
 @option{--no-ebda} option is used, the new tables will be known only to
 GRUB, but may be used by GRUB's EFI emulation.
+
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+      Otherwise an attacker can instruct the GRUB to load an SSDT table to
+      overwrite the kernel lockdown configuration and later load and execute
+      unsigned code.
 @end deffn
 
 
diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c
index 5a1499aa0..1215f2a62 100644
--- a/grub-core/commands/acpi.c
+++ b/grub-core/commands/acpi.c
@@ -27,6 +27,7 @@
 #include <grub/mm.h>
 #include <grub/memory.h>
 #include <grub/i18n.h>
+#include <grub/lockdown.h>
 
 #ifdef GRUB_MACHINE_EFI
 #include <grub/efi/efi.h>
@@ -775,13 +776,13 @@ static grub_extcmd_t cmd;
 
 GRUB_MOD_INIT(acpi)
 {
-  cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0,
-			      N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
-			      "--load-only=TABLE1,TABLE2] FILE1"
-			      " [FILE2] [...]"),
-			      N_("Load host ACPI tables and tables "
-			      "specified by arguments."),
-			      options);
+  cmd = grub_register_extcmd_lockdown ("acpi", grub_cmd_acpi, 0,
+                                       N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
+                                          "--load-only=TABLE1,TABLE2] FILE1"
+                                          " [FILE2] [...]"),
+                                       N_("Load host ACPI tables and tables "
+                                          "specified by arguments."),
+                                       options);
 }
 
 GRUB_MOD_FINI(acpi)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 008/117] mmap: Don't register cutmem and badram commands when lockdown is enforced
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (6 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 007/117] acpi: Don't register the acpi command when locked down Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 009/117] commands: Restrict commands that can load BIOS or DT blobs when locked down Daniel Kiper
                   ` (110 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The cutmem and badram commands can be used to remove EFI memory regions
and potentially disable the UEFI Secure Boot. Prevent the commands to be
registered if the GRUB is locked down.

Fixes: CVE-2020-27779

Reported-by: Teddy Reed <teddy.reed@gmail.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi        |  4 ++++
 grub-core/mmap/mmap.c | 13 +++++++------
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 4ce31c2d4..5dbb02f1c 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4139,6 +4139,10 @@ this page is to be filtered.  This syntax makes it easy to represent patterns
 that are often result of memory damage, due to physical distribution of memory
 cells.
 
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+      This prevents removing EFI memory regions to potentially subvert the
+      security mechanisms provided by the UEFI secure boot.
+
 @node blocklist
 @subsection blocklist
 
diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c
index 64684c23d..3cae68364 100644
--- a/grub-core/mmap/mmap.c
+++ b/grub-core/mmap/mmap.c
@@ -20,6 +20,7 @@
 #include <grub/memory.h>
 #include <grub/machine/memory.h>
 #include <grub/err.h>
+#include <grub/lockdown.h>
 #include <grub/misc.h>
 #include <grub/mm.h>
 #include <grub/command.h>
@@ -534,12 +535,12 @@ static grub_command_t cmd, cmd_cut;
 \f
 GRUB_MOD_INIT(mmap)
 {
-  cmd = grub_register_command ("badram", grub_cmd_badram,
-			       N_("ADDR1,MASK1[,ADDR2,MASK2[,...]]"),
-			       N_("Declare memory regions as faulty (badram)."));
-  cmd_cut = grub_register_command ("cutmem", grub_cmd_cutmem,
-				   N_("FROM[K|M|G] TO[K|M|G]"),
-				   N_("Remove any memory regions in specified range."));
+  cmd = grub_register_command_lockdown ("badram", grub_cmd_badram,
+                                        N_("ADDR1,MASK1[,ADDR2,MASK2[,...]]"),
+                                        N_("Declare memory regions as faulty (badram)."));
+  cmd_cut = grub_register_command_lockdown ("cutmem", grub_cmd_cutmem,
+                                            N_("FROM[K|M|G] TO[K|M|G]"),
+                                            N_("Remove any memory regions in specified range."));
 
 }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 009/117] commands: Restrict commands that can load BIOS or DT blobs when locked down
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (7 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 008/117] mmap: Don't register cutmem and badram commands when lockdown is enforced Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 010/117] commands/setpci: Restrict setpci command " Daniel Kiper
                   ` (109 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

There are some more commands that should be restricted when the GRUB is
locked down. Following is the list of commands and reasons to restrict:

  * fakebios:   creates BIOS-like structures for backward compatibility with
                existing OSes. This should not be allowed when locked down.

  * loadbios:   reads a BIOS dump from storage and loads it. This action
                should not be allowed when locked down.

  * devicetree: loads a Device Tree blob and passes it to the OS. It replaces
                any Device Tree provided by the firmware. This also should
                not be allowed when locked down.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi                    |  3 +++
 grub-core/commands/efi/loadbios.c | 14 +++++++-------
 grub-core/loader/arm/linux.c      |  6 +++---
 grub-core/loader/efi/fdt.c        |  4 ++--
 4 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 5dbb02f1c..91666781b 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4324,6 +4324,9 @@ hour, minute, and second unchanged.
 Load a device tree blob (.dtb) from a filesystem, for later use by a Linux
 kernel. Does not perform merging with any device tree supplied by firmware,
 but rather replaces it completely.
+
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+      This is done to prevent subverting various security mechanisms.
 @end deffn
 
 @node distrust
diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c
index d41d521a4..5c7725f8b 100644
--- a/grub-core/commands/efi/loadbios.c
+++ b/grub-core/commands/efi/loadbios.c
@@ -205,14 +205,14 @@ static grub_command_t cmd_fakebios, cmd_loadbios;
 
 GRUB_MOD_INIT(loadbios)
 {
-  cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
-					0, N_("Create BIOS-like structures for"
-					      " backward compatibility with"
-					      " existing OS."));
+  cmd_fakebios = grub_register_command_lockdown ("fakebios", grub_cmd_fakebios,
+						 0, N_("Create BIOS-like structures for"
+						       " backward compatibility with"
+						       " existing OS."));
 
-  cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
-					N_("BIOS_DUMP [INT10_DUMP]"),
-					N_("Load BIOS dump."));
+  cmd_loadbios = grub_register_command_lockdown ("loadbios", grub_cmd_loadbios,
+						 N_("BIOS_DUMP [INT10_DUMP]"),
+						 N_("Load BIOS dump."));
 }
 
 GRUB_MOD_FINI(loadbios)
diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
index d70c17486..ed23dc71e 100644
--- a/grub-core/loader/arm/linux.c
+++ b/grub-core/loader/arm/linux.c
@@ -493,9 +493,9 @@ GRUB_MOD_INIT (linux)
 				     0, N_("Load Linux."));
   cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
 				      0, N_("Load initrd."));
-  cmd_devicetree = grub_register_command ("devicetree", grub_cmd_devicetree,
-					  /* TRANSLATORS: DTB stands for device tree blob.  */
-					  0, N_("Load DTB file."));
+  cmd_devicetree = grub_register_command_lockdown ("devicetree", grub_cmd_devicetree,
+						   /* TRANSLATORS: DTB stands for device tree blob. */
+						   0, N_("Load DTB file."));
   my_mod = mod;
   current_fdt = (const void *) grub_arm_firmware_get_boot_data ();
   machine_type = grub_arm_firmware_get_machine_type ();
diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
index ee9c5592c..003d07cd8 100644
--- a/grub-core/loader/efi/fdt.c
+++ b/grub-core/loader/efi/fdt.c
@@ -165,8 +165,8 @@ static grub_command_t cmd_devicetree;
 GRUB_MOD_INIT (fdt)
 {
   cmd_devicetree =
-    grub_register_command ("devicetree", grub_cmd_devicetree, 0,
-			   N_("Load DTB file."));
+    grub_register_command_lockdown ("devicetree", grub_cmd_devicetree, 0,
+				    N_("Load DTB file."));
 }
 
 GRUB_MOD_FINI (fdt)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 010/117] commands/setpci: Restrict setpci command when locked down
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (8 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 009/117] commands: Restrict commands that can load BIOS or DT blobs when locked down Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 011/117] commands/hdparm: Restrict hdparm " Daniel Kiper
                   ` (108 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

This command can set PCI devices register values, which makes it dangerous
in a locked down configuration. Restrict it so can't be used on this setup.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/setpci.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c
index e966af080..8a0c91f02 100644
--- a/grub-core/commands/setpci.c
+++ b/grub-core/commands/setpci.c
@@ -328,10 +328,10 @@ static grub_extcmd_t cmd;
 
 GRUB_MOD_INIT(setpci)
 {
-  cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0,
-			      N_("[-s POSITION] [-d DEVICE] [-v VAR] "
-				 "REGISTER[=VALUE[:MASK]]"),
-			      N_("Manipulate PCI devices."), options);
+  cmd = grub_register_extcmd_lockdown ("setpci", grub_cmd_setpci, 0,
+				       N_("[-s POSITION] [-d DEVICE] [-v VAR] "
+					  "REGISTER[=VALUE[:MASK]]"),
+				       N_("Manipulate PCI devices."), options);
 }
 
 GRUB_MOD_FINI(setpci)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 011/117] commands/hdparm: Restrict hdparm command when locked down
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (9 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 010/117] commands/setpci: Restrict setpci command " Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 012/117] gdb: Restrict GDB access " Daniel Kiper
                   ` (107 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The command can be used to get/set ATA disk parameters. Some of these can
be dangerous since change the disk behavior. Restrict it when locked down.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/hdparm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c
index d3fa9661e..2e2319e64 100644
--- a/grub-core/commands/hdparm.c
+++ b/grub-core/commands/hdparm.c
@@ -436,9 +436,9 @@ static grub_extcmd_t cmd;
 
 GRUB_MOD_INIT(hdparm)
 {
-  cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0,
-			      N_("[OPTIONS] DISK"),
-			      N_("Get/set ATA disk parameters."), options);
+  cmd = grub_register_extcmd_lockdown ("hdparm", grub_cmd_hdparm, 0,
+				       N_("[OPTIONS] DISK"),
+				       N_("Get/set ATA disk parameters."), options);
 }
 
 GRUB_MOD_FINI(hdparm)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 012/117] gdb: Restrict GDB access when locked down
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (10 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 011/117] commands/hdparm: Restrict hdparm " Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 013/117] loader/xnu: Don't allow loading extension and packages " Daniel Kiper
                   ` (106 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The gdbstub* commands allow to start and control a GDB stub running on
local host that can be used to connect from a remote debugger. Restrict
this functionality when the GRUB is locked down.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/gdb/gdb.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/grub-core/gdb/gdb.c b/grub-core/gdb/gdb.c
index 847a1e1e3..1818cb6f8 100644
--- a/grub-core/gdb/gdb.c
+++ b/grub-core/gdb/gdb.c
@@ -75,20 +75,24 @@ static grub_command_t cmd, cmd_stop, cmd_break;
 GRUB_MOD_INIT (gdb)
 {
   grub_gdb_idtinit ();
-  cmd = grub_register_command ("gdbstub", grub_cmd_gdbstub,
-			       N_("PORT"), 
-			       /* TRANSLATORS: GDB stub is a small part of
-				  GDB functionality running on local host
-				  which allows remote debugger to
-				  connect to it.  */
-			       N_("Start GDB stub on given port"));
-  cmd_break = grub_register_command ("gdbstub_break", grub_cmd_gdb_break,
-				     /* TRANSLATORS: this refers to triggering
-					a breakpoint so that the user will land
-					into GDB.  */
-				     0, N_("Break into GDB"));
-  cmd_stop = grub_register_command ("gdbstub_stop", grub_cmd_gdbstop,
-				    0, N_("Stop GDB stub"));
+  cmd = grub_register_command_lockdown ("gdbstub", grub_cmd_gdbstub,
+					N_("PORT"),
+					/*
+					 * TRANSLATORS: GDB stub is a small part of
+					 * GDB functionality running on local host
+					 * which allows remote debugger to
+					 * connect to it.
+					 */
+					N_("Start GDB stub on given port"));
+  cmd_break = grub_register_command_lockdown ("gdbstub_break", grub_cmd_gdb_break,
+					      /*
+					       * TRANSLATORS: this refers to triggering
+					       * a breakpoint so that the user will land
+					       * into GDB.
+					       */
+					      0, N_("Break into GDB"));
+  cmd_stop = grub_register_command_lockdown ("gdbstub_stop", grub_cmd_gdbstop,
+					     0, N_("Stop GDB stub"));
 }
 
 GRUB_MOD_FINI (gdb)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 013/117] loader/xnu: Don't allow loading extension and packages when locked down
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (11 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 012/117] gdb: Restrict GDB access " Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 014/117] docs: Document the cutmem command Daniel Kiper
                   ` (105 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The shim_lock verifier validates the XNU kernels but no its extensions
and packages. Prevent these to be loaded when the GRUB is locked down.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/xnu.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index 9ae4ceb35..44fd5a979 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -1485,20 +1485,23 @@ GRUB_MOD_INIT(xnu)
 				      N_("Load XNU image."));
   cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64,
 					0, N_("Load 64-bit XNU image."));
-  cmd_mkext = grub_register_command ("xnu_mkext", grub_cmd_xnu_mkext, 0,
-				     N_("Load XNU extension package."));
-  cmd_kext = grub_register_command ("xnu_kext", grub_cmd_xnu_kext, 0,
-				    N_("Load XNU extension."));
-  cmd_kextdir = grub_register_command ("xnu_kextdir", grub_cmd_xnu_kextdir,
-				       /* TRANSLATORS: OSBundleRequired is a
-					  variable name in xnu extensions
-					  manifests. It behaves mostly like
-					  GNU/Linux runlevels.
-				       */
-				       N_("DIRECTORY [OSBundleRequired]"),
-				       /* TRANSLATORS: There are many extensions
-					  in extension directory.  */
-				       N_("Load XNU extension directory."));
+  cmd_mkext = grub_register_command_lockdown ("xnu_mkext", grub_cmd_xnu_mkext, 0,
+					      N_("Load XNU extension package."));
+  cmd_kext = grub_register_command_lockdown ("xnu_kext", grub_cmd_xnu_kext, 0,
+					     N_("Load XNU extension."));
+  cmd_kextdir = grub_register_command_lockdown ("xnu_kextdir", grub_cmd_xnu_kextdir,
+						/*
+						 * TRANSLATORS: OSBundleRequired is
+						 * a variable name in xnu extensions
+						 * manifests. It behaves mostly like
+						 * GNU/Linux runlevels.
+						 */
+						N_("DIRECTORY [OSBundleRequired]"),
+						/*
+						 * TRANSLATORS: There are many extensions
+						 * in extension directory.
+						 */
+						N_("Load XNU extension directory."));
   cmd_ramdisk = grub_register_command ("xnu_ramdisk", grub_cmd_xnu_ramdisk, 0,
    /* TRANSLATORS: ramdisk here isn't identifier. It can be translated.  */
 				       N_("Load XNU ramdisk. "
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 014/117] docs: Document the cutmem command
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (12 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 013/117] loader/xnu: Don't allow loading extension and packages " Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 015/117] dl: Only allow unloading modules that are not dependencies Daniel Kiper
                   ` (104 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The command is not present in the docs/grub.texi user documentation.

Reported-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
---
 docs/grub.texi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index 91666781b..c5fc3904f 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3981,6 +3981,7 @@ you forget a command, you can run the command @command{help}
 * cpuid::                       Check for CPU features
 * crc::                         Compute or check CRC32 checksums
 * cryptomount::                 Mount a crypto device
+* cutmem::                      Remove memory regions
 * date::                        Display or set current date and time
 * devicetree::                  Load a device tree blob
 * distrust::                    Remove a pubkey from trusted keys
@@ -4139,6 +4140,8 @@ this page is to be filtered.  This syntax makes it easy to represent patterns
 that are often result of memory damage, due to physical distribution of memory
 cells.
 
+The command is similar to @command{cutmem} command.
+
 Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
       This prevents removing EFI memory regions to potentially subvert the
       security mechanisms provided by the UEFI secure boot.
@@ -4303,6 +4306,24 @@ modules (@var{luks}, @var{luks2} and @var{geli}) have to be loaded manually
 before this command can be used.
 @end deffn
 
+@node cutmem
+@subsection cutmem
+
+@deffn Command cutmem from[K|M|G] to[K|M|G]
+Remove any memory regions in specified range.
+@end deffn
+
+This command notifies the memory manager that specified regions of RAM ought to
+be filtered out. This remains in effect after a payload kernel has been loaded
+by GRUB, as long as the loaded kernel obtains its memory map from GRUB. Kernels
+that support this include Linux, GNU Mach, the kernel of FreeBSD and Multiboot
+kernels in general.
+
+The command is similar to @command{badram} command.
+
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+      This prevents removing EFI memory regions to potentially subvert the
+      security mechanisms provided by the UEFI secure boot.
 
 @node date
 @subsection date
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 015/117] dl: Only allow unloading modules that are not dependencies
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (13 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 014/117] docs: Document the cutmem command Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 016/117] usb: Avoid possible out-of-bound accesses caused by malicious devices Daniel Kiper
                   ` (103 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

When a module is attempted to be removed its reference counter is always
decremented. This means that repeated rmmod invocations will cause the
module to be unloaded even if another module depends on it.

This may lead to a use-after-free scenario allowing an attacker to execute
arbitrary code and by-pass the UEFI Secure Boot protection.

While being there, add the extern keyword to some function declarations in
that header file.

Fixes: CVE-2020-25632

Reported-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/minicmd.c | 7 +++++--
 grub-core/kern/dl.c          | 9 +++++++++
 include/grub/dl.h            | 8 +++++---
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index 6bbce3128..fa498931e 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -140,8 +140,11 @@ grub_mini_cmd_rmmod (struct grub_command *cmd __attribute__ ((unused)),
   if (grub_dl_is_persistent (mod))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload persistent module");
 
-  if (grub_dl_unref (mod) <= 0)
-    grub_dl_unload (mod);
+  if (grub_dl_ref_count (mod) > 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload referenced module");
+
+  grub_dl_unref (mod);
+  grub_dl_unload (mod);
 
   return 0;
 }
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 48eb5e7b6..48f8a7907 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -549,6 +549,15 @@ grub_dl_unref (grub_dl_t mod)
   return --mod->ref_count;
 }
 
+int
+grub_dl_ref_count (grub_dl_t mod)
+{
+  if (mod == NULL)
+    return 0;
+
+  return mod->ref_count;
+}
+
 static void
 grub_dl_flush_cache (grub_dl_t mod)
 {
diff --git a/include/grub/dl.h b/include/grub/dl.h
index f03c03561..b3753c9ca 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -203,9 +203,11 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
 grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
 grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size);
 int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
-void grub_dl_unload_unneeded (void);
-int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
-int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
+extern void grub_dl_unload_unneeded (void);
+extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
+extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
+extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod);
+
 extern grub_dl_t EXPORT_VAR(grub_dl_head);
 
 #ifndef GRUB_UTIL
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 016/117] usb: Avoid possible out-of-bound accesses caused by malicious devices
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (14 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 015/117] dl: Only allow unloading modules that are not dependencies Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 017/117] mmap: Fix memory leak when iterating over mapped memory Daniel Kiper
                   ` (102 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The maximum number of configurations and interfaces are fixed but there is
no out-of-bound checking to prevent a malicious USB device to report large
values for these and cause accesses outside the arrays' memory.

Fixes: CVE-2020-25647

Reported-by: Joseph Tartaro <joseph.tartaro@ioactive.com>
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/bus/usb/usb.c | 15 ++++++++++++---
 include/grub/usb.h      | 10 +++++++---
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c
index 8da5e4c74..7cb3cc230 100644
--- a/grub-core/bus/usb/usb.c
+++ b/grub-core/bus/usb/usb.c
@@ -75,6 +75,9 @@ grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook,
 grub_usb_err_t
 grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
 {
+  if (endpoint >= GRUB_USB_MAX_TOGGLE)
+    return GRUB_USB_ERR_BADDEVICE;
+
   dev->toggle[endpoint] = 0;
   return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
 				     | GRUB_USB_REQTYPE_STANDARD
@@ -134,10 +137,10 @@ grub_usb_device_initialize (grub_usb_device_t dev)
     return err;
   descdev = &dev->descdev;
 
-  for (i = 0; i < 8; i++)
+  for (i = 0; i < GRUB_USB_MAX_CONF; i++)
     dev->config[i].descconf = NULL;
 
-  if (descdev->configcnt == 0)
+  if (descdev->configcnt == 0 || descdev->configcnt > GRUB_USB_MAX_CONF)
     {
       err = GRUB_USB_ERR_BADDEVICE;
       goto fail;
@@ -172,6 +175,12 @@ grub_usb_device_initialize (grub_usb_device_t dev)
       /* Skip the configuration descriptor.  */
       pos = dev->config[i].descconf->length;
 
+      if (dev->config[i].descconf->numif > GRUB_USB_MAX_IF)
+        {
+          err = GRUB_USB_ERR_BADDEVICE;
+          goto fail;
+        }
+
       /* Read all interfaces.  */
       for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
 	{
@@ -217,7 +226,7 @@ grub_usb_device_initialize (grub_usb_device_t dev)
 
  fail:
 
-  for (i = 0; i < 8; i++)
+  for (i = 0; i < GRUB_USB_MAX_CONF; i++)
     grub_free (dev->config[i].descconf);
 
   return err;
diff --git a/include/grub/usb.h b/include/grub/usb.h
index 512ae1dd0..6475c552f 100644
--- a/include/grub/usb.h
+++ b/include/grub/usb.h
@@ -23,6 +23,10 @@
 #include <grub/usbdesc.h>
 #include <grub/usbtrans.h>
 
+#define GRUB_USB_MAX_CONF    8
+#define GRUB_USB_MAX_IF      32
+#define GRUB_USB_MAX_TOGGLE  256
+
 typedef struct grub_usb_device *grub_usb_device_t;
 typedef struct grub_usb_controller *grub_usb_controller_t;
 typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t;
@@ -167,7 +171,7 @@ struct grub_usb_configuration
   struct grub_usb_desc_config *descconf;
 
   /* Interfaces associated to this configuration.  */
-  struct grub_usb_interface interf[32];
+  struct grub_usb_interface interf[GRUB_USB_MAX_IF];
 };
 
 struct grub_usb_hub_port
@@ -191,7 +195,7 @@ struct grub_usb_device
   struct grub_usb_controller controller;
 
   /* Device configurations (after opening the device).  */
-  struct grub_usb_configuration config[8];
+  struct grub_usb_configuration config[GRUB_USB_MAX_CONF];
 
   /* Device address.  */
   int addr;
@@ -203,7 +207,7 @@ struct grub_usb_device
   int initialized;
 
   /* Data toggle values (used for bulk transfers only).  */
-  int toggle[256];
+  int toggle[GRUB_USB_MAX_TOGGLE];
 
   /* Used by libusb wrapper.  Schedulded for removal. */
   void *data;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 017/117] mmap: Fix memory leak when iterating over mapped memory
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (15 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 016/117] usb: Avoid possible out-of-bound accesses caused by malicious devices Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 018/117] net/net: Fix possible dereference to of a NULL pointer Daniel Kiper
                   ` (101 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

When returning from grub_mmap_iterate() the memory allocated to present
is not being released causing it to leak.

Fixes: CID 96655

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/mmap/mmap.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c
index 3cae68364..c8c8312c5 100644
--- a/grub-core/mmap/mmap.c
+++ b/grub-core/mmap/mmap.c
@@ -270,6 +270,7 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
 		   hook_data))
 	{
 	  grub_free (ctx.scanline_events);
+	  grub_free (present);
 	  return GRUB_ERR_NONE;
 	}
 
@@ -282,6 +283,7 @@ grub_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
     }
 
   grub_free (ctx.scanline_events);
+  grub_free (present);
   return GRUB_ERR_NONE;
 }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 018/117] net/net: Fix possible dereference to of a NULL pointer
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (16 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 017/117] mmap: Fix memory leak when iterating over mapped memory Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 019/117] net/tftp: Fix dangling memory pointer Daniel Kiper
                   ` (100 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

It is always possible that grub_zalloc() could fail, so we should check for
a NULL return. Otherwise we run the risk of dereferencing a NULL pointer.

Fixes: CID 296221

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/net/net.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 04ad10682..4d3eb5c1a 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -86,8 +86,13 @@ grub_net_link_layer_add_address (struct grub_net_card *card,
 
   /* Add sender to cache table.  */
   if (card->link_layer_table == NULL)
-    card->link_layer_table = grub_zalloc (LINK_LAYER_CACHE_SIZE
-					  * sizeof (card->link_layer_table[0]));
+    {
+      card->link_layer_table = grub_zalloc (LINK_LAYER_CACHE_SIZE
+					    * sizeof (card->link_layer_table[0]));
+      if (card->link_layer_table == NULL)
+	return;
+    }
+
   entry = &(card->link_layer_table[card->new_ll_entry]);
   entry->avail = 1;
   grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address));
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 019/117] net/tftp: Fix dangling memory pointer
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (17 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 018/117] net/net: Fix possible dereference to of a NULL pointer Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 020/117] kern/parser: Fix resource leak if argc == 0 Daniel Kiper
                   ` (99 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The static code analysis tool, Parfait, reported that the valid of
file->data was left referencing memory that was freed by the call to
grub_free(data) where data was initialized from file->data.

To ensure that there is no unintentional access to this memory
referenced by file->data we should set the pointer to NULL.

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/net/tftp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index 7e659a78b..1f3793ed8 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -442,6 +442,7 @@ tftp_close (struct grub_file *file)
       grub_net_udp_close (data->sock);
     }
   grub_free (data);
+  file->data = NULL;
   return GRUB_ERR_NONE;
 }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 020/117] kern/parser: Fix resource leak if argc == 0
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (18 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 019/117] net/tftp: Fix dangling memory pointer Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 021/117] kern/efi: Fix memory leak on failure Daniel Kiper
                   ` (98 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

After processing the command-line yet arriving at the point where we are
setting argv, we are allocating memory, even if argc == 0, which makes
no sense since we never put anything into the allocated argv.

The solution is to simply return that we've successfully processed the
arguments but that argc == 0, and also ensure that argv is NULL when
we're not allocating anything in it.

There are only 2 callers of this function, and both are handling a zero
value in argc assuming nothing is allocated in argv.

Fixes: CID 96680

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/parser.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 619db3122..d1cf061ad 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -146,6 +146,7 @@ grub_parser_split_cmdline (const char *cmdline,
   int i;
 
   *argc = 0;
+  *argv = NULL;
   do
     {
       if (!rd || !*rd)
@@ -207,6 +208,10 @@ grub_parser_split_cmdline (const char *cmdline,
       (*argc)++;
     }
 
+  /* If there are no args, then we're done. */
+  if (!*argc)
+    return 0;
+
   /* Reserve memory for the return values.  */
   args = grub_malloc (bp - buffer);
   if (!args)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 021/117] kern/efi: Fix memory leak on failure
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (19 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 020/117] kern/parser: Fix resource leak if argc == 0 Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 022/117] kern/efi/mm: Fix possible NULL pointer dereference Daniel Kiper
                   ` (97 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

Free the memory allocated to name before returning on failure.

Fixes: CID 296222

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/efi/efi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 2942b8e35..67394bb6f 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -410,6 +410,7 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
 	    {
 	      grub_error (GRUB_ERR_OUT_OF_RANGE,
 			  "malformed EFI Device Path node has length=%d", len);
+	      grub_free (name);
 	      return NULL;
 	    }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 022/117] kern/efi/mm: Fix possible NULL pointer dereference
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (20 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 021/117] kern/efi: Fix memory leak on failure Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 023/117] gnulib/regexec: Resolve unused variable Daniel Kiper
                   ` (96 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The model of grub_efi_get_memory_map() is that if memory_map is NULL,
then the purpose is to discover how much memory should be allocated to
it for the subsequent call.

The problem here is that with grub_efi_is_finished set to 1, there is no
check at all that the function is being called with a non-NULL memory_map.

While this MAY be true, we shouldn't assume it.

The solution to this is to behave as expected, and if memory_map is NULL,
then don't try to use it and allow memory_map_size to be filled in, and
return 0 as is done later in the code if the buffer is too small (or NULL).

Additionally, drop unneeded ret = 1.

Fixes: CID 96632

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/efi/mm.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 457772d57..8d380c054 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -339,16 +339,25 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size,
   if (grub_efi_is_finished)
     {
       int ret = 1;
-      if (*memory_map_size < finish_mmap_size)
+
+      if (memory_map != NULL)
 	{
-	  grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size);
+	  if (*memory_map_size < finish_mmap_size)
+	    {
+	      grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size);
+	      ret = 0;
+	    }
+          else
+	    grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size);
+	}
+      else
+	{
+	  /*
+	   * Incomplete, no buffer to copy into, same as
+	   * GRUB_EFI_BUFFER_TOO_SMALL below.
+	   */
 	  ret = 0;
 	}
-      else
-	{
-	  grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size);
-	  ret = 1;
-	}
       *memory_map_size = finish_mmap_size;
       if (map_key)
 	*map_key = finish_key;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 023/117] gnulib/regexec: Resolve unused variable
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (21 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 022/117] kern/efi/mm: Fix possible NULL pointer dereference Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 024/117] gnulib/regcomp: Fix uninitialized token structure Daniel Kiper
                   ` (95 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

This is a really minor issue where a variable is being assigned to but
not checked before it is overwritten again.

The reason for this issue is that we are not building with DEBUG set and
this in turn means that the assert() that reads the value of the
variable match_last is being processed out.

The solution, move the assignment to match_last in to an ifdef DEBUG too.

Fixes: CID 292459

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 bootstrap.conf                                      |  2 +-
 conf/Makefile.extra-dist                            |  1 +
 grub-core/lib/gnulib-patches/fix-unused-value.patch | 14 ++++++++++++++
 3 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/lib/gnulib-patches/fix-unused-value.patch

diff --git a/bootstrap.conf b/bootstrap.conf
index 6d383240e..4c8c37c16 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -79,7 +79,7 @@ cp -a INSTALL INSTALL.grub
 
 bootstrap_post_import_hook () {
   set -e
-  for patchname in fix-base64 fix-null-deref fix-width no-abort; do
+  for patchname in fix-base64 fix-null-deref fix-unused-value fix-width no-abort; do
     patch -d grub-core/lib/gnulib -p2 \
       < "grub-core/lib/gnulib-patches/$patchname.patch"
   done
diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
index 37dc3aa10..0d3b74e8e 100644
--- a/conf/Makefile.extra-dist
+++ b/conf/Makefile.extra-dist
@@ -30,6 +30,7 @@ EXTRA_DIST += grub-core/genemuinitheader.sh
 
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch
+EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/no-abort.patch
 
diff --git a/grub-core/lib/gnulib-patches/fix-unused-value.patch b/grub-core/lib/gnulib-patches/fix-unused-value.patch
new file mode 100644
index 000000000..ba51f1bf2
--- /dev/null
+++ b/grub-core/lib/gnulib-patches/fix-unused-value.patch
@@ -0,0 +1,14 @@
+--- a/lib/regexec.c	2020-10-21 14:25:35.310195912 +0000
++++ b/lib/regexec.c	2020-10-21 14:32:07.961765604 +0000
+@@ -828,7 +828,11 @@
+ 		    break;
+ 		  if (__glibc_unlikely (err != REG_NOMATCH))
+ 		    goto free_return;
++#ifdef DEBUG
++		  /* Only used for assertion below when DEBUG is set, otherwise
++		     it will be over-written when we loop around.  */
+ 		  match_last = -1;
++#endif
+ 		}
+ 	      else
+ 		break; /* We found a match.  */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 024/117] gnulib/regcomp: Fix uninitialized token structure
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (22 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 023/117] gnulib/regexec: Resolve unused variable Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 025/117] gnulib/argp-help: Fix dereference of a possibly NULL state Daniel Kiper
                   ` (94 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The code is assuming that the value of br_token.constraint was
initialized to zero when it wasn't.

While some compilers will ensure that, not all do, so it is better to
fix this explicitly than leave it to chance.

Fixes: CID 73749

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 bootstrap.conf                                          |  2 +-
 conf/Makefile.extra-dist                                |  1 +
 grub-core/lib/gnulib-patches/fix-uninit-structure.patch | 11 +++++++++++
 3 files changed, 13 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/lib/gnulib-patches/fix-uninit-structure.patch

diff --git a/bootstrap.conf b/bootstrap.conf
index 4c8c37c16..a7fc34eb3 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -79,7 +79,7 @@ cp -a INSTALL INSTALL.grub
 
 bootstrap_post_import_hook () {
   set -e
-  for patchname in fix-base64 fix-null-deref fix-unused-value fix-width no-abort; do
+  for patchname in fix-base64 fix-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do
     patch -d grub-core/lib/gnulib -p2 \
       < "grub-core/lib/gnulib-patches/$patchname.patch"
   done
diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
index 0d3b74e8e..d83cde427 100644
--- a/conf/Makefile.extra-dist
+++ b/conf/Makefile.extra-dist
@@ -30,6 +30,7 @@ EXTRA_DIST += grub-core/genemuinitheader.sh
 
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch
+EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/no-abort.patch
diff --git a/grub-core/lib/gnulib-patches/fix-uninit-structure.patch b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch
new file mode 100644
index 000000000..7b4d9f67a
--- /dev/null
+++ b/grub-core/lib/gnulib-patches/fix-uninit-structure.patch
@@ -0,0 +1,11 @@
+--- a/lib/regcomp.c	2020-10-22 13:49:06.770168928 +0000
++++ b/lib/regcomp.c	2020-10-22 13:50:37.026528298 +0000
+@@ -3662,7 +3662,7 @@
+   Idx alloc = 0;
+ #endif /* not RE_ENABLE_I18N */
+   reg_errcode_t ret;
+-  re_token_t br_token;
++  re_token_t br_token = {0};
+   bin_tree_t *tree;
+ 
+   sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 025/117] gnulib/argp-help: Fix dereference of a possibly NULL state
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (23 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 024/117] gnulib/regcomp: Fix uninitialized token structure Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 026/117] gnulib/regexec: Fix possible null-dereference Daniel Kiper
                   ` (93 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

All other instances of call to __argp_failure() where there is
a dgettext() call is first checking whether state is NULL before
attempting to dereference it to get the root_argp->argp_domain.

Fixes: CID 292436

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 bootstrap.conf                                          |  2 +-
 conf/Makefile.extra-dist                                |  1 +
 grub-core/lib/gnulib-patches/fix-null-state-deref.patch | 12 ++++++++++++
 3 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/lib/gnulib-patches/fix-null-state-deref.patch

diff --git a/bootstrap.conf b/bootstrap.conf
index a7fc34eb3..d71d1b51e 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -79,7 +79,7 @@ cp -a INSTALL INSTALL.grub
 
 bootstrap_post_import_hook () {
   set -e
-  for patchname in fix-base64 fix-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do
+  for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-uninit-structure fix-unused-value fix-width no-abort; do
     patch -d grub-core/lib/gnulib -p2 \
       < "grub-core/lib/gnulib-patches/$patchname.patch"
   done
diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
index d83cde427..a46fc44e7 100644
--- a/conf/Makefile.extra-dist
+++ b/conf/Makefile.extra-dist
@@ -30,6 +30,7 @@ EXTRA_DIST += grub-core/genemuinitheader.sh
 
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch
+EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch
diff --git a/grub-core/lib/gnulib-patches/fix-null-state-deref.patch b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch
new file mode 100644
index 000000000..813ec09c8
--- /dev/null
+++ b/grub-core/lib/gnulib-patches/fix-null-state-deref.patch
@@ -0,0 +1,12 @@
+--- a/lib/argp-help.c	2020-10-28 14:32:19.189215988 +0000
++++ b/lib/argp-help.c	2020-10-28 14:38:21.204673940 +0000
+@@ -145,7 +145,8 @@
+       if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin)
+         {
+           __argp_failure (state, 0, 0,
+-                          dgettext (state->root_argp->argp_domain,
++                          dgettext (state == NULL ? NULL
++                                    : state->root_argp->argp_domain,
+                                     "\
+ ARGP_HELP_FMT: %s value is less than or equal to %s"),
+                           "rmargin", up->name);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 026/117] gnulib/regexec: Fix possible null-dereference
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (24 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 025/117] gnulib/argp-help: Fix dereference of a possibly NULL state Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 027/117] gnulib/regcomp: Fix uninitialized re_token Daniel Kiper
                   ` (92 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

It appears to be possible that the mctx->state_log field may be NULL,
and the name of this function, clean_state_log_if_needed(), suggests
that it should be checking that it is valid to be cleaned before
assuming that it does.

Fixes: CID 86720

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 bootstrap.conf                                            |  3 ++-
 conf/Makefile.extra-dist                                  |  1 +
 grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch | 12 ++++++++++++
 3 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch

diff --git a/bootstrap.conf b/bootstrap.conf
index d71d1b51e..22feff5c0 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -79,7 +79,8 @@ cp -a INSTALL INSTALL.grub
 
 bootstrap_post_import_hook () {
   set -e
-  for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-uninit-structure fix-unused-value fix-width no-abort; do
+  for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regexec-null-deref \
+      fix-uninit-structure fix-unused-value fix-width no-abort; do
     patch -d grub-core/lib/gnulib -p2 \
       < "grub-core/lib/gnulib-patches/$patchname.patch"
   done
diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
index a46fc44e7..c0ac65ec3 100644
--- a/conf/Makefile.extra-dist
+++ b/conf/Makefile.extra-dist
@@ -31,6 +31,7 @@ EXTRA_DIST += grub-core/genemuinitheader.sh
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch
+EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch
diff --git a/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch
new file mode 100644
index 000000000..db6dac9c9
--- /dev/null
+++ b/grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch
@@ -0,0 +1,12 @@
+--- a/lib/regexec.c	2020-10-21 14:25:35.310195912 +0000
++++ b/lib/regexec.c	2020-11-05 10:55:09.621542984 +0000
+@@ -1692,6 +1692,9 @@
+ {
+   Idx top = mctx->state_log_top;
+
++  if (mctx->state_log == NULL)
++    return REG_NOERROR;
++
+   if ((next_state_log_idx >= mctx->input.bufs_len
+        && mctx->input.bufs_len < mctx->input.len)
+       || (next_state_log_idx >= mctx->input.valid_len
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 027/117] gnulib/regcomp: Fix uninitialized re_token
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (25 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 026/117] gnulib/regexec: Fix possible null-dereference Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 028/117] io/lzopio: Resolve unnecessary self-assignment errors Daniel Kiper
                   ` (91 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

This issue has been fixed in the latest version of gnulib, so to
maintain consistency, I've backported that change rather than doing
something different.

Fixes: CID 73828

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 bootstrap.conf                                            |  4 ++--
 conf/Makefile.extra-dist                                  |  1 +
 .../lib/gnulib-patches/fix-regcomp-uninit-token.patch     | 15 +++++++++++++++
 3 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch

diff --git a/bootstrap.conf b/bootstrap.conf
index 22feff5c0..6b043fc35 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -79,8 +79,8 @@ cp -a INSTALL INSTALL.grub
 
 bootstrap_post_import_hook () {
   set -e
-  for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regexec-null-deref \
-      fix-uninit-structure fix-unused-value fix-width no-abort; do
+  for patchname in fix-base64 fix-null-deref fix-null-state-deref fix-regcomp-uninit-token \
+      fix-regexec-null-deref fix-uninit-structure fix-unused-value fix-width no-abort; do
     patch -d grub-core/lib/gnulib -p2 \
       < "grub-core/lib/gnulib-patches/$patchname.patch"
   done
diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist
index c0ac65ec3..8f1485d52 100644
--- a/conf/Makefile.extra-dist
+++ b/conf/Makefile.extra-dist
@@ -31,6 +31,7 @@ EXTRA_DIST += grub-core/genemuinitheader.sh
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-base64.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-deref.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-null-state-deref.patch
+EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-regexec-null-deref.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-uninit-structure.patch
 EXTRA_DIST += grub-core/lib/gnulib-patches/fix-unused-value.patch
diff --git a/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch
new file mode 100644
index 000000000..02e06315d
--- /dev/null
+++ b/grub-core/lib/gnulib-patches/fix-regcomp-uninit-token.patch
@@ -0,0 +1,15 @@
+--- a/lib/regcomp.c	2020-11-24 17:06:08.159223858 +0000
++++ b/lib/regcomp.c	2020-11-24 17:06:15.630253923 +0000
+@@ -3808,11 +3808,7 @@
+ create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
+ 	     re_token_type_t type)
+ {
+-  re_token_t t;
+-#if defined GCC_LINT || defined lint
+-  memset (&t, 0, sizeof t);
+-#endif
+-  t.type = type;
++  re_token_t t = { .type = type };
+   return create_token_tree (dfa, left, right, &t);
+ }
+ 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 028/117] io/lzopio: Resolve unnecessary self-assignment errors
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (26 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 027/117] gnulib/regcomp: Fix uninitialized re_token Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 029/117] zstd: Initialize seq_t structure fully Daniel Kiper
                   ` (90 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

These 2 assignments are unnecessary since they are just assigning
to themselves.

Fixes: CID 73643

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/io/lzopio.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c
index 30144857d..a7d442543 100644
--- a/grub-core/io/lzopio.c
+++ b/grub-core/io/lzopio.c
@@ -125,8 +125,6 @@ read_block_header (struct grub_lzopio *lzopio)
 			  sizeof (lzopio->block.ucheck)) !=
 	  sizeof (lzopio->block.ucheck))
 	return -1;
-
-      lzopio->block.ucheck = lzopio->block.ucheck;
     }
 
   /* Read checksum of compressed data.  */
@@ -143,8 +141,6 @@ read_block_header (struct grub_lzopio *lzopio)
 			      sizeof (lzopio->block.ccheck)) !=
 	      sizeof (lzopio->block.ccheck))
 	    return -1;
-
-	  lzopio->block.ccheck = lzopio->block.ccheck;
 	}
     }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 029/117] zstd: Initialize seq_t structure fully
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (27 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 028/117] io/lzopio: Resolve unnecessary self-assignment errors Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-18  8:50   ` Paul Menzel
  2021-03-02 18:00 ` [SECURITY PATCH 030/117] kern/partition: Check for NULL before dereferencing input string Daniel Kiper
                   ` (89 subsequent siblings)
  118 siblings, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

While many compilers will initialize this to zero, not all will, so it
is better to be sure that fields not being explicitly set are at known
values, and there is code that checks this fields value elsewhere in the
code.

Fixes: CID 292440

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/lib/zstd/zstd_decompress.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/lib/zstd/zstd_decompress.c b/grub-core/lib/zstd/zstd_decompress.c
index 711b5b6d7..e4b5670c2 100644
--- a/grub-core/lib/zstd/zstd_decompress.c
+++ b/grub-core/lib/zstd/zstd_decompress.c
@@ -1325,7 +1325,7 @@ typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset
 FORCE_INLINE_TEMPLATE seq_t
 ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
 {
-    seq_t seq;
+    seq_t seq = {0};
     U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
     U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
     U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 030/117] kern/partition: Check for NULL before dereferencing input string
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (28 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 029/117] zstd: Initialize seq_t structure fully Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 031/117] disk/ldm: Make sure comp data is freed before exiting from make_vg() Daniel Kiper
                   ` (88 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

There is the possibility that the value of str comes from an external
source and continuing to use it before ever checking its validity is
wrong. So, needs fixing.

Additionally, drop unneeded part initialization.

Fixes: CID 292444

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/partition.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c
index 2c401b866..3068c4dca 100644
--- a/grub-core/kern/partition.c
+++ b/grub-core/kern/partition.c
@@ -109,11 +109,14 @@ grub_partition_map_probe (const grub_partition_map_t partmap,
 grub_partition_t
 grub_partition_probe (struct grub_disk *disk, const char *str)
 {
-  grub_partition_t part = 0;
+  grub_partition_t part;
   grub_partition_t curpart = 0;
   grub_partition_t tail;
   const char *ptr;
 
+  if (str == NULL)
+    return 0;
+
   part = tail = disk->partition;
 
   for (ptr = str; *ptr;)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 031/117] disk/ldm: Make sure comp data is freed before exiting from make_vg()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (29 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 030/117] kern/partition: Check for NULL before dereferencing input string Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 032/117] disk/ldm: If failed then free vg variable too Daniel Kiper
                   ` (87 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Marco A Benatto <mbenatto@redhat.com>

Several error handling paths in make_vg() do not free comp data before
jumping to fail2 label and returning from the function. This will leak
memory. So, let's fix all issues of that kind.

Fixes: CID 73804

Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/ldm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
index 912e88255..48942549a 100644
--- a/grub-core/disk/ldm.c
+++ b/grub-core/disk/ldm.c
@@ -554,7 +554,11 @@ make_vg (grub_disk_t disk,
 	      comp->segments = grub_calloc (comp->segment_alloc,
 					    sizeof (*comp->segments));
 	      if (!comp->segments)
-		goto fail2;
+		{
+		  grub_free (comp->internal_id);
+		  grub_free (comp);
+		  goto fail2;
+		}
 	    }
 	  else
 	    {
@@ -562,7 +566,11 @@ make_vg (grub_disk_t disk,
 	      comp->segment_count = 1;
 	      comp->segments = grub_malloc (sizeof (*comp->segments));
 	      if (!comp->segments)
-		goto fail2;
+		{
+		  grub_free (comp->internal_id);
+		  grub_free (comp);
+		  goto fail2;
+		}
 	      comp->segments->start_extent = 0;
 	      comp->segments->extent_count = lv->size;
 	      comp->segments->layout = 0;
@@ -574,15 +582,26 @@ make_vg (grub_disk_t disk,
 		  comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK;
 		}
 	      else
-		goto fail2;
+		{
+		  grub_free (comp->segments);
+		  grub_free (comp->internal_id);
+		  grub_free (comp);
+		  goto fail2;
+		}
 	      ptr += *ptr + 1;
 	      ptr++;
 	      if (!(vblk[i].flags & 0x10))
-		goto fail2;
+		{
+		  grub_free (comp->segments);
+		  grub_free (comp->internal_id);
+		  grub_free (comp);
+		  goto fail2;
+		}
 	      if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
 		  || ptr + *ptr + 1 >= vblk[i].dynamic
 		  + sizeof (vblk[i].dynamic))
 		{
+		  grub_free (comp->segments);
 		  grub_free (comp->internal_id);
 		  grub_free (comp);
 		  goto fail2;
@@ -592,6 +611,7 @@ make_vg (grub_disk_t disk,
 	      if (ptr + *ptr + 1 >= vblk[i].dynamic
 		  + sizeof (vblk[i].dynamic))
 		{
+		  grub_free (comp->segments);
 		  grub_free (comp->internal_id);
 		  grub_free (comp);
 		  goto fail2;
@@ -601,7 +621,12 @@ make_vg (grub_disk_t disk,
 	      comp->segments->nodes = grub_calloc (comp->segments->node_alloc,
 						   sizeof (*comp->segments->nodes));
 	      if (!lv->segments->nodes)
-		goto fail2;
+		{
+		  grub_free (comp->segments);
+		  grub_free (comp->internal_id);
+		  grub_free (comp);
+		  goto fail2;
+		}
 	    }
 
 	  if (lv->segments->node_alloc == lv->segments->node_count)
@@ -611,11 +636,23 @@ make_vg (grub_disk_t disk,
 
 	      if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) ||
 		  grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz))
-		goto fail2;
+		{
+		  grub_free (comp->segments->nodes);
+		  grub_free (comp->segments);
+		  grub_free (comp->internal_id);
+		  grub_free (comp);
+		  goto fail2;
+		}
 
 	      t = grub_realloc (lv->segments->nodes, sz);
 	      if (!t)
-		goto fail2;
+		{
+		  grub_free (comp->segments->nodes);
+		  grub_free (comp->segments);
+		  grub_free (comp->internal_id);
+		  grub_free (comp);
+		  goto fail2;
+		}
 	      lv->segments->nodes = t;
 	    }
 	  lv->segments->nodes[lv->segments->node_count].pv = 0;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 032/117] disk/ldm: If failed then free vg variable too
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (30 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 031/117] disk/ldm: Make sure comp data is freed before exiting from make_vg() Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 033/117] disk/ldm: Fix memory leak on uninserted lv references Daniel Kiper
                   ` (86 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>

Fixes: CID 73809

Signed-off-by: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/ldm.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
index 48942549a..c25941ec9 100644
--- a/grub-core/disk/ldm.c
+++ b/grub-core/disk/ldm.c
@@ -199,6 +199,7 @@ make_vg (grub_disk_t disk,
     {
       grub_free (vg->uuid);
       grub_free (vg->name);
+      grub_free (vg);
       return NULL;
     }
   grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 033/117] disk/ldm: Fix memory leak on uninserted lv references
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (31 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 032/117] disk/ldm: If failed then free vg variable too Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 034/117] disk/cryptodisk: Fix potential integer overflow Daniel Kiper
                   ` (85 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The problem here is that the memory allocated to the variable lv is not
yet inserted into the list that is being processed at the label fail2.

As we can already see at line 342, which correctly frees lv before going
to fail2, we should also be doing that at these earlier jumps to fail2.

Fixes: CID 73824

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/ldm.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
index c25941ec9..4577a51dc 100644
--- a/grub-core/disk/ldm.c
+++ b/grub-core/disk/ldm.c
@@ -321,7 +321,10 @@ make_vg (grub_disk_t disk,
 	  lv->visible = 1;
 	  lv->segments = grub_zalloc (sizeof (*lv->segments));
 	  if (!lv->segments)
-	    goto fail2;
+	    {
+	      grub_free (lv);
+	      goto fail2;
+	    }
 	  lv->segments->start_extent = 0;
 	  lv->segments->type = GRUB_DISKFILTER_MIRROR;
 	  lv->segments->node_count = 0;
@@ -329,7 +332,10 @@ make_vg (grub_disk_t disk,
 	  lv->segments->nodes = grub_calloc (lv->segments->node_alloc,
 					     sizeof (*lv->segments->nodes));
 	  if (!lv->segments->nodes)
-	    goto fail2;
+	    {
+	      grub_free (lv);
+	      goto fail2;
+	    }
 	  ptr = vblk[i].dynamic;
 	  if (ptr + *ptr + 1 >= vblk[i].dynamic
 	      + sizeof (vblk[i].dynamic))
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 034/117] disk/cryptodisk: Fix potential integer overflow
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (32 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 033/117] disk/ldm: Fix memory leak on uninserted lv references Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 035/117] hfsplus: Check that the volume name length is valid Daniel Kiper
                   ` (84 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The encrypt and decrypt functions expect a grub_size_t. So, we need to
ensure that the constant bit shift is using grub_size_t rather than
unsigned int when it is performing the shift.

Fixes: CID 307788

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/cryptodisk.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index b62835acc..41866c62d 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -325,10 +325,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << log_sector_size), iv);
+					   ((grub_size_t) 1 << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << log_sector_size), iv);
+					   ((grub_size_t) 1 << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -336,10 +336,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << log_sector_size), iv);
+					    ((grub_size_t) 1 << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << log_sector_size), iv);
+					    ((grub_size_t) 1 << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 035/117] hfsplus: Check that the volume name length is valid
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (33 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 034/117] disk/cryptodisk: Fix potential integer overflow Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 036/117] zfs: Fix possible negative shift operation Daniel Kiper
                   ` (83 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

HFS+ documentation suggests that the maximum filename and volume name is
255 Unicode characters in length.

So, when converting from big-endian to little-endian, we should ensure
that the name of the volume has a length that is between 0 and 255,
inclusive.

Fixes: CID 73641

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/hfsplus.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index 9c4e4c88c..8fe7c12ed 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -1012,6 +1012,15 @@ grub_hfsplus_label (grub_device_t device, char **label)
     grub_hfsplus_btree_recptr (&data->catalog_tree, node, ptr);
 
   label_len = grub_be_to_cpu16 (catkey->namelen);
+
+  /* Ensure that the length is >= 0. */
+  if (label_len < 0)
+    label_len = 0;
+
+  /* Ensure label length is at most 255 Unicode characters. */
+  if (label_len > 255)
+    label_len = 255;
+
   label_name = grub_calloc (label_len, sizeof (*label_name));
   if (!label_name)
     {
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 036/117] zfs: Fix possible negative shift operation
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (34 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 035/117] hfsplus: Check that the volume name length is valid Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 037/117] zfs: Fix resource leaks while constructing path Daniel Kiper
                   ` (82 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

While it is possible for the return value from zfs_log2() to be zero
(0), it is quite unlikely, given that the previous assignment to blksz
is shifted up by SPA_MINBLOCKSHIFT (9) before 9 is subtracted at the
assignment to epbs.

But, while unlikely during a normal operation, it may be that a carefully
crafted ZFS filesystem could result in a zero (0) value to the
dn_datalbkszsec field, which means that the shift left does nothing
and assigns zero (0) to blksz, resulting in a negative epbs value.

Fixes: CID 73608

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/zfs/zfs.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index b6e1e178d..695e6ea30 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -2670,6 +2670,11 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type,
   blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, 
 			     mdn->endian) << SPA_MINBLOCKSHIFT;
   epbs = zfs_log2 (blksz) - DNODE_SHIFT;
+
+  /* While this should never happen, we should check that epbs is not negative. */
+  if (epbs < 0)
+    epbs = 0;
+
   blkid = objnum >> epbs;
   idx = objnum & ((1 << epbs) - 1);
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 037/117] zfs: Fix resource leaks while constructing path
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (35 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 036/117] zfs: Fix possible negative shift operation Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 038/117] zfs: Fix possible integer overflows Daniel Kiper
                   ` (81 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>

There are several exit points in dnode_get_path() that are causing possible
memory leaks.

In the while(1) the correct exit mechanism should not be to do a direct return,
but to instead break out of the loop, setting err first if it is not already set.

The reason behind this is that the dnode_path is a linked list, and while doing
through this loop, it is being allocated and built up - the only way to
correctly unravel it is to traverse it, which is what is being done at the end
of the function outside of the loop.

Several of the existing exit points correctly did a break, but not all so this
change makes that more consistent and should resolve the leaking of memory as
found by Coverity.

Fixes: CID 73741

Signed-off-by: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/zfs/zfs.c | 30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index 695e6ea30..ca82eb878 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -2839,8 +2839,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 
       if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS)
 	{
-	  grub_free (path_buf);
-	  return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
+	  err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
+	  break;
 	}
       err = zap_lookup (&(dnode_path->dn), cname, &objnum,
 			data, subvol->case_insensitive);
@@ -2882,11 +2882,18 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 		       << SPA_MINBLOCKSHIFT);
 
 	      if (blksz == 0)
-		return grub_error(GRUB_ERR_BAD_FS, "0-sized block");
+                {
+                  err = grub_error (GRUB_ERR_BAD_FS, "0-sized block");
+                  break;
+                }
 
 	      sym_value = grub_malloc (sym_sz);
 	      if (!sym_value)
-		return grub_errno;
+		{
+		  err = grub_errno;
+		  break;
+		}
+
 	      for (block = 0; block < (sym_sz + blksz - 1) / blksz; block++)
 		{
 		  void *t;
@@ -2896,7 +2903,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 		  if (err)
 		    {
 		      grub_free (sym_value);
-		      return err;
+		      break;
 		    }
 
 		  movesize = sym_sz - block * blksz;
@@ -2906,6 +2913,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 		  grub_memcpy (sym_value + block * blksz, t, movesize);
 		  grub_free (t);
 		}
+		if (err)
+		  break;
 	      free_symval = 1;
 	    }	    
 	  path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
@@ -2914,7 +2923,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 	      grub_free (oldpathbuf);
 	      if (free_symval)
 		grub_free (sym_value);
-	      return grub_errno;
+	      err = grub_errno;
+	      break;
 	    }
 	  grub_memcpy (path, sym_value, sym_sz);
 	  if (free_symval)
@@ -2952,11 +2962,12 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 	      
 	      err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data);
 	      if (err)
-		return err;
+	        break;
 	    }
 	  else
 	    {
-	      return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
+	      err = grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
+	      break;
 	    }
 
 	  hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
@@ -2977,7 +2988,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn,
 	      if (!path_buf)
 		{
 		  grub_free (oldpathbuf);
-		  return grub_errno;
+		  err = grub_errno;
+		  break;
 		}
 	      grub_memcpy (path, sym_value, sym_sz);
 	      path [sym_sz] = 0;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 038/117] zfs: Fix possible integer overflows
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (36 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 037/117] zfs: Fix resource leaks while constructing path Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 039/117] zfsinfo: Correct a check for error allocating memory Daniel Kiper
                   ` (80 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

In all cases the problem is that the value being acted upon by
a left-shift is a 32-bit number which is then being used in the
context of a 64-bit number.

To avoid overflow we ensure that the number being shifted is 64-bit
before the shift is done.

Fixes: CID 73684, CID 73695, CID 73764

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/zfs/zfs.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index ca82eb878..9ef2fd61a 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -567,7 +567,7 @@ find_bestub (uberblock_phys_t * ub_array,
       ubptr = (uberblock_phys_t *) ((grub_properly_aligned_t *) ub_array
 				    + ((i << ub_shift)
 				       / sizeof (grub_properly_aligned_t)));
-      err = uberblock_verify (ubptr, offset, 1 << ub_shift);
+      err = uberblock_verify (ubptr, offset, (grub_size_t) 1 << ub_shift);
       if (err)
 	{
 	  grub_errno = GRUB_ERR_NONE;
@@ -1546,7 +1546,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
 
 	    high = grub_divmod64 ((offset >> desc->ashift) + c,
 				  desc->n_children, &devn);
-	    csize = bsize << desc->ashift;
+	    csize = (grub_size_t) bsize << desc->ashift;
 	    if (csize > len)
 	      csize = len;
 
@@ -1638,8 +1638,8 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc,
 
 	    while (len > 0)
 	      {
-		grub_size_t csize;
-		csize = ((s / (desc->n_children - desc->nparity))
+		grub_size_t csize = s;
+		csize = ((csize / (desc->n_children - desc->nparity))
 			 << desc->ashift);
 		if (csize > len)
 		  csize = len;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 039/117] zfsinfo: Correct a check for error allocating memory
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (37 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 038/117] zfs: Fix possible integer overflows Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 040/117] affs: Fix memory leaks Daniel Kiper
                   ` (79 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

While arguably the check for grub_errno is correct, we should really be
checking the return value from the function since it is always possible
that grub_errno was set elsewhere, making this code behave incorrectly.

Fixes: CID 73668

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/zfs/zfsinfo.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c
index c8a28acf5..bf2918018 100644
--- a/grub-core/fs/zfs/zfsinfo.c
+++ b/grub-core/fs/zfs/zfsinfo.c
@@ -358,8 +358,8 @@ grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
 
   devname = grub_file_get_device_name (args[0]);
-  if (grub_errno)
-    return grub_errno;
+  if (devname == NULL)
+    return GRUB_ERR_OUT_OF_MEMORY;
 
   dev = grub_device_open (devname);
   grub_free (devname);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 040/117] affs: Fix memory leaks
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (38 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 039/117] zfsinfo: Correct a check for error allocating memory Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 041/117] libgcrypt/mpi: Fix possible unintended sign extension Daniel Kiper
                   ` (78 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The node structure reference is being allocated but not freed if it
reaches the end of the function. If any of the hooks had returned
a non-zero value, then node would have been copied in to the context
reference, but otherwise node is not stored and should be freed.

Similarly, the call to grub_affs_create_node() replaces the allocated
memory in node with a newly allocated structure, leaking the existing
memory pointed by node.

Finally, when dir->parent is set, then we again replace node with newly
allocated memory, which seems unnecessary when we copy in the values
from dir->parent immediately after.

Fixes: CID 73759

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/affs.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c
index 220b3712f..230e26af0 100644
--- a/grub-core/fs/affs.c
+++ b/grub-core/fs/affs.c
@@ -400,12 +400,12 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
 {
   unsigned int i;
   struct grub_affs_file file;
-  struct grub_fshelp_node *node = 0;
+  struct grub_fshelp_node *node, *orig_node;
   struct grub_affs_data *data = dir->data;
   grub_uint32_t *hashtable;
 
   /* Create the directory entries for `.' and `..'.  */
-  node = grub_zalloc (sizeof (*node));
+  node = orig_node = grub_zalloc (sizeof (*node));
   if (!node)
     return 1;
     
@@ -414,9 +414,6 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
     return 1;
   if (dir->parent)
     {
-      node = grub_zalloc (sizeof (*node));
-      if (!node)
-	return 1;
       *node = *dir->parent;
       if (hook ("..", GRUB_FSHELP_DIR, node, hook_data))
 	return 1;
@@ -456,17 +453,18 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
 
 	  if (grub_affs_create_node (dir, hook, hook_data, &node, &hashtable,
 				     next, &file))
-	    return 1;
+	    {
+	      /* Node has been replaced in function. */
+	      grub_free (orig_node);
+	      return 1;
+	    }
 
 	  next = grub_be_to_cpu32 (file.next);
 	}
     }
 
-  grub_free (hashtable);
-  return 0;
-
  fail:
-  grub_free (node);
+  grub_free (orig_node);
   grub_free (hashtable);
   return 0;
 }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 041/117] libgcrypt/mpi: Fix possible unintended sign extension
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (39 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 040/117] affs: Fix memory leaks Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 042/117] libgcrypt/mpi: Fix possible NULL dereference Daniel Kiper
                   ` (77 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The array of unsigned char gets promoted to a signed 32-bit int before
it is finally promoted to a size_t. There is the possibility that this
may result in the signed-bit being set for the intermediate signed
32-bit int. We should ensure that the promotion is to the correct type
before we bitwise-OR the values.

Fixes: CID 96697

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/lib/libgcrypt/mpi/mpicoder.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/lib/libgcrypt/mpi/mpicoder.c b/grub-core/lib/libgcrypt/mpi/mpicoder.c
index a3435ed14..7ecad27b2 100644
--- a/grub-core/lib/libgcrypt/mpi/mpicoder.c
+++ b/grub-core/lib/libgcrypt/mpi/mpicoder.c
@@ -458,7 +458,7 @@ gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
       if (len && len < 4)
         return gcry_error (GPG_ERR_TOO_SHORT);
 
-      n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
+      n = ((size_t)s[0] << 24 | (size_t)s[1] << 16 | (size_t)s[2] << 8 | (size_t)s[3]);
       s += 4;
       if (len)
         len -= 4;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 042/117] libgcrypt/mpi: Fix possible NULL dereference
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (40 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 041/117] libgcrypt/mpi: Fix possible unintended sign extension Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 043/117] syslinux: Fix memory leak while parsing Daniel Kiper
                   ` (76 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The code in gcry_mpi_scan() assumes that buffer is not NULL, but there
is no explicit check for that, so we add one.

Fixes: CID 73757

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/lib/libgcrypt/mpi/mpicoder.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/grub-core/lib/libgcrypt/mpi/mpicoder.c b/grub-core/lib/libgcrypt/mpi/mpicoder.c
index 7ecad27b2..6fe389165 100644
--- a/grub-core/lib/libgcrypt/mpi/mpicoder.c
+++ b/grub-core/lib/libgcrypt/mpi/mpicoder.c
@@ -379,6 +379,9 @@ gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
   unsigned int len;
   int secure = (buffer && gcry_is_secure (buffer));
 
+  if (!buffer)
+    return gcry_error (GPG_ERR_INV_ARG);
+
   if (format == GCRYMPI_FMT_SSH)
     len = 0;
   else
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 043/117] syslinux: Fix memory leak while parsing
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (41 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 042/117] libgcrypt/mpi: Fix possible NULL dereference Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 044/117] normal/completion: Fix leaking of memory when processing a completion Daniel Kiper
                   ` (75 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

In syslinux_parse_real() the 2 points where return is being called
didn't release the memory stored in buf which is no longer required.

Fixes: CID 176634

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/lib/syslinux_parse.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/grub-core/lib/syslinux_parse.c b/grub-core/lib/syslinux_parse.c
index de9fda06f..ff244d2e0 100644
--- a/grub-core/lib/syslinux_parse.c
+++ b/grub-core/lib/syslinux_parse.c
@@ -737,7 +737,10 @@ syslinux_parse_real (struct syslinux_menu *menu)
 		  && grub_strncasecmp ("help", ptr3, ptr4 - ptr3) == 0))
 	    {
 	      if (helptext (ptr5, file, menu))
-		return 1;
+		{
+		  grub_free (buf);
+		  return 1;
+		}
 	      continue;
 	    }
 
@@ -757,6 +760,7 @@ syslinux_parse_real (struct syslinux_menu *menu)
     }
  fail:
   grub_file_close (file);
+  grub_free (buf);
   return err;
 }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 044/117] normal/completion: Fix leaking of memory when processing a completion
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (42 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 043/117] syslinux: Fix memory leak while parsing Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 045/117] commands/hashsum: Fix a memory leak Daniel Kiper
                   ` (74 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

It is possible for the code to reach the end of the function without
freeing the memory allocated to argv and argc still to be 0.

We should always call grub_free(argv). The grub_free() will handle
a NULL argument correctly if it reaches that code without the memory
being allocated.

Fixes: CID 96672

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/normal/completion.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c
index c07100a8d..18cadfa85 100644
--- a/grub-core/normal/completion.c
+++ b/grub-core/normal/completion.c
@@ -401,8 +401,8 @@ char *
 grub_normal_do_completion (char *buf, int *restore,
 			   void (*hook) (const char *, grub_completion_type_t, int))
 {
-  int argc;
-  char **argv;
+  int argc = 0;
+  char **argv = NULL;
 
   /* Initialize variables.  */
   match = 0;
@@ -517,10 +517,8 @@ grub_normal_do_completion (char *buf, int *restore,
 
  fail:
   if (argc != 0)
-    {
-      grub_free (argv[0]);
-      grub_free (argv);
-    }
+    grub_free (argv[0]);
+  grub_free (argv);
   grub_free (match);
   grub_errno = GRUB_ERR_NONE;
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 045/117] commands/hashsum: Fix a memory leak
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (43 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 044/117] normal/completion: Fix leaking of memory when processing a completion Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 046/117] commands/probe: Fix a resource leak when probing disks Daniel Kiper
                   ` (73 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

check_list() uses grub_file_getline(), which allocates a buffer.
If the hash list file contains invalid lines, the function leaks
this buffer when it returns an error.

Fixes: CID 176635

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/hashsum.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c
index 456ba908b..b8a22b0c8 100644
--- a/grub-core/commands/hashsum.c
+++ b/grub-core/commands/hashsum.c
@@ -128,11 +128,17 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
 	  high = hextoval (*p++);
 	  low = hextoval (*p++);
 	  if (high < 0 || low < 0)
-	    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
+	    {
+	      grub_free (buf);
+	      return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
+	    }
 	  expected[i] = (high << 4) | low;
 	}
       if ((p[0] != ' ' && p[0] != '\t') || (p[1] != ' ' && p[1] != '\t'))
-	return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
+	{
+	  grub_free (buf);
+	  return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
+	}
       p += 2;
       if (prefix)
 	{
@@ -140,7 +146,10 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
 	  
 	  filename = grub_xasprintf ("%s/%s", prefix, p);
 	  if (!filename)
-	    return grub_errno;
+	    {
+	      grub_free (buf);
+	      return grub_errno;
+	    }
 	  file = grub_file_open (filename, GRUB_FILE_TYPE_TO_HASH
 				 | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS
 				    : GRUB_FILE_TYPE_NONE));
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 046/117] commands/probe: Fix a resource leak when probing disks
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (44 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 045/117] commands/hashsum: Fix a memory leak Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 047/117] video/efi_gop: Remove unnecessary return value of grub_video_gop_fill_mode_info() Daniel Kiper
                   ` (72 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

Every other return statement in this code is calling grub_device_close()
to clean up dev before returning. This one should do that too.

Fixes: CID 292443

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/probe.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c
index 573bdf603..e53b61178 100644
--- a/grub-core/commands/probe.c
+++ b/grub-core/commands/probe.c
@@ -111,7 +111,11 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
 	  grub_disk_t disk = grub_disk_open(dev->disk->name);
 
 	  if (!disk)
-	    return grub_errno;
+	    {
+	      grub_device_close (dev);
+	      return grub_errno;
+	    }
+
 	  if (grub_strcmp(dev->disk->partition->partmap->name, "gpt") == 0)
 	    {
 	      struct grub_gpt_partentry entry;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 047/117] video/efi_gop: Remove unnecessary return value of grub_video_gop_fill_mode_info()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (45 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 046/117] commands/probe: Fix a resource leak when probing disks Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 048/117] video/fb/fbfill: Fix potential integer overflow Daniel Kiper
                   ` (71 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The return value of grub_video_gop_fill_mode_info() is never able to be
anything other than GRUB_ERR_NONE. So, rather than continue to return
a value and checking it each time, it is more correct to redefine the
function to not return anything and remove checks of its return value
altogether.

Fixes: CID 96701

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/efi_gop.c | 25 ++++++-------------------
 1 file changed, 6 insertions(+), 19 deletions(-)

diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c
index 7fe0cdabf..b7590dc6c 100644
--- a/grub-core/video/efi_gop.c
+++ b/grub-core/video/efi_gop.c
@@ -235,7 +235,7 @@ grub_video_gop_fill_real_mode_info (unsigned mode,
   return GRUB_ERR_NONE;
 }
 
-static grub_err_t
+static void
 grub_video_gop_fill_mode_info (unsigned mode,
 			       struct grub_efi_gop_mode_info *in,
 			       struct grub_video_mode_info *out)
@@ -260,8 +260,6 @@ grub_video_gop_fill_mode_info (unsigned mode,
   out->blit_format = GRUB_VIDEO_BLIT_FORMAT_BGRA_8888;
   out->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
 		     | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
-
-  return GRUB_ERR_NONE;
 }
 
 static int
@@ -274,7 +272,6 @@ grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info, vo
       grub_efi_uintn_t size;
       grub_efi_status_t status;
       struct grub_efi_gop_mode_info *info = NULL;
-      grub_err_t err;
       struct grub_video_mode_info mode_info;
 	 
       status = efi_call_4 (gop->query_mode, gop, mode, &size, &info);
@@ -285,12 +282,7 @@ grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info, vo
 	  continue;
 	}
 
-      err = grub_video_gop_fill_mode_info (mode, info, &mode_info);
-      if (err)
-	{
-	  grub_errno = GRUB_ERR_NONE;
-	  continue;
-	}
+      grub_video_gop_fill_mode_info (mode, info, &mode_info);
       if (hook (&mode_info, hook_arg))
 	return 1;
     }
@@ -474,13 +466,8 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
 
   info = gop->mode->info;
 
-  err = grub_video_gop_fill_mode_info (gop->mode->mode, info,
-				       &framebuffer.mode_info);
-  if (err)
-    {
-      grub_dprintf ("video", "GOP: couldn't fill mode info\n");
-      return err;
-    }
+  grub_video_gop_fill_mode_info (gop->mode->mode, info,
+				 &framebuffer.mode_info);
 
   framebuffer.ptr = (void *) (grub_addr_t) gop->mode->fb_base;
   framebuffer.offscreen
@@ -494,8 +481,8 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
     {
       grub_dprintf ("video", "GOP: couldn't allocate shadow\n");
       grub_errno = 0;
-      err = grub_video_gop_fill_mode_info (gop->mode->mode, info,
-					   &framebuffer.mode_info);
+      grub_video_gop_fill_mode_info (gop->mode->mode, info,
+				     &framebuffer.mode_info);
       buffer = framebuffer.ptr;
     }
     
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 048/117] video/fb/fbfill: Fix potential integer overflow
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (46 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 047/117] video/efi_gop: Remove unnecessary return value of grub_video_gop_fill_mode_info() Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 049/117] video/fb/video_fb: Fix multiple integer overflows Daniel Kiper
                   ` (70 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The multiplication of 2 unsigned 32-bit integers may overflow before
promotion to unsigned 64-bit. We should ensure that the multiplication
is done with overflow detection. Additionally, use grub_sub() for
subtraction.

Fixes: CID 73640, CID 73697, CID 73702, CID 73823

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/fb/fbfill.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/grub-core/video/fb/fbfill.c b/grub-core/video/fb/fbfill.c
index 11816d07a..a37acd1e2 100644
--- a/grub-core/video/fb/fbfill.c
+++ b/grub-core/video/fb/fbfill.c
@@ -31,6 +31,7 @@
 #include <grub/fbfill.h>
 #include <grub/fbutil.h>
 #include <grub/types.h>
+#include <grub/safemath.h>
 #include <grub/video.h>
 
 /* Generic filler that works for every supported mode.  */
@@ -61,7 +62,9 @@ grub_video_fbfill_direct32 (struct grub_video_fbblit_info *dst,
 
   /* Calculate the number of bytes to advance from the end of one line
      to the beginning of the next line.  */
-  rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+  if (grub_mul (dst->mode_info->bytes_per_pixel, width, &rowskip) ||
+      grub_sub (dst->mode_info->pitch, rowskip, &rowskip))
+    return;
 
   /* Get the start address.  */
   dstptr = grub_video_fb_get_video_ptr (dst, x, y);
@@ -98,7 +101,9 @@ grub_video_fbfill_direct24 (struct grub_video_fbblit_info *dst,
 #endif
   /* Calculate the number of bytes to advance from the end of one line
      to the beginning of the next line.  */
-  rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+  if (grub_mul (dst->mode_info->bytes_per_pixel, width, &rowskip) ||
+      grub_sub (dst->mode_info->pitch, rowskip, &rowskip))
+    return;
 
   /* Get the start address.  */
   dstptr = grub_video_fb_get_video_ptr (dst, x, y);
@@ -131,7 +136,9 @@ grub_video_fbfill_direct16 (struct grub_video_fbblit_info *dst,
 
   /* Calculate the number of bytes to advance from the end of one line
      to the beginning of the next line.  */
-  rowskip = (dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width);
+  if (grub_mul (dst->mode_info->bytes_per_pixel, width, &rowskip) ||
+      grub_sub (dst->mode_info->pitch, rowskip, &rowskip))
+    return;
 
   /* Get the start address.  */
   dstptr = grub_video_fb_get_video_ptr (dst, x, y);
@@ -161,7 +168,9 @@ grub_video_fbfill_direct8 (struct grub_video_fbblit_info *dst,
 
   /* Calculate the number of bytes to advance from the end of one line
      to the beginning of the next line.  */
-  rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width;
+  if (grub_mul (dst->mode_info->bytes_per_pixel, width, &rowskip) ||
+      grub_sub (dst->mode_info->pitch, rowskip, &rowskip))
+    return;
 
   /* Get the start address.  */
   dstptr = grub_video_fb_get_video_ptr (dst, x, y);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
@ 2021-03-02 18:00 Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image Daniel Kiper
                   ` (118 more replies)
  0 siblings, 119 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel
  Cc: 93sam, alexander.burmashev, chrco, chris.coulson, cjwatson,
	corsac, cperry, darren.kenny, dja, eric.snowberg, ilya.okomin,
	ivansprundel, jan.setjeeilers, jaredz, javierm, jerecox,
	john.haxby, joseph.tartaro, julian.klode, kanth.ghatraju, km,
	konrad.wilk, mario.limonciello, mbenatto, mjg59, noamr, nyanko,
	pfsmorigo, phcoder, pjones, rhughes, sajacobu, teddy.reed, tf,
	u.bauer, xnox

Hi all,

The BootHole vulnerability [1][2] announced last year encouraged many people to
take a closer look at the security of boot process in general and the GRUB
bootloader in particular. Due to that, during past few months we were getting
reports of, and also discovering various security flaws in the GRUB ourselves.
You can find the list of most severe ones which got CVEs assigned at the end of
this message. The patch bundle fixing all these issues in the upstream GRUB
contains 117 patches.

In addition, we have been working on a generation number based revocation
scheme termed UEFI Secure Boot Advanced Targeting (SBAT) [3]. This will require
an UEFI dbx release and resigning all the artifacts -- shim, GRUB, kernel,
etc. -- needed to boot the system. This is the same as we did for the BootHole
series of vulnerabilities, but the SBAT work is designed to make this process
much less painful in the future.

Details of exactly what needs updating will be provided by the respective
distros and vendors when updates become available. Here [4] we are listing at
least some links to the messaging known at the time of this posting.

It is important to know that shim and SBAT development is still ongoing.

Full mitigation against all the CVEs will require an updated UEFI revocation
list (dbx) which, in at least some cases, will not allow Secure Boot with
today's boot artifacts. Vendor shims may explicitly permit known older boot
artifacts to boot. At some stage, the dbx on new hardware will be updated.

Updated GRUB2, shim and other boot artifacts from all the affected vendors will
be made available when the embargo lifts or some time thereafter. An updated
dbx from the various affected vendors will also ship, although possibly not at
the same time. The new Microsoft dbx will be provided for download here [5].

I am posting all the GRUB2 upstream patches which fixes all security bugs found
and reported up until now. Major Linux distros carry or will carry soon one
form or another of these patches. Now all the GRUB2 upstream patches are in
the GRUB2 git repository [6] too.

In particular I would like to thank, in alphabetical order, the following
people who were working really hard on the GRUB, shim and other things related
to these issues:
  - Alexander Burmashev (Oracle),
  - Chris Co (Microsoft),
  - Chris Coulson (Canonical),
  - Cliff Perry (Red Hat),
  - Colin Watson (Debian),
  - D. Jared Dominguez (Red Hat),
  - Daniel Axtens (IBM),
  - Darren Kenny (Oracle),
  - Dimitri John Ledkov (Canonical),
  - Eric Snowberg (Oracle),
  - Ilja Van Sprundel (IOActive),
  - Ilya Okomin (Oracle),
  - Jan Setje-Eilers (Oracle),
  - Javier Martinez Canillas (Red Hat),
  - Jeremiah Cox (Microsoft),
  - John Haxby (Oracle),
  - Jordan Geurten (Microsoft),
  - Joseph Tartaro (IOActive),
  - Julian Andres Klode (Canonical),
  - Marco A Benatto (Red Hat),
  - Mario Limonciello (Dell),
  - Mathieu Trudel-Lapierre (Stack8),
  - Matthew Garrett (Google),
  - Máté Kukri,
  - Noam Rathaus (SSD Secure Disclosure),
  - NyankoSec (SSD Secure Disclosure),
  - Paulo Flabiano Smorigo (Canonical),
  - Peter Jones (Red Hat),
  - Richard Hughes (Red Hat),
  - Sarah Jacobus (Microsoft),
  - Steve McIntyre (Debian),
  - Teddy Reed,
  - Thomas Frauendorfer (Miray Software),
  - Ulrich Bauer (Miray Software),
  - Yves-Alexis Perez (Debian).

We would not be able to succeed without all your hard work.

It was very big pleasure to work with you all.

Thank you!

Daniel

[1] https://lists.gnu.org/archive/html/grub-devel/2020-07/msg00034.html

[2] https://www.eclypsium.com/2020/07/29/theres-a-hole-in-the-boot/

[3] https://github.com/rhboot/shim/blob/main/SBAT.md

[4] Canonical: https://wiki.ubuntu.com/SecurityTeam/KnowledgeBase/GRUB2SecureBootBypass2021
    Debian:    https://www.debian.org/security/2021-GRUB-UEFI-SecureBoot
    Red Hat:   https://access.redhat.com/security/vulnerabilities/RHSB-2021-003
    SUSE:      https://www.suse.com/support/kb/doc/?id=000019892

[5] https://uefi.org/revocationlistfile

[6] https://git.savannah.gnu.org/gitweb/?p=grub.git&view=view+git+repository
    https://git.savannah.gnu.org/git/grub.git

*******************************************************************************

CVE-2020-14372 grub2: The acpi command allows privileged user to load crafted
               ACPI tables when Secure Boot is enabled
CWE-184
7.5/CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

GRUB2 enables the use of the command acpi even when Secure Boot is signaled by
the firmware. An attacker with local root privileges to can drop a small SSDT
in /boot/efi and modify grub.cfg to instruct grub to load said SSDT. The SSDT
then gets run by the kernel and it overwrites the kernel lock down configuration
enabling the attacker to load unsigned kernel modules and kexec unsigned code.

Reported-by: Máté Kukri

*******************************************************************************

CVE-2020-25632 grub2: Use-after-free in rmmod command
CWE-416
7.5/CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

The rmmod implementation for GRUB2 is flawed, allowing an attacker to unload
a module used as dependency without checking if any other dependent module is
still loaded. This leads to an use-after-free scenario possibly allowing an
attacker to execute arbitrary code and by-pass Secure Boot protections.

Reported-by: Chris Coulson (Canonical)

*******************************************************************************

CVE-2020-25647 grub2: Out-of-bound write in grub_usb_device_initialize()
CWE-787
6.9/CVSS:3.1/AV:P/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

grub_usb_device_initialize() is called to handle USB device initialization. It
reads out the descriptors it needs from the USB device and uses that data to
fill in some USB data structures. grub_usb_device_initialize() performs very
little bounds checking and simply assumes the USB device provides sane values.
This behavior can trigger memory corruption. If properly exploited, this would
lead to arbitrary code execution allowing the attacker to by-pass Secure Boot
mechanism.

Reported-by: Joseph Tartaro (IOActive) and Ilja van Sprundel (IOActive)

*******************************************************************************

CVE-2020-27749 grub2: Stack buffer overflow in grub_parser_split_cmdline
CWE-121
7.5/CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

grub_parser_split_cmdline() expands variable names present in the supplied
command line in to their corresponding variable contents and uses a 1kB stack
buffer for temporary storage without sufficient bounds checking. If the
function is called with a command line that references a variable with a
sufficiently large payload, it is possible to overflow the stack buffer,
corrupt the stack frame and control execution. An attacker may use this to
circumvent Secure Boot protections.

Reported-by: Chris Coulson (Canonical)

*******************************************************************************

CVE-2020-27779 grub2: The cutmem command allows privileged user to remove
               memory regions when Secure Boot is enabled
CWE-285
7.5/CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

The GRUB2's cutmem command does not honor Secure Boot locking. This allows an
privileged attacker to remove address ranges from memory creating an
opportunity to circumvent Secure Boot protections after proper triage about
grub's memory layout.

Reported-by: Teddy Reed

*******************************************************************************

CVE-2021-3418 - grub2: GRUB 2.05 reintroduced CVE-2020-15705
CWE-281
6.4/CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H

The GRUB2 upstream reintroduced the CVE-2020-15705. This refers to a distro
specific flaw which made upstream in the mentioned version.

If certificates that signed GRUB2 are installed into db, GRUB2 can be booted
directly. It will then boot any kernel without signature validation. The booted
kernel will think it was booted in Secure Boot mode and will implement lock
down, yet it could have been tampered.

This flaw only affects upstream and distributions using the shim_lock verifier.

Reported-by: Dimitri John Ledkov (Canonical)

*******************************************************************************

CVE-2021-20225 grub2: Heap out-of-bounds write in short form option parser
CWE-787
7.5/CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

The option parser in GRUB2 allows an attacker to write past the end of
a heap-allocated buffer by calling certain commands with a large number
of specific short forms of options.

Reported-by: Daniel Axtens (IBM)

*******************************************************************************

CVE-2021-20233 grub2: Heap out-of-bound write due to mis-calculation of
               space required for quoting
CWE-787
7.5/CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H

There's a flaw on GRUB2 menu rendering code setparam_prefix() in the menu
rendering code performs a length calculation on the assumption that expressing
a quoted single quote will require 3 characters, while it actually requires
4 characters. This allow an attacker to corrupt memory by one byte for each
quote in the input.

Reported-by: Daniel Axtens (IBM)

*******************************************************************************

 acinclude.m4                                       |  38 ++-
 bootstrap.conf                                     |   3 +-
 conf/Makefile.common                               |   2 +
 conf/Makefile.extra-dist                           |   5 +
 configure.ac                                       |  44 ++-
 docs/grub-dev.texi                                 |  27 ++
 docs/grub.texi                                     | 106 +++++--
 grub-core/Makefile.am                              |   7 +-
 grub-core/Makefile.core.def                        |  14 +-
 grub-core/bus/usb/usb.c                            |  15 +-
 grub-core/commands/acpi.c                          |  15 +-
 grub-core/commands/efi/loadbios.c                  |  16 +-
 grub-core/commands/efi/shim_lock.c                 | 133 ---------
 grub-core/commands/extcmd.c                        |  23 ++
 grub-core/commands/hashsum.c                       |  15 +-
 grub-core/commands/hdparm.c                        |   6 +-
 grub-core/commands/i386/wrmsr.c                    |   5 +-
 grub-core/commands/iorw.c                          |  19 +-
 grub-core/commands/ls.c                            |   2 +-
 grub-core/commands/memrw.c                         |  19 +-
 grub-core/commands/menuentry.c                     |   2 +-
 grub-core/commands/minicmd.c                       |   7 +-
 grub-core/commands/probe.c                         |   6 +-
 grub-core/commands/setpci.c                        |   8 +-
 grub-core/disk/cryptodisk.c                        |   8 +-
 grub-core/disk/ldm.c                               |  62 +++-
 grub-core/disk/lvm.c                               | 101 ++++++-
 grub-core/fs/affs.c                                |  18 +-
 grub-core/fs/btrfs.c                               |   7 +-
 grub-core/fs/fshelp.c                              |  12 +
 grub-core/fs/hfs.c                                 |   7 +-
 grub-core/fs/hfsplus.c                             |  27 ++
 grub-core/fs/jfs.c                                 |  19 +-
 grub-core/fs/nilfs2.c                              |  56 ++--
 grub-core/fs/sfs.c                                 |   9 +-
 grub-core/fs/zfs/zfs.c                             |  43 ++-
 grub-core/fs/zfs/zfsinfo.c                         |   4 +-
 grub-core/gdb/gdb.c                                |  32 ++-
 grub-core/gfxmenu/gui_label.c                      |   4 +
 grub-core/gfxmenu/gui_list.c                       |   2 +-
 grub-core/gfxmenu/gui_progress_bar.c               |   3 +
 grub-core/io/gzio.c                                |  44 ++-
 grub-core/io/lzopio.c                              |   4 -
 grub-core/kern/buffer.c                            | 117 ++++++++
 grub-core/kern/command.c                           |  24 ++
 grub-core/kern/dl.c                                |   9 +
 grub-core/kern/efi/efi.c                           |   1 +
 grub-core/kern/efi/init.c                          |  66 +++++
 grub-core/kern/efi/mm.c                            |  19 +-
 grub-core/kern/efi/sb.c                            |  79 +++++
 grub-core/kern/lockdown.c                          |  84 ++++++
 grub-core/kern/main.c                              |   4 +
 grub-core/kern/misc.c                              | 110 ++++++-
 grub-core/kern/mm.c                                |   2 +-
 grub-core/kern/parser.c                            | 203 ++++++++-----
 grub-core/kern/partition.c                         |   5 +-
 grub-core/{commands => kern}/verifiers.c           |   8 +-
 grub-core/lib/arg.c                                |  13 +
 .../lib/gnulib-patches/fix-null-state-deref.patch  |  12 +
 .../gnulib-patches/fix-regcomp-uninit-token.patch  |  15 +
 .../gnulib-patches/fix-regexec-null-deref.patch    |  12 +
 .../lib/gnulib-patches/fix-uninit-structure.patch  |  11 +
 .../lib/gnulib-patches/fix-unused-value.patch      |  14 +
 grub-core/lib/libgcrypt/mpi/mpicoder.c             |   5 +-
 grub-core/lib/syslinux_parse.c                     |   6 +-
 grub-core/lib/zstd/zstd_decompress.c               |   2 +-
 grub-core/loader/arm/linux.c                       |   6 +-
 grub-core/loader/efi/fdt.c                         |   4 +-
 grub-core/loader/i386/bsd.c                        |   4 +-
 grub-core/loader/xnu.c                             |  65 +++--
 grub-core/mmap/mmap.c                              |  15 +-
 grub-core/net/net.c                                |   9 +-
 grub-core/net/tftp.c                               |   1 +
 grub-core/normal/completion.c                      |  10 +-
 grub-core/script/execute.c                         |   7 +-
 grub-core/term/gfxterm.c                           |   9 +
 grub-core/video/efi_gop.c                          |  25 +-
 grub-core/video/fb/fbfill.c                        |  17 +-
 grub-core/video/fb/video_fb.c                      |  60 ++--
 grub-core/video/readers/jpeg.c                     |  26 ++
 include/grub/buffer.h                              | 144 ++++++++++
 include/grub/command.h                             |   5 +
 include/grub/dl.h                                  |   8 +-
 include/grub/efi/api.h                             |  19 ++
 include/grub/efi/sb.h                              |   3 +
 include/grub/extcmd.h                              |   7 +
 include/grub/hfsplus.h                             |   2 +
 include/grub/kernel.h                              |   3 +-
 include/grub/lockdown.h                            |  44 +++
 include/grub/misc.h                                |  16 ++
 include/grub/stack_protector.h                     |  30 ++
 include/grub/usb.h                                 |  10 +-
 include/grub/util/install.h                        |  11 +-
 include/grub/util/mkimage.h                        |   1 +
 include/grub/verify.h                              |   9 +-
 util/glue-efi.c                                    |  14 +-
 util/grub-editenv.c                                |   8 +-
 util/grub-install-common.c                         |  22 +-
 util/grub-install.c                                |   4 +
 util/grub-mkimage.c                                |  21 +-
 util/grub.d/30_os-prober.in                        |   5 +-
 util/mkimage.c                                     | 317 +++++++++++----------
 102 files changed, 2115 insertions(+), 666 deletions(-)

Alex Burmashev (1):
      templates: Disable the os-prober by default

Chris Coulson (8):
      commands/hashsum: Fix a memory leak
      kern/parser: Fix a memory leak
      kern/parser: Introduce process_char() helper
      kern/parser: Introduce terminate_arg() helper
      kern/parser: Refactor grub_parser_split_cmdline() cleanup
      kern/buffer: Add variable sized heap buffer
      kern/parser: Fix a stack buffer overflow
      kern/efi: Add initial stack protector implementation

Daniel Axtens (35):
      script/execute: Fix NULL dereference in grub_script_execute_cmdline()
      commands/ls: Require device_name is not NULL before printing
      script/execute: Avoid crash when using "$#" outside a function scope
      lib/arg: Block repeated short options that require an argument
      script/execute: Don't crash on a "for" loop with no items
      commands/menuentry: Fix quoting in setparams_prefix()
      kern/misc: Always set *end in grub_strtoull()
      video/readers/jpeg: Catch files with unsupported quantization or Huffman tables
      video/readers/jpeg: Catch OOB reads/writes in grub_jpeg_decode_du()
      video/readers/jpeg: Don't decode data before start of stream
      term/gfxterm: Don't set up a font with glyphs that are too big
      fs/fshelp: Catch impermissibly large block sizes in read helper
      fs/hfsplus: Don't fetch a key beyond the end of the node
      fs/hfsplus: Don't use uninitialized data on corrupt filesystems
      fs/hfs: Disable under lockdown
      fs/sfs: Fix over-read of root object name
      fs/jfs: Do not move to leaf level if name length is negative
      fs/jfs: Limit the extents that getblk() can consider
      fs/jfs: Catch infinite recursion
      fs/nilfs2: Reject too-large keys
      fs/nilfs2: Don't search children if provided number is too large
      fs/nilfs2: Properly bail on errors in grub_nilfs2_btree_node_lookup()
      io/gzio: Bail if gzio->tl/td is NULL
      io/gzio: Add init_dynamic_block() clean up if unpacking codes fails
      io/gzio: Catch missing values in huft_build() and bail
      io/gzio: Zero gzio->tl/td in init_dynamic_block() if huft_build() fails
      disk/lvm: Don't go beyond the end of the data we read from disk
      disk/lvm: Don't blast past the end of the circular metadata buffer
      disk/lvm: Bail on missing PV list
      disk/lvm: Do not crash if an expected string is not found
      disk/lvm: Do not overread metadata
      disk/lvm: Sanitize rlocn->offset to prevent wild read
      disk/lvm: Do not allow a LV to be it's own segment's node's LV
      fs/btrfs: Validate the number of stripes/parities in RAID5/6
      fs/btrfs: Squash some uninitialized reads

Daniel Kiper (1):
      util/grub-install: Fix NULL pointer dereferences

Darren Kenny (36):
      mmap: Fix memory leak when iterating over mapped memory
      net/net: Fix possible dereference to of a NULL pointer
      net/tftp: Fix dangling memory pointer
      kern/parser: Fix resource leak if argc == 0
      kern/efi: Fix memory leak on failure
      kern/efi/mm: Fix possible NULL pointer dereference
      gnulib/regexec: Resolve unused variable
      gnulib/regcomp: Fix uninitialized token structure
      gnulib/argp-help: Fix dereference of a possibly NULL state
      gnulib/regexec: Fix possible null-dereference
      gnulib/regcomp: Fix uninitialized re_token
      io/lzopio: Resolve unnecessary self-assignment errors
      zstd: Initialize seq_t structure fully
      kern/partition: Check for NULL before dereferencing input string
      disk/ldm: Fix memory leak on uninserted lv references
      disk/cryptodisk: Fix potential integer overflow
      hfsplus: Check that the volume name length is valid
      zfs: Fix possible negative shift operation
      zfs: Fix possible integer overflows
      zfsinfo: Correct a check for error allocating memory
      affs: Fix memory leaks
      libgcrypt/mpi: Fix possible unintended sign extension
      libgcrypt/mpi: Fix possible NULL dereference
      syslinux: Fix memory leak while parsing
      normal/completion: Fix leaking of memory when processing a completion
      commands/probe: Fix a resource leak when probing disks
      video/efi_gop: Remove unnecessary return value of grub_video_gop_fill_mode_info()
      video/fb/fbfill: Fix potential integer overflow
      video/fb/video_fb: Fix multiple integer overflows
      video/fb/video_fb: Fix possible integer overflow
      video/readers/jpeg: Test for an invalid next marker reference from a jpeg file
      gfxmenu/gui_list: Remove code that coverity is flagging as dead
      loader/bsd: Check for NULL arg up-front
      loader/xnu: Fix memory leak
      util/grub-editenv: Fix incorrect casting of a signed value
      util/glue-efi: Fix incorrect use of a possibly negative value

Dimitri John Ledkov (2):
      grub-install-common: Add --sbat option
      shim_lock: Only skip loading shim_lock verifier with explicit consent

Javier Martinez Canillas (15):
      kern: Add lockdown support
      kern/lockdown: Set a variable if the GRUB is locked down
      efi: Lockdown the GRUB when the UEFI Secure Boot is enabled
      efi: Use grub_is_lockdown() instead of hardcoding a disabled modules list
      acpi: Don't register the acpi command when locked down
      mmap: Don't register cutmem and badram commands when lockdown is enforced
      commands: Restrict commands that can load BIOS or DT blobs when locked down
      commands/setpci: Restrict setpci command when locked down
      commands/hdparm: Restrict hdparm command when locked down
      gdb: Restrict GDB access when locked down
      loader/xnu: Don't allow loading extension and packages when locked down
      docs: Document the cutmem command
      dl: Only allow unloading modules that are not dependencies
      usb: Avoid possible out-of-bound accesses caused by malicious devices
      util/mkimage: Remove unused code to add BSS section

Marco A Benatto (5):
      verifiers: Move verifiers API to kernel image
      efi: Move the shim_lock verifier to the GRUB core
      disk/ldm: Make sure comp data is freed before exiting from make_vg()
      loader/xnu: Free driverkey data when an error is detected in grub_xnu_writetree_toheap()
      kern/mm: Fix grub_debug_calloc() compilation error

Paulo Flabiano Smorigo (3):
      disk/ldm: If failed then free vg variable too
      zfs: Fix resource leaks while constructing path
      loader/xnu: Check if pointer is NULL before using it

Peter Jones (7):
      util/mkimage: Use grub_host_to_target32() instead of grub_cpu_to_le32()
      util/mkimage: Always use grub_host_to_target32() to initialize PE stack and heap stuff
      util/mkimage: Unify more of the PE32 and PE32+ header set-up
      util/mkimage: Reorder PE optional header fields set-up
      util/mkimage: Improve data_size value calculation
      util/mkimage: Refactor section setup to use a helper
      util/mkimage: Add an option to import SBAT metadata into a .sbat section

Thomas Frauendorfer | Miray Software (4):
      kern/misc: Split parse_printf_args() into format parsing and va_list handling
      kern/misc: Add STRING type for internal printf() format handling
      kern/misc: Add function to check printf() format against expected format
      gfxmenu/gui: Check printf() format in the gui_progress_bar and gui_label


^ permalink raw reply	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 049/117] video/fb/video_fb: Fix multiple integer overflows
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (47 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 048/117] video/fb/fbfill: Fix potential integer overflow Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 050/117] video/fb/video_fb: Fix possible integer overflow Daniel Kiper
                   ` (69 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The calculation of the unsigned 64-bit value is being generated by
multiplying 2, signed or unsigned, 32-bit integers which may overflow
before promotion to unsigned 64-bit. Fix all of them.

Fixes: CID 73703, CID 73767, CID 73833

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/fb/video_fb.c | 52 ++++++++++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 16 deletions(-)

diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c
index 1a602c8b2..1c9a138dc 100644
--- a/grub-core/video/fb/video_fb.c
+++ b/grub-core/video/fb/video_fb.c
@@ -25,6 +25,7 @@
 #include <grub/fbutil.h>
 #include <grub/bitmap.h>
 #include <grub/dl.h>
+#include <grub/safemath.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -1417,15 +1418,23 @@ doublebuf_blit_update_screen (void)
 {
   if (framebuffer.current_dirty.first_line
       <= framebuffer.current_dirty.last_line)
-    grub_memcpy ((char *) framebuffer.pages[0]
-		 + framebuffer.current_dirty.first_line
-		 * framebuffer.back_target->mode_info.pitch,
-		 (char *) framebuffer.back_target->data
-		 + framebuffer.current_dirty.first_line
-		 * framebuffer.back_target->mode_info.pitch,
-		 framebuffer.back_target->mode_info.pitch
-		 * (framebuffer.current_dirty.last_line
-		    - framebuffer.current_dirty.first_line));
+    {
+      grub_size_t copy_size;
+
+      if (grub_sub (framebuffer.current_dirty.last_line,
+		    framebuffer.current_dirty.first_line, &copy_size) ||
+	  grub_mul (framebuffer.back_target->mode_info.pitch, copy_size, &copy_size))
+	{
+	  /* Shouldn't happen, but if it does we've a bug. */
+	  return GRUB_ERR_BUG;
+	}
+
+      grub_memcpy ((char *) framebuffer.pages[0] + framebuffer.current_dirty.first_line *
+		   framebuffer.back_target->mode_info.pitch,
+		   (char *) framebuffer.back_target->data + framebuffer.current_dirty.first_line *
+		   framebuffer.back_target->mode_info.pitch,
+		   copy_size);
+    }
   framebuffer.current_dirty.first_line
     = framebuffer.back_target->mode_info.height;
   framebuffer.current_dirty.last_line = 0;
@@ -1439,7 +1448,7 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **back,
 				   volatile void *framebuf)
 {
   grub_err_t err;
-  grub_size_t page_size = mode_info.pitch * mode_info.height;
+  grub_size_t page_size = (grub_size_t) mode_info.pitch * mode_info.height;
 
   framebuffer.offscreen_buffer = grub_zalloc (page_size);
   if (! framebuffer.offscreen_buffer)
@@ -1482,12 +1491,23 @@ doublebuf_pageflipping_update_screen (void)
     last_line = framebuffer.previous_dirty.last_line;
 
   if (first_line <= last_line)
-    grub_memcpy ((char *) framebuffer.pages[framebuffer.render_page]
-		 + first_line * framebuffer.back_target->mode_info.pitch,
-		 (char *) framebuffer.back_target->data
-		 + first_line * framebuffer.back_target->mode_info.pitch,
-		 framebuffer.back_target->mode_info.pitch
-		 * (last_line - first_line));
+    {
+      grub_size_t copy_size;
+
+      if (grub_sub (last_line, first_line, &copy_size) ||
+	  grub_mul (framebuffer.back_target->mode_info.pitch, copy_size, &copy_size))
+	{
+	  /* Shouldn't happen, but if it does we've a bug. */
+	  return GRUB_ERR_BUG;
+	}
+
+      grub_memcpy ((char *) framebuffer.pages[framebuffer.render_page] + first_line *
+		   framebuffer.back_target->mode_info.pitch,
+		   (char *) framebuffer.back_target->data + first_line *
+		   framebuffer.back_target->mode_info.pitch,
+		   copy_size);
+    }
+
   framebuffer.previous_dirty = framebuffer.current_dirty;
   framebuffer.current_dirty.first_line
     = framebuffer.back_target->mode_info.height;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 050/117] video/fb/video_fb: Fix possible integer overflow
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (48 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 049/117] video/fb/video_fb: Fix multiple integer overflows Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 051/117] video/readers/jpeg: Test for an invalid next marker reference from a jpeg file Daniel Kiper
                   ` (68 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

It is minimal possibility that the values being used here will overflow.
So, change the code to use the safemath function grub_mul() to ensure
that doesn't happen.

Fixes: CID 73761

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/fb/video_fb.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c
index 1c9a138dc..ae6b89f9a 100644
--- a/grub-core/video/fb/video_fb.c
+++ b/grub-core/video/fb/video_fb.c
@@ -1537,7 +1537,13 @@ doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info,
 			     volatile void *page1_ptr)
 {
   grub_err_t err;
-  grub_size_t page_size = mode_info->pitch * mode_info->height;
+  grub_size_t page_size = 0;
+
+  if (grub_mul (mode_info->pitch, mode_info->height, &page_size))
+    {
+      /* Shouldn't happen, but if it does we've a bug. */
+      return GRUB_ERR_BUG;
+    }
 
   framebuffer.offscreen_buffer = grub_malloc (page_size);
   if (! framebuffer.offscreen_buffer)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 051/117] video/readers/jpeg: Test for an invalid next marker reference from a jpeg file
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (49 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 050/117] video/fb/video_fb: Fix possible integer overflow Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:00 ` [SECURITY PATCH 052/117] gfxmenu/gui_list: Remove code that coverity is flagging as dead Daniel Kiper
                   ` (67 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

While it may never happen, and potentially could be caught at the end of
the function, it is worth checking up front for a bad reference to the
next marker just in case of a maliciously crafted file being provided.

Fixes: CID 73694

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/readers/jpeg.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index 31359a4c9..0b6ce3cee 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -253,6 +253,12 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
   next_marker = data->file->offset;
   next_marker += grub_jpeg_get_word (data);
 
+  if (next_marker > data->file->size)
+    {
+      /* Should never be set beyond the size of the file. */
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid next reference");
+    }
+
   while (data->file->offset + sizeof (data->quan_table[id]) + 1
 	 <= next_marker)
     {
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 052/117] gfxmenu/gui_list: Remove code that coverity is flagging as dead
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (50 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 051/117] video/readers/jpeg: Test for an invalid next marker reference from a jpeg file Daniel Kiper
@ 2021-03-02 18:00 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 053/117] loader/bsd: Check for NULL arg up-front Daniel Kiper
                   ` (66 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:00 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The test of value for NULL before calling grub_strdup() is not required,
since the if condition prior to this has already tested for value being
NULL and cannot reach this code if it is.

Fixes: CID 73659

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/gfxmenu/gui_list.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c
index 01477cdf2..df334a6c5 100644
--- a/grub-core/gfxmenu/gui_list.c
+++ b/grub-core/gfxmenu/gui_list.c
@@ -771,7 +771,7 @@ list_set_property (void *vself, const char *name, const char *value)
         {
           self->need_to_recreate_boxes = 1;
           grub_free (self->selected_item_box_pattern);
-          self->selected_item_box_pattern = value ? grub_strdup (value) : 0;
+          self->selected_item_box_pattern = grub_strdup (value);
           self->selected_item_box_pattern_inherit = 0;
         }
     }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 053/117] loader/bsd: Check for NULL arg up-front
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (51 preceding siblings ...)
  2021-03-02 18:00 ` [SECURITY PATCH 052/117] gfxmenu/gui_list: Remove code that coverity is flagging as dead Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 054/117] loader/xnu: Fix memory leak Daniel Kiper
                   ` (65 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The code in the next block suggests that it is possible for .set to be
true but .arg may still be NULL.

This code assumes that it is never NULL, yet later is testing if it is
NULL - that is inconsistent.

So we should check first if .arg is not NULL, and remove this check that
is being flagged by Coverity since it is no longer required.

Fixes: CID 292471

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/i386/bsd.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
index f5bf7f89e..d89ff0a7a 100644
--- a/grub-core/loader/i386/bsd.c
+++ b/grub-core/loader/i386/bsd.c
@@ -1605,7 +1605,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
   kernel_type = KERNEL_TYPE_OPENBSD;
   bootflags = grub_bsd_parse_flags (ctxt->state, openbsd_flags);
 
-  if (ctxt->state[OPENBSD_ROOT_ARG].set)
+  if (ctxt->state[OPENBSD_ROOT_ARG].set && ctxt->state[OPENBSD_ROOT_ARG].arg != NULL)
     {
       const char *arg = ctxt->state[OPENBSD_ROOT_ARG].arg;
       unsigned type, unit, part;
@@ -1622,7 +1622,7 @@ grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
 			   "unknown disk type name");
 
       unit = grub_strtoul (arg, &arg, 10);
-      if (! (arg && *arg >= 'a' && *arg <= 'z'))
+      if (! (*arg >= 'a' && *arg <= 'z'))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT,
 			   "only device specifications of form "
 			   "<type><number><lowercase letter> are supported");
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 054/117] loader/xnu: Fix memory leak
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (52 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 053/117] loader/bsd: Check for NULL arg up-front Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 055/117] loader/xnu: Free driverkey data when an error is detected in grub_xnu_writetree_toheap() Daniel Kiper
                   ` (64 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The code here is finished with the memory stored in name, but it only
frees it if there curvalue is valid, while it could actually free it
regardless.

The fix is a simple relocation of the grub_free() to before the test
of curvalue.

Fixes: CID 96646

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/xnu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index 44fd5a979..eb1446251 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -1391,9 +1391,9 @@ grub_xnu_fill_devicetree (void)
     name[len] = 0;
 
     curvalue = grub_xnu_create_value (curkey, name);
-    if (!curvalue)
-      return grub_errno;
     grub_free (name);
+    if (!curvalue)
+      return grub_errno;
    
     data = grub_malloc (grub_strlen (var->value) + 1);
     if (!data)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 055/117] loader/xnu: Free driverkey data when an error is detected in grub_xnu_writetree_toheap()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (53 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 054/117] loader/xnu: Fix memory leak Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 056/117] loader/xnu: Check if pointer is NULL before using it Daniel Kiper
                   ` (63 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Marco A Benatto <mbenatto@redhat.com>

... to avoid memory leaks.

Fixes: CID 96640

Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/xnu.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index eb1446251..1a590dbc0 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -227,26 +227,33 @@ grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size)
   if (! memorymap)
     return grub_errno;
 
-  driverkey = (struct grub_xnu_devtree_key *) grub_malloc (sizeof (*driverkey));
+  driverkey = (struct grub_xnu_devtree_key *) grub_zalloc (sizeof (*driverkey));
   if (! driverkey)
     return grub_errno;
   driverkey->name = grub_strdup ("DeviceTree");
   if (! driverkey->name)
-    return grub_errno;
+    {
+      err = grub_errno;
+      goto fail;
+    }
+
   driverkey->datasize = sizeof (*extdesc);
   driverkey->next = memorymap->first_child;
   memorymap->first_child = driverkey;
   driverkey->data = extdesc
     = (struct grub_xnu_extdesc *) grub_malloc (sizeof (*extdesc));
   if (! driverkey->data)
-    return grub_errno;
+    {
+      err = grub_errno;
+      goto fail;
+    }
 
   /* Allocate the space based on the size with dummy value. */
   *size = grub_xnu_writetree_get_size (grub_xnu_devtree_root, "/");
   err = grub_xnu_heap_malloc (ALIGN_UP (*size + 1, GRUB_XNU_PAGESIZE),
 			      &src, target);
   if (err)
-    return err;
+    goto fail;
 
   /* Put real data in the dummy. */
   extdesc->addr = *target;
@@ -255,6 +262,15 @@ grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size)
   /* Write the tree to heap. */
   grub_xnu_writetree_toheap_real (src, grub_xnu_devtree_root, "/");
   return GRUB_ERR_NONE;
+
+ fail:
+  memorymap->first_child = NULL;
+
+  grub_free (driverkey->data);
+  grub_free (driverkey->name);
+  grub_free (driverkey);
+
+  return err;
 }
 
 /* Find a key or value in parent key. */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 056/117] loader/xnu: Check if pointer is NULL before using it
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (54 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 055/117] loader/xnu: Free driverkey data when an error is detected in grub_xnu_writetree_toheap() Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 057/117] util/grub-install: Fix NULL pointer dereferences Daniel Kiper
                   ` (62 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>

Fixes: CID 73654

Signed-off-by: Paulo Flabiano Smorigo <pfsmorigo@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/loader/xnu.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index 1a590dbc0..1c0cf6a43 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -670,6 +670,9 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile,
   char *name, *nameend;
   int namelen;
 
+  if (infoplistname == NULL)
+    return grub_error (GRUB_ERR_BAD_FILENAME, N_("missing p-list filename"));
+
   name = get_name_ptr (infoplistname);
   nameend = grub_strchr (name, '/');
 
@@ -701,10 +704,7 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile,
   else
     macho = 0;
 
-  if (infoplistname)
-    infoplist = grub_file_open (infoplistname, GRUB_FILE_TYPE_XNU_INFO_PLIST);
-  else
-    infoplist = 0;
+  infoplist = grub_file_open (infoplistname, GRUB_FILE_TYPE_XNU_INFO_PLIST);
   grub_errno = GRUB_ERR_NONE;
   if (infoplist)
     {
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 057/117] util/grub-install: Fix NULL pointer dereferences
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (55 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 056/117] loader/xnu: Check if pointer is NULL before using it Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 058/117] util/grub-editenv: Fix incorrect casting of a signed value Daniel Kiper
                   ` (61 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

Two grub_device_open() calls does not have associated NULL checks
for returned values. Fix that and appease the Coverity.

Fixes: CID 314583

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
---
 util/grub-install.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/util/grub-install.c b/util/grub-install.c
index 79fc4b937..a0babe3ef 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1784,6 +1784,8 @@ main (int argc, char *argv[])
 	  fill_core_services (core_services);
 
 	  ins_dev = grub_device_open (install_drive);
+	  if (ins_dev == NULL)
+	    grub_util_error ("%s", grub_errmsg);
 
 	  bless (ins_dev, core_services, 0);
 
@@ -1884,6 +1886,8 @@ main (int argc, char *argv[])
 	  fill_core_services(core_services);
 
 	  ins_dev = grub_device_open (install_drive);
+	  if (ins_dev == NULL)
+	    grub_util_error ("%s", grub_errmsg);
 
 	  bless (ins_dev, boot_efi, 1);
 	  if (!removable && update_nvram)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 058/117] util/grub-editenv: Fix incorrect casting of a signed value
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (56 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 057/117] util/grub-install: Fix NULL pointer dereferences Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 059/117] util/glue-efi: Fix incorrect use of a possibly negative value Daniel Kiper
                   ` (60 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

The return value of ftell() may be negative (-1) on error. While it is
probably unlikely to occur, we should not blindly cast to an unsigned
value without first testing that it is not negative.

Fixes: CID 73856

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/grub-editenv.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/util/grub-editenv.c b/util/grub-editenv.c
index f3662c95b..db6f187cc 100644
--- a/util/grub-editenv.c
+++ b/util/grub-editenv.c
@@ -125,6 +125,7 @@ open_envblk_file (const char *name)
 {
   FILE *fp;
   char *buf;
+  long loc;
   size_t size;
   grub_envblk_t envblk;
 
@@ -143,7 +144,12 @@ open_envblk_file (const char *name)
     grub_util_error (_("cannot seek `%s': %s"), name,
 		     strerror (errno));
 
-  size = (size_t) ftell (fp);
+  loc = ftell (fp);
+  if (loc < 0)
+    grub_util_error (_("cannot get file location `%s': %s"), name,
+		     strerror (errno));
+
+  size = (size_t) loc;
 
   if (fseek (fp, 0, SEEK_SET) < 0)
     grub_util_error (_("cannot seek `%s': %s"), name,
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 059/117] util/glue-efi: Fix incorrect use of a possibly negative value
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (57 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 058/117] util/grub-editenv: Fix incorrect casting of a signed value Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 060/117] script/execute: Fix NULL dereference in grub_script_execute_cmdline() Daniel Kiper
                   ` (59 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Darren Kenny <darren.kenny@oracle.com>

It is possible for the ftell() function to return a negative value,
although it is fairly unlikely here, we should be checking for
a negative value before we assign it to an unsigned value.

Fixes: CID 73744

Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/glue-efi.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/util/glue-efi.c b/util/glue-efi.c
index 68f53168b..de0fa6d33 100644
--- a/util/glue-efi.c
+++ b/util/glue-efi.c
@@ -39,13 +39,23 @@ write_fat (FILE *in32, FILE *in64, FILE *out, const char *out_filename,
   struct grub_macho_fat_header head;
   struct grub_macho_fat_arch arch32, arch64;
   grub_uint32_t size32, size64;
+  long size;
   char *buf;
 
   fseek (in32, 0, SEEK_END);
-  size32 = ftell (in32);
+  size = ftell (in32);
+  if (size < 0)
+    grub_util_error ("cannot get end of input file '%s': %s",
+		     name32, strerror (errno));
+  size32 = (grub_uint32_t) size;
   fseek (in32, 0, SEEK_SET);
+
   fseek (in64, 0, SEEK_END);
-  size64 = ftell (in64);
+  size = ftell (in64);
+  if (size < 0)
+    grub_util_error ("cannot get end of input file '%s': %s",
+		     name64, strerror (errno));
+  size64 = (grub_uint64_t) size;
   fseek (in64, 0, SEEK_SET);
 
   head.magic = grub_cpu_to_le32_compile_time (GRUB_MACHO_FAT_EFI_MAGIC);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 060/117] script/execute: Fix NULL dereference in grub_script_execute_cmdline()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (58 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 059/117] util/glue-efi: Fix incorrect use of a possibly negative value Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 061/117] commands/ls: Require device_name is not NULL before printing Daniel Kiper
                   ` (58 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/script/execute.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
index ce83edd4b..3ad468fce 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -940,7 +940,7 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
   struct grub_script_argv argv = { 0, 0, 0 };
 
   /* Lookup the command.  */
-  if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0])
+  if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args || ! argv.args[0])
     return grub_errno;
 
   for (i = 0; i < argv.argc; i++)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 061/117] commands/ls: Require device_name is not NULL before printing
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (59 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 060/117] script/execute: Fix NULL dereference in grub_script_execute_cmdline() Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 062/117] script/execute: Avoid crash when using "$#" outside a function scope Daniel Kiper
                   ` (57 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

This can be triggered with:
  ls -l (0 0*)
and causes a NULL deref in grub_normal_print_device_info().

I'm not sure if there's any implication with the IEEE 1275 platform.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/ls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c
index 5b7491aa4..326d2d6b4 100644
--- a/grub-core/commands/ls.c
+++ b/grub-core/commands/ls.c
@@ -196,7 +196,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
       goto fail;
     }
 
-  if (! *path)
+  if (! *path && device_name)
     {
       if (grub_errno == GRUB_ERR_UNKNOWN_FS)
 	grub_errno = GRUB_ERR_NONE;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 062/117] script/execute: Avoid crash when using "$#" outside a function scope
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (60 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 061/117] commands/ls: Require device_name is not NULL before printing Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 063/117] lib/arg: Block repeated short options that require an argument Daniel Kiper
                   ` (56 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

"$#" represents the number of arguments to a function. It is only
defined in a function scope, where "scope" is non-NULL. Currently,
if we attempt to evaluate "$#" outside a function scope, "scope" will
be NULL and we will crash with a NULL pointer dereference.

Do not attempt to count arguments for "$#" if "scope" is NULL. This
will result in "$#" being interpreted as an empty string if evaluated
outside a function scope.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/script/execute.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
index 3ad468fce..b88765f1d 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -485,7 +485,7 @@ gettext_putvar (const char *str, grub_size_t len,
     return 0;
 
   /* Enough for any number.  */
-  if (len == 1 && str[0] == '#')
+  if (len == 1 && str[0] == '#' && scope != NULL)
     {
       grub_snprintf (*ptr, 30, "%u", scope->argv.argc);
       *ptr += grub_strlen (*ptr);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 063/117] lib/arg: Block repeated short options that require an argument
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (61 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 062/117] script/execute: Avoid crash when using "$#" outside a function scope Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 064/117] script/execute: Don't crash on a "for" loop with no items Daniel Kiper
                   ` (55 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Fuzzing found the following crash:

  search -hhhhhhhhhhhhhf

We didn't allocate enough option space for 13 hints because the
allocation code counts the number of discrete arguments (i.e. argc).
However, the shortopt parsing code will happily keep processing
a combination of short options without checking if those short
options require an argument. This means you can easily end writing
past the allocated option space.

This fixes a OOB write which can cause heap corruption.

Fixes: CVE-2021-20225

Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/lib/arg.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c
index 8439a0062..ade82d5dc 100644
--- a/grub-core/lib/arg.c
+++ b/grub-core/lib/arg.c
@@ -299,6 +299,19 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
 		 it can have an argument value.  */
 	      if (*curshort)
 		{
+		  /*
+		   * Only permit further short opts if this one doesn't
+		   * require a value.
+		   */
+		  if (opt->type != ARG_TYPE_NONE &&
+		      !(opt->flags & GRUB_ARG_OPTION_OPTIONAL))
+		    {
+		      grub_error (GRUB_ERR_BAD_ARGUMENT,
+				  N_("missing mandatory option for `%s'"),
+				  opt->longarg);
+		      goto fail;
+		    }
+
 		  if (parse_option (cmd, opt, 0, usr) || grub_errno)
 		    goto fail;
 		}
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 064/117] script/execute: Don't crash on a "for" loop with no items
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (62 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 063/117] lib/arg: Block repeated short options that require an argument Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 065/117] commands/menuentry: Fix quoting in setparams_prefix() Daniel Kiper
                   ` (54 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

The following crashes the parser:

  for x in; do
  0
  done

This is because grub_script_arglist_to_argv() doesn't consider the
possibility that arglist is NULL. Catch that explicitly.

This avoids a NULL pointer dereference.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/script/execute.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
index b88765f1d..25158407d 100644
--- a/grub-core/script/execute.c
+++ b/grub-core/script/execute.c
@@ -624,6 +624,9 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
   struct grub_script_arg *arg = 0;
   struct grub_script_argv result = { 0, 0, 0 };
 
+  if (arglist == NULL)
+    return 1;
+
   for (; arglist && arglist->arg; arglist = arglist->next)
     {
       if (grub_script_argv_next (&result))
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 065/117] commands/menuentry: Fix quoting in setparams_prefix()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (63 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 064/117] script/execute: Don't crash on a "for" loop with no items Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 066/117] kern/misc: Always set *end in grub_strtoull() Daniel Kiper
                   ` (53 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Commit 9acdcbf32542 (use single quotes in menuentry setparams command)
says that expressing a quoted single quote will require 3 characters. It
actually requires (and always did require!) 4 characters:

  str: a'b => a'\''b
  len:  3  => 6 (2 for the letters + 4 for the quote)

This leads to not allocating enough memory and thus out of bounds writes
that have been observed to cause heap corruption.

Allocate 4 bytes for each single quote.

Commit 22e7dbb2bb81 (Fix quoting in legacy parser.) does the same
quoting, but it adds 3 as extra overhead on top of the single byte that
the quote already needs. So it's correct.

Fixes: 9acdcbf32542 (use single quotes in menuentry setparams command)
Fixes: CVE-2021-20233

Reported-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/commands/menuentry.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
index 9164df744..720e6d8ea 100644
--- a/grub-core/commands/menuentry.c
+++ b/grub-core/commands/menuentry.c
@@ -230,7 +230,7 @@ setparams_prefix (int argc, char **args)
       len += 3; /* 3 = 1 space + 2 quotes */
       p = args[i];
       while (*p)
-	len += (*p++ == '\'' ? 3 : 1);
+	len += (*p++ == '\'' ? 4 : 1);
     }
 
   result = grub_malloc (len + 2);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 066/117] kern/misc: Always set *end in grub_strtoull()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (64 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 065/117] commands/menuentry: Fix quoting in setparams_prefix() Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 067/117] video/readers/jpeg: Catch files with unsupported quantization or Huffman tables Daniel Kiper
                   ` (52 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Currently, if there is an error in grub_strtoull(), *end is not set.
This differs from the usual behavior of strtoull(), and also means that
some callers may use an uninitialized value for *end.

Set *end unconditionally.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/misc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index a278e069b..430e72340 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -419,6 +419,10 @@ grub_strtoull (const char * restrict str, const char ** const restrict end,
 	{
 	  grub_error (GRUB_ERR_OUT_OF_RANGE,
 		      N_("overflow is detected"));
+
+          if (end)
+            *end = (char *) str;
+
 	  return ~0ULL;
 	}
 
@@ -430,6 +434,10 @@ grub_strtoull (const char * restrict str, const char ** const restrict end,
     {
       grub_error (GRUB_ERR_BAD_NUMBER,
 		  N_("unrecognized number"));
+
+      if (end)
+        *end = (char *) str;
+
       return 0;
     }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 067/117] video/readers/jpeg: Catch files with unsupported quantization or Huffman tables
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (65 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 066/117] kern/misc: Always set *end in grub_strtoull() Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 068/117] video/readers/jpeg: Catch OOB reads/writes in grub_jpeg_decode_du() Daniel Kiper
                   ` (51 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Our decoder only supports 2 quantization tables. If a file asks for
a quantization table with index > 1, reject it.

Similarly, our decoder only supports 4 Huffman tables. If a file asks
for a Huffman table with index > 3, reject it.

This fixes some out of bounds reads. It's not clear what degree of control
over subsequent execution could be gained by someone who can carefully
set up the contents of memory before loading an invalid JPEG file.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/readers/jpeg.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index 0b6ce3cee..23f919aa0 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -333,7 +333,11 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
       else if (ss != JPEG_SAMPLING_1x1)
 	return grub_error (GRUB_ERR_BAD_FILE_TYPE,
 			   "jpeg: sampling method not supported");
+
       data->comp_index[id][0] = grub_jpeg_get_byte (data);
+      if (data->comp_index[id][0] > 1)
+	return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+			   "jpeg: too many quantization tables");
     }
 
   if (data->file->offset != next_marker)
@@ -602,6 +606,10 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
       ht = grub_jpeg_get_byte (data);
       data->comp_index[id][1] = (ht >> 4);
       data->comp_index[id][2] = (ht & 0xF) + 2;
+
+      if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) ||
+	  (data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3))
+	return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index");
     }
 
   grub_jpeg_get_byte (data);	/* Skip 3 unused bytes.  */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 068/117] video/readers/jpeg: Catch OOB reads/writes in grub_jpeg_decode_du()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (66 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 067/117] video/readers/jpeg: Catch files with unsupported quantization or Huffman tables Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 069/117] video/readers/jpeg: Don't decode data before start of stream Daniel Kiper
                   ` (50 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

The key line is:

  du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];

jpeg_zigzag_order is grub_uint8_t[64].

I don't understand JPEG decoders quite well enough to explain what's
going on here. However, I observe sometimes pos=64, which leads to an
OOB read of the jpeg_zigzag_order global then an OOB write to du.
That leads to various unpleasant memory corruption conditions.

Catch where pos >= ARRAY_SIZE(jpeg_zigzag_order) and bail.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/readers/jpeg.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index 23f919aa0..e5148120f 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -526,6 +526,14 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
       val = grub_jpeg_get_number (data, num & 0xF);
       num >>= 4;
       pos += num;
+
+      if (pos >= ARRAY_SIZE (jpeg_zigzag_order))
+	{
+	  grub_error (GRUB_ERR_BAD_FILE_TYPE,
+		      "jpeg: invalid position in zigzag order!?");
+	  return;
+	}
+
       du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
       pos++;
     }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 069/117] video/readers/jpeg: Don't decode data before start of stream
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (67 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 068/117] video/readers/jpeg: Catch OOB reads/writes in grub_jpeg_decode_du() Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 070/117] term/gfxterm: Don't set up a font with glyphs that are too big Daniel Kiper
                   ` (49 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

When a start of stream marker is encountered, we call grub_jpeg_decode_sos()
which allocates space for a bitmap.

When a restart marker is encountered, we call grub_jpeg_decode_data() which
then fills in that bitmap.

If we get a restart marker before the start of stream marker, we will
attempt to write to a bitmap_ptr that hasn't been allocated. Catch this
and bail out. This fixes an attempt to write to NULL.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/video/readers/jpeg.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index e5148120f..e31602f76 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -646,6 +646,10 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
   nr1 = (data->image_height + vb - 1) >> (3 + data->log_vs);
   nc1 = (data->image_width + hb - 1)  >> (3 + data->log_hs);
 
+  if (data->bitmap_ptr == NULL)
+    return grub_error(GRUB_ERR_BAD_FILE_TYPE,
+		      "jpeg: attempted to decode data before start of stream");
+
   for (; data->r1 < nr1 && (!data->dri || rst);
        data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
     for (c1 = 0;  c1 < nc1 && (!data->dri || rst);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 070/117] term/gfxterm: Don't set up a font with glyphs that are too big
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (68 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 069/117] video/readers/jpeg: Don't decode data before start of stream Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 071/117] fs/fshelp: Catch impermissibly large block sizes in read helper Daniel Kiper
                   ` (48 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Catch the case where we have a font so big that it causes the number of
rows or columns to be 0. Currently we continue and allocate a
virtual_screen.text_buffer of size 0. We then try to use that for glpyhs
and things go badly.

On the emu platform, malloc() may give us a valid pointer, in which case
we'll access heap memory which we shouldn't. Alternatively, it may give us
NULL, in which case we'll crash. For other platforms, if I understand
grub_memalign() correctly, we will receive a valid but small allocation
that we will very likely later overrun.

Prevent the creation of a virtual screen that isn't at least 40 cols
by 12 rows. This is arbitrary, but it seems that if your width or height
is half a standard 80x24 terminal, you're probably going to struggle to
read anything anyway.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/term/gfxterm.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c
index af7c090a3..b40fcce91 100644
--- a/grub-core/term/gfxterm.c
+++ b/grub-core/term/gfxterm.c
@@ -232,6 +232,15 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
   virtual_screen.columns = virtual_screen.width / virtual_screen.normal_char_width;
   virtual_screen.rows = virtual_screen.height / virtual_screen.normal_char_height;
 
+  /*
+   * There must be a minimum number of rows and columns for the screen to
+   * make sense. Arbitrarily pick half of 80x24. If either dimensions is 0
+   * we would allocate 0 bytes for the text_buffer.
+   */
+  if (virtual_screen.columns < 40 || virtual_screen.rows < 12)
+    return grub_error (GRUB_ERR_BAD_FONT,
+		       "font: glyphs too large to fit on screen");
+
   /* Allocate memory for text buffer.  */
   virtual_screen.text_buffer =
     (struct grub_colored_char *) grub_malloc (virtual_screen.columns
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 071/117] fs/fshelp: Catch impermissibly large block sizes in read helper
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (69 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 070/117] term/gfxterm: Don't set up a font with glyphs that are too big Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 072/117] fs/hfsplus: Don't fetch a key beyond the end of the node Daniel Kiper
                   ` (47 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

A fuzzed HFS+ filesystem had log2blocksize = 22. This gave
log2blocksize + GRUB_DISK_SECTOR_BITS = 31. 1 << 31 = 0x80000000,
which is -1 as an int. This caused some wacky behavior later on in
the function, leading to out-of-bounds writes on the destination buffer.

Catch log2blocksize + GRUB_DISK_SECTOR_BITS >= 31. We could be stricter,
but this is the minimum that will prevent integer size weirdness.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/fshelp.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c
index 4c902adf3..a2d0d297a 100644
--- a/grub-core/fs/fshelp.c
+++ b/grub-core/fs/fshelp.c
@@ -362,6 +362,18 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
   grub_disk_addr_t i, blockcnt;
   int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
 
+  /*
+   * Catch blatantly invalid log2blocksize. We could be a lot stricter, but
+   * this is the most permissive we can be before we start to see integer
+   * overflow/underflow issues.
+   */
+  if (log2blocksize + GRUB_DISK_SECTOR_BITS >= 31)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE,
+		  N_("blocksize too large"));
+      return -1;
+    }
+
   if (pos > filesize)
     {
       grub_error (GRUB_ERR_OUT_OF_RANGE,
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 072/117] fs/hfsplus: Don't fetch a key beyond the end of the node
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (70 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 071/117] fs/fshelp: Catch impermissibly large block sizes in read helper Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 073/117] fs/hfsplus: Don't use uninitialized data on corrupt filesystems Daniel Kiper
                   ` (46 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Otherwise you get a wild pointer, leading to a bunch of invalid reads.
Check it falls inside the given node.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/hfsplus.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index 8fe7c12ed..1c7791b02 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -635,6 +635,10 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
 	      pointer = ((char *) currkey
 			 + grub_be_to_cpu16 (currkey->keylen)
 			 + 2);
+
+	      if ((char *) pointer > node + btree->nodesize - 2)
+		return grub_error (GRUB_ERR_BAD_FS, "HFS+ key beyond end of node");
+
 	      currnode = grub_be_to_cpu32 (grub_get_unaligned32 (pointer));
 	      match = 1;
 	    }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 073/117] fs/hfsplus: Don't use uninitialized data on corrupt filesystems
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (71 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 072/117] fs/hfsplus: Don't fetch a key beyond the end of the node Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 074/117] fs/hfs: Disable under lockdown Daniel Kiper
                   ` (45 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Valgrind identified the following use of uninitialized data:

  ==2782220== Conditional jump or move depends on uninitialised value(s)
  ==2782220==    at 0x42B364: grub_hfsplus_btree_search (hfsplus.c:566)
  ==2782220==    by 0x42B21D: grub_hfsplus_read_block (hfsplus.c:185)
  ==2782220==    by 0x42A693: grub_fshelp_read_file (fshelp.c:386)
  ==2782220==    by 0x42C598: grub_hfsplus_read_file (hfsplus.c:219)
  ==2782220==    by 0x42C598: grub_hfsplus_mount (hfsplus.c:330)
  ==2782220==    by 0x42B8C5: grub_hfsplus_dir (hfsplus.c:958)
  ==2782220==    by 0x4C1AE6: grub_fs_probe (fs.c:73)
  ==2782220==    by 0x407C94: grub_ls_list_files (ls.c:186)
  ==2782220==    by 0x407C94: grub_cmd_ls (ls.c:284)
  ==2782220==    by 0x4D7130: grub_extcmd_dispatcher (extcmd.c:55)
  ==2782220==    by 0x4045A6: execute_command (grub-fstest.c:59)
  ==2782220==    by 0x4045A6: fstest (grub-fstest.c:433)
  ==2782220==    by 0x4045A6: main (grub-fstest.c:772)
  ==2782220==  Uninitialised value was created by a heap allocation
  ==2782220==    at 0x483C7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==2782220==    by 0x4C0305: grub_malloc (mm.c:42)
  ==2782220==    by 0x42C21D: grub_hfsplus_mount (hfsplus.c:239)
  ==2782220==    by 0x42B8C5: grub_hfsplus_dir (hfsplus.c:958)
  ==2782220==    by 0x4C1AE6: grub_fs_probe (fs.c:73)
  ==2782220==    by 0x407C94: grub_ls_list_files (ls.c:186)
  ==2782220==    by 0x407C94: grub_cmd_ls (ls.c:284)
  ==2782220==    by 0x4D7130: grub_extcmd_dispatcher (extcmd.c:55)
  ==2782220==    by 0x4045A6: execute_command (grub-fstest.c:59)
  ==2782220==    by 0x4045A6: fstest (grub-fstest.c:433)
  ==2782220==    by 0x4045A6: main (grub-fstest.c:772)

This happens when the process of reading the catalog file goes sufficiently
wrong that there's an attempt to read the extent overflow file, which has
not yet been loaded. Keep track of when the extent overflow file is
fully loaded and refuse to use it before then.

The load valgrind doesn't like is btree->nodesize, and that's then used
to allocate a data structure. It looks like there are subsequently a lot
of reads based on that pointer so OOB reads are likely, and indeed crashes
(albeit difficult-to-replicate ones) have been observed in fuzzing.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/hfsplus.c | 14 ++++++++++++++
 include/grub/hfsplus.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c
index 1c7791b02..361e5be49 100644
--- a/grub-core/fs/hfsplus.c
+++ b/grub-core/fs/hfsplus.c
@@ -177,6 +177,17 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
 	  break;
 	}
 
+      /*
+       * If the extent overflow tree isn't ready yet, we can't look
+       * in it. This can happen where the catalog file is corrupted.
+       */
+      if (!node->data->extoverflow_tree_ready)
+	{
+	  grub_error (GRUB_ERR_BAD_FS,
+		      "attempted to read extent overflow tree before loading");
+	  break;
+	}
+
       /* Set up the key to look for in the extent overflow file.  */
       extoverflow.extkey.fileid = node->fileid;
       extoverflow.extkey.type = 0;
@@ -241,6 +252,7 @@ grub_hfsplus_mount (grub_disk_t disk)
     return 0;
 
   data->disk = disk;
+  data->extoverflow_tree_ready = 0;
 
   /* Read the bootblock.  */
   grub_disk_read (disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader),
@@ -357,6 +369,8 @@ grub_hfsplus_mount (grub_disk_t disk)
   if (data->extoverflow_tree.nodesize < 2)
     goto fail;
 
+  data->extoverflow_tree_ready = 1;
+
   if (grub_hfsplus_read_file (&data->attr_tree.file, 0, 0,
 			      sizeof (struct grub_hfsplus_btnode),
 			      sizeof (header), (char *) &header) <= 0)
diff --git a/include/grub/hfsplus.h b/include/grub/hfsplus.h
index 117740ae2..e14dd31ff 100644
--- a/include/grub/hfsplus.h
+++ b/include/grub/hfsplus.h
@@ -113,6 +113,8 @@ struct grub_hfsplus_data
   struct grub_hfsplus_btree extoverflow_tree;
   struct grub_hfsplus_btree attr_tree;
 
+  int extoverflow_tree_ready;
+
   struct grub_hfsplus_file dirroot;
   struct grub_hfsplus_file opened_file;
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 074/117] fs/hfs: Disable under lockdown
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (72 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 073/117] fs/hfsplus: Don't use uninitialized data on corrupt filesystems Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 075/117] fs/sfs: Fix over-read of root object name Daniel Kiper
                   ` (44 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

HFS has issues such as infinite mutual recursion that are simply too
complex to fix for such a legacy format. So simply do not permit
it to be loaded under lockdown.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/hfs.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c
index 3fe842b4d..9a5b7bbe9 100644
--- a/grub-core/fs/hfs.c
+++ b/grub-core/fs/hfs.c
@@ -30,6 +30,7 @@
 #include <grub/hfs.h>
 #include <grub/i18n.h>
 #include <grub/fshelp.h>
+#include <grub/lockdown.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -1433,11 +1434,13 @@ static struct grub_fs grub_hfs_fs =
 
 GRUB_MOD_INIT(hfs)
 {
-  grub_fs_register (&grub_hfs_fs);
+  if (!grub_is_lockdown ())
+    grub_fs_register (&grub_hfs_fs);
   my_mod = mod;
 }
 
 GRUB_MOD_FINI(hfs)
 {
-  grub_fs_unregister (&grub_hfs_fs);
+  if (!grub_is_lockdown())
+    grub_fs_unregister (&grub_hfs_fs);
 }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 075/117] fs/sfs: Fix over-read of root object name
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (73 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 074/117] fs/hfs: Disable under lockdown Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 076/117] fs/jfs: Do not move to leaf level if name length is negative Daniel Kiper
                   ` (43 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

There's a read of the name of the root object that assumes that the name
is nul-terminated within the root block. This isn't guaranteed - it seems
SFS would require you to read multiple blocks to get a full name in general,
but maybe that doesn't apply to the root object.

Either way, figure out how much space is left in the root block and don't
over-read it. This fixes some OOB reads.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/sfs.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
index de2b107a4..983e88008 100644
--- a/grub-core/fs/sfs.c
+++ b/grub-core/fs/sfs.c
@@ -373,6 +373,7 @@ grub_sfs_mount (grub_disk_t disk)
   struct grub_sfs_objc *rootobjc;
   char *rootobjc_data = 0;
   grub_uint32_t blk;
+  unsigned int max_len;
 
   data = grub_malloc (sizeof (*data));
   if (!data)
@@ -421,7 +422,13 @@ grub_sfs_mount (grub_disk_t disk)
   data->diropen.data = data;
   data->diropen.cache = 0;
   data->disk = disk;
-  data->label = grub_strdup ((char *) (rootobjc->objects[0].filename));
+
+  /* We only read 1 block of data, so truncate the name if needed. */
+  max_len = ((GRUB_DISK_SECTOR_SIZE << data->log_blocksize)
+	     - 24    /* offsetof (struct grub_sfs_objc, objects) */
+	     - 25);  /* offsetof (struct grub_sfs_obj, filename) */
+  data->label = grub_zalloc (max_len + 1);
+  grub_strncpy (data->label, (char *) rootobjc->objects[0].filename, max_len);
 
   grub_free (rootobjc_data);
   return data;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 076/117] fs/jfs: Do not move to leaf level if name length is negative
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (74 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 075/117] fs/sfs: Fix over-read of root object name Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 077/117] fs/jfs: Limit the extents that getblk() can consider Daniel Kiper
                   ` (42 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Fuzzing JFS revealed crashes where a negative number would be passed
to le_to_cpu16_copy(). There it would be cast to a large positive number
and the copy would read and write off the end of the respective buffers.

Catch this at the top as well as the bottom of the loop.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/jfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index d5a6d6527..e5bbda61c 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -567,7 +567,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro)
 
   /* Move down to the leaf level.  */
   nextent = leaf->next;
-  if (leaf->next != 255)
+  if (leaf->next != 255 && len > 0)
     do
       {
  	next_leaf = &diro->next_leaf[nextent];
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 077/117] fs/jfs: Limit the extents that getblk() can consider
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (75 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 076/117] fs/jfs: Do not move to leaf level if name length is negative Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 078/117] fs/jfs: Catch infinite recursion Daniel Kiper
                   ` (41 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

getblk() implicitly trusts that treehead->count is an accurate count of
the number of extents. However, that value is read from disk and is not
trustworthy, leading to OOB reads and crashes. I am not sure to what
extent the data read from OOB can influence subsequent program execution.

Require callers to pass in the maximum number of extents for which
they have storage.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/jfs.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index e5bbda61c..804c42d31 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -261,13 +261,15 @@ static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint
 static grub_int64_t
 getblk (struct grub_jfs_treehead *treehead,
 	struct grub_jfs_tree_extent *extents,
+	int max_extents,
 	struct grub_jfs_data *data,
 	grub_uint64_t blk)
 {
   int found = -1;
   int i;
 
-  for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2; i++)
+  for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 &&
+	      i < max_extents; i++)
     {
       if (treehead->flags & GRUB_JFS_TREE_LEAF)
 	{
@@ -302,7 +304,7 @@ getblk (struct grub_jfs_treehead *treehead,
 			   << (grub_le_to_cpu16 (data->sblock.log2_blksz)
 			       - GRUB_DISK_SECTOR_BITS), 0,
 			   sizeof (*tree), (char *) tree))
-	ret = getblk (&tree->treehead, &tree->extents[0], data, blk);
+	ret = getblk (&tree->treehead, &tree->extents[0], 254, data, blk);
       grub_free (tree);
       return ret;
     }
@@ -316,7 +318,7 @@ static grub_int64_t
 grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
 		grub_uint64_t blk)
 {
-  return getblk (&inode->file.tree, &inode->file.extents[0], data, blk);
+  return getblk (&inode->file.tree, &inode->file.extents[0], 16, data, blk);
 }
 
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 078/117] fs/jfs: Catch infinite recursion
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (76 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 077/117] fs/jfs: Limit the extents that getblk() can consider Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 079/117] fs/nilfs2: Reject too-large keys Daniel Kiper
                   ` (40 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

It's possible with a fuzzed filesystem for JFS to keep getblk()-ing
the same data over and over again, leading to stack exhaustion.

Check if we'd be calling the function with exactly the same data as
was passed in, and if so abort.

I'm not sure what the performance impact of this is and am open to
better ideas.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/jfs.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c
index 804c42d31..6f7c43904 100644
--- a/grub-core/fs/jfs.c
+++ b/grub-core/fs/jfs.c
@@ -304,7 +304,16 @@ getblk (struct grub_jfs_treehead *treehead,
 			   << (grub_le_to_cpu16 (data->sblock.log2_blksz)
 			       - GRUB_DISK_SECTOR_BITS), 0,
 			   sizeof (*tree), (char *) tree))
-	ret = getblk (&tree->treehead, &tree->extents[0], 254, data, blk);
+	{
+	  if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) ||
+	      grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent)))
+	    ret = getblk (&tree->treehead, &tree->extents[0], 254, data, blk);
+	  else
+	    {
+	      grub_error (GRUB_ERR_BAD_FS, "jfs: infinite recursion detected");
+	      ret = -1;
+	    }
+	}
       grub_free (tree);
       return ret;
     }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 079/117] fs/nilfs2: Reject too-large keys
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (77 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 078/117] fs/jfs: Catch infinite recursion Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 080/117] fs/nilfs2: Don't search children if provided number is too large Daniel Kiper
                   ` (39 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

NILFS2 has up to 7 keys, per the data structure. Do not permit array
indices in excess of that.

This catches some OOB reads. I don't know how controllable the invalidly
read data is or if that could be used later in the program.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/nilfs2.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index 082326f38..20053caf5 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -569,6 +569,11 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
 static inline grub_uint64_t
 grub_nilfs2_direct_lookup (struct grub_nilfs2_inode *inode, grub_uint64_t key)
 {
+  if (1 + key > 6)
+    {
+      grub_error (GRUB_ERR_BAD_FS, "key is too large");
+      return 0xffffffffffffffff;
+    }
   return grub_le_to_cpu64 (inode->i_bmap[1 + key]);
 }
 
@@ -584,7 +589,7 @@ grub_nilfs2_bmap_lookup (struct grub_nilfs2_data *data,
     {
       grub_uint64_t ptr;
       ptr = grub_nilfs2_direct_lookup (inode, key);
-      if (need_translate)
+      if (ptr != ((grub_uint64_t) 0xffffffffffffffff) && need_translate)
 	ptr = grub_nilfs2_dat_translate (data, ptr);
       return ptr;
     }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 080/117] fs/nilfs2: Don't search children if provided number is too large
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (78 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 079/117] fs/nilfs2: Reject too-large keys Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 081/117] fs/nilfs2: Properly bail on errors in grub_nilfs2_btree_node_lookup() Daniel Kiper
                   ` (38 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

NILFS2 reads the number of children a node has from the node. Unfortunately,
that's not trustworthy. Check if it's beyond what the filesystem permits and
reject it if so.

This blocks some OOB reads. I'm not sure how controllable the read is and what
could be done with invalidly read data later on.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/nilfs2.c | 38 +++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index 20053caf5..7963b4ef5 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -416,14 +416,34 @@ grub_nilfs2_btree_node_get_key (struct grub_nilfs2_btree_node *node,
 }
 
 static inline int
-grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node,
+grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data,
+				      struct grub_nilfs2_btree_node *node)
+{
+  int node_children_max = ((NILFS2_BLOCK_SIZE (data) -
+			    sizeof (struct grub_nilfs2_btree_node) -
+			    NILFS_BTREE_NODE_EXTRA_PAD_SIZE) /
+			   (sizeof (grub_uint64_t) + sizeof (grub_uint64_t)));
+
+  return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max;
+}
+
+static inline int
+grub_nilfs2_btree_node_lookup (struct grub_nilfs2_data *data,
+			       struct grub_nilfs2_btree_node *node,
 			       grub_uint64_t key, int *indexp)
 {
   grub_uint64_t nkey;
   int index, low, high, s;
 
   low = 0;
+
   high = grub_le_to_cpu16 (node->bn_nchildren) - 1;
+  if (high >= grub_nilfs2_btree_node_nchildren_max (data, node))
+    {
+      grub_error (GRUB_ERR_BAD_FS, "too many children");
+      return 0;
+    }
+
   index = 0;
   s = 0;
   while (low <= high)
@@ -459,18 +479,6 @@ grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node,
   return s == 0;
 }
 
-static inline int
-grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data,
-				      struct grub_nilfs2_btree_node *node)
-{
-  int node_children_max = ((NILFS2_BLOCK_SIZE (data) -
-			    sizeof (struct grub_nilfs2_btree_node) -
-			    NILFS_BTREE_NODE_EXTRA_PAD_SIZE) /
-			   (sizeof (grub_uint64_t) + sizeof (grub_uint64_t)));
-
-  return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max;
-}
-
 static inline grub_uint64_t *
 grub_nilfs2_btree_node_dptrs (struct grub_nilfs2_data *data,
 			      struct grub_nilfs2_btree_node *node)
@@ -517,7 +525,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
   node = grub_nilfs2_btree_get_root (inode);
   level = grub_nilfs2_btree_get_level (node);
 
-  found = grub_nilfs2_btree_node_lookup (node, key, &index);
+  found = grub_nilfs2_btree_node_lookup (data, node, key, &index);
   ptr = grub_nilfs2_btree_node_get_ptr (data, node, index);
   if (need_translate)
     ptr = grub_nilfs2_dat_translate (data, ptr);
@@ -538,7 +546,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
 	}
 
       if (!found)
-	found = grub_nilfs2_btree_node_lookup (node, key, &index);
+	found = grub_nilfs2_btree_node_lookup (data, node, key, &index);
       else
 	index = 0;
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 081/117] fs/nilfs2: Properly bail on errors in grub_nilfs2_btree_node_lookup()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (79 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 080/117] fs/nilfs2: Don't search children if provided number is too large Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 082/117] io/gzio: Bail if gzio->tl/td is NULL Daniel Kiper
                   ` (37 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

We just introduced an error return in grub_nilfs2_btree_node_lookup().
Make sure the callers catch it.

At the same time, make sure that grub_nilfs2_btree_node_lookup() always
inits the index pointer passed to it.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/nilfs2.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index 7963b4ef5..9b76982b3 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -433,7 +433,7 @@ grub_nilfs2_btree_node_lookup (struct grub_nilfs2_data *data,
 			       grub_uint64_t key, int *indexp)
 {
   grub_uint64_t nkey;
-  int index, low, high, s;
+  int index = 0, low, high, s;
 
   low = 0;
 
@@ -441,10 +441,10 @@ grub_nilfs2_btree_node_lookup (struct grub_nilfs2_data *data,
   if (high >= grub_nilfs2_btree_node_nchildren_max (data, node))
     {
       grub_error (GRUB_ERR_BAD_FS, "too many children");
+      *indexp = index;
       return 0;
     }
 
-  index = 0;
   s = 0;
   while (low <= high)
     {
@@ -526,6 +526,10 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
   level = grub_nilfs2_btree_get_level (node);
 
   found = grub_nilfs2_btree_node_lookup (data, node, key, &index);
+
+  if (grub_errno != GRUB_ERR_NONE)
+    goto fail;
+
   ptr = grub_nilfs2_btree_node_get_ptr (data, node, index);
   if (need_translate)
     ptr = grub_nilfs2_dat_translate (data, ptr);
@@ -550,7 +554,8 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
       else
 	index = 0;
 
-      if (index < grub_nilfs2_btree_node_nchildren_max (data, node))
+      if (index < grub_nilfs2_btree_node_nchildren_max (data, node) &&
+	  grub_errno == GRUB_ERR_NONE)
 	{
 	  ptr = grub_nilfs2_btree_node_get_ptr (data, node, index);
 	  if (need_translate)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 082/117] io/gzio: Bail if gzio->tl/td is NULL
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (80 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 081/117] fs/nilfs2: Properly bail on errors in grub_nilfs2_btree_node_lookup() Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 083/117] io/gzio: Add init_dynamic_block() clean up if unpacking codes fails Daniel Kiper
                   ` (36 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

This is an ugly fix that doesn't address why gzio->tl comes to be NULL.
However, it seems to be sufficient to patch up a bunch of NULL derefs.

It would be good to revisit this in future and see if we can have
a cleaner solution that addresses some of the causes of the unexpected
NULL pointers.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/io/gzio.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 43d98a7bd..4a8eaeae2 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -669,6 +669,13 @@ inflate_codes_in_window (grub_gzio_t gzio)
     {
       if (! gzio->code_state)
 	{
+
+	  if (gzio->tl == NULL)
+	    {
+	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "NULL gzio->tl");
+	      return 1;
+	    }
+
 	  NEEDBITS ((unsigned) gzio->bl);
 	  if ((e = (t = gzio->tl + ((unsigned) b & ml))->e) > 16)
 	    do
@@ -707,6 +714,12 @@ inflate_codes_in_window (grub_gzio_t gzio)
 	      n = t->v.n + ((unsigned) b & mask_bits[e]);
 	      DUMPBITS (e);
 
+	      if (gzio->td == NULL)
+		{
+		  grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "NULL gzio->td");
+		  return 1;
+		}
+
 	      /* decode distance of block to copy */
 	      NEEDBITS ((unsigned) gzio->bd);
 	      if ((e = (t = gzio->td + ((unsigned) b & md))->e) > 16)
@@ -917,6 +930,13 @@ init_dynamic_block (grub_gzio_t gzio)
   n = nl + nd;
   m = mask_bits[gzio->bl];
   i = l = 0;
+
+  if (gzio->tl == NULL)
+    {
+      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "NULL gzio->tl");
+      return;
+    }
+
   while ((unsigned) i < n)
     {
       NEEDBITS ((unsigned) gzio->bl);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 083/117] io/gzio: Add init_dynamic_block() clean up if unpacking codes fails
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (81 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 082/117] io/gzio: Bail if gzio->tl/td is NULL Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 084/117] io/gzio: Catch missing values in huft_build() and bail Daniel Kiper
                   ` (35 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

init_dynamic_block() didn't clean up gzio->tl and td in some error
paths. This left td pointing to part of tl. Then in grub_gzio_close(),
when tl was freed the storage for td would also be freed. The code then
attempts to free td explicitly, performing a UAF and then a double free.

Explicitly clean up tl and td in the error paths.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/io/gzio.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 4a8eaeae2..4236f0fd4 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -953,7 +953,7 @@ init_dynamic_block (grub_gzio_t gzio)
 	  if ((unsigned) i + j > n)
 	    {
 	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
-	      return;
+	      goto fail;
 	    }
 	  while (j--)
 	    ll[i++] = l;
@@ -966,7 +966,7 @@ init_dynamic_block (grub_gzio_t gzio)
 	  if ((unsigned) i + j > n)
 	    {
 	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
-	      return;
+	      goto fail;
 	    }
 	  while (j--)
 	    ll[i++] = 0;
@@ -981,7 +981,7 @@ init_dynamic_block (grub_gzio_t gzio)
 	  if ((unsigned) i + j > n)
 	    {
 	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
-	      return;
+	      goto fail;
 	    }
 	  while (j--)
 	    ll[i++] = 0;
@@ -1019,6 +1019,12 @@ init_dynamic_block (grub_gzio_t gzio)
   /* indicate we're now working on a block */
   gzio->code_state = 0;
   gzio->block_len++;
+  return;
+
+ fail:
+  huft_free (gzio->tl);
+  gzio->td = NULL;
+  gzio->tl = NULL;
 }
 
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 084/117] io/gzio: Catch missing values in huft_build() and bail
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (82 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 083/117] io/gzio: Add init_dynamic_block() clean up if unpacking codes fails Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 085/117] io/gzio: Zero gzio->tl/td in init_dynamic_block() if huft_build() fails Daniel Kiper
                   ` (34 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

In huft_build(), "v" is a table of values in order of bit length.
The code later (when setting up table entries in "r") assumes that all
elements of this array corresponding to a code are initialized and less
than N_MAX. However, it doesn't enforce this.

With sufficiently manipulated inputs (e.g. from fuzzing), there can be
elements of "v" that are not filled. Therefore a lookup into "e" or "d"
will use an uninitialized value. This can lead to an invalid/OOB read on
those values, often leading to a crash.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/io/gzio.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 4236f0fd4..19adebeed 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -507,6 +507,7 @@ huft_build (unsigned *b,	/* code lengths in bits (all assumed <= BMAX) */
     }
 
   /* Make a table of values in order of bit lengths */
+  grub_memset (v, N_MAX, ARRAY_SIZE (v));
   p = b;
   i = 0;
   do
@@ -588,11 +589,18 @@ huft_build (unsigned *b,	/* code lengths in bits (all assumed <= BMAX) */
 	      r.v.n = (ush) (*p);	/* simple code is just the value */
 	      p++;		/* one compiler does not like *p++ */
 	    }
-	  else
+	  else if (*p < N_MAX)
 	    {
 	      r.e = (uch) e[*p - s];	/* non-simple--look up in lists */
 	      r.v.n = d[*p++ - s];
 	    }
+	  else
+	    {
+	      /* Detected an uninitialised value, abort. */
+	      if (h)
+		huft_free (u[0]);
+	      return 2;
+	    }
 
 	  /* fill code-like entries with r */
 	  f = 1 << (k - w);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 085/117] io/gzio: Zero gzio->tl/td in init_dynamic_block() if huft_build() fails
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (83 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 084/117] io/gzio: Catch missing values in huft_build() and bail Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 086/117] disk/lvm: Don't go beyond the end of the data we read from disk Daniel Kiper
                   ` (33 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

If huft_build() fails, gzio->tl or gzio->td could contain pointers that
are no longer valid. Zero them out.

This prevents a double free when grub_gzio_close() comes through and
attempts to free them again.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/io/gzio.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
index 19adebeed..aea86a0a9 100644
--- a/grub-core/io/gzio.c
+++ b/grub-core/io/gzio.c
@@ -1010,6 +1010,7 @@ init_dynamic_block (grub_gzio_t gzio)
   gzio->bl = lbits;
   if (huft_build (ll, nl, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0)
     {
+      gzio->tl = 0;
       grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
 		  "failed in building a Huffman code table");
       return;
@@ -1019,6 +1020,7 @@ init_dynamic_block (grub_gzio_t gzio)
     {
       huft_free (gzio->tl);
       gzio->tl = 0;
+      gzio->td = 0;
       grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
 		  "failed in building a Huffman code table");
       return;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 086/117] disk/lvm: Don't go beyond the end of the data we read from disk
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (84 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 085/117] io/gzio: Zero gzio->tl/td in init_dynamic_block() if huft_build() fails Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 087/117] disk/lvm: Don't blast past the end of the circular metadata buffer Daniel Kiper
                   ` (32 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

We unconditionally trusted offset_xl from the LVM label header, even if
it told us that the PV header/disk locations were way off past the end
of the data we read from disk.

Require that the offset be sane, fixing an OOB read and crash.

Fixes: CID 314367, CID 314371

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 753545146..6988fe492 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -178,6 +178,20 @@ grub_lvm_detect (grub_disk_t disk,
       goto fail;
     }
 
+  /*
+   * We read a grub_lvm_pv_header and then 2 grub_lvm_disk_locns that
+   * immediately follow the PV header. Make sure we have space for both.
+   */
+  if (grub_le_to_cpu32 (lh->offset_xl) >=
+      GRUB_LVM_LABEL_SIZE - sizeof (struct grub_lvm_pv_header) -
+      2 * sizeof (struct grub_lvm_disk_locn))
+    {
+#ifdef GRUB_UTIL
+      grub_util_info ("LVM PV header/disk locations are beyond the end of the block");
+#endif
+      goto fail;
+    }
+
   pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl));
 
   for (i = 0, j = 0; i < GRUB_LVM_ID_LEN; i++)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 087/117] disk/lvm: Don't blast past the end of the circular metadata buffer
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (85 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 086/117] disk/lvm: Don't go beyond the end of the data we read from disk Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 088/117] disk/lvm: Bail on missing PV list Daniel Kiper
                   ` (31 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

This catches at least some OOB reads, and it's possible I suppose that
if 2 * mda_size is less than GRUB_LVM_MDA_HEADER_SIZE it might catch some
OOB writes too (although that hasn't showed up as a crash in fuzzing yet).

It's a bit ugly and I'd appreciate better suggestions.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 6988fe492..b70d7d79f 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -251,6 +251,16 @@ grub_lvm_detect (grub_disk_t disk,
   if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) >
       grub_le_to_cpu64 (mdah->size))
     {
+      if (2 * mda_size < GRUB_LVM_MDA_HEADER_SIZE ||
+          (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) -
+	   grub_le_to_cpu64 (mdah->size) > mda_size - GRUB_LVM_MDA_HEADER_SIZE))
+	{
+#ifdef GRUB_UTIL
+	  grub_util_info ("cannot copy metadata wrap in circular buffer");
+#endif
+	  goto fail2;
+	}
+
       /* Metadata is circular. Copy the wrap in place. */
       grub_memcpy (metadatabuf + mda_size,
 		   metadatabuf + GRUB_LVM_MDA_HEADER_SIZE,
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 088/117] disk/lvm: Bail on missing PV list
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (86 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 087/117] disk/lvm: Don't blast past the end of the circular metadata buffer Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 089/117] disk/lvm: Do not crash if an expected string is not found Daniel Kiper
                   ` (30 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

There's an if block for the presence of "physical_volumes {", but if
that block is absent, then p remains NULL and a NULL-deref will result
when looking for logical volumes.

It doesn't seem like LVM makes sense without physical volumes, so error
out rather than crashing.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index b70d7d79f..31bbc9acc 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -409,6 +409,8 @@ grub_lvm_detect (grub_disk_t disk,
 	      goto fail4;
 	    }
 	}
+      else
+        goto fail4;
 
       p = grub_strstr (p, "logical_volumes {");
       if (p)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 089/117] disk/lvm: Do not crash if an expected string is not found
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (87 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 088/117] disk/lvm: Bail on missing PV list Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 090/117] disk/lvm: Do not overread metadata Daniel Kiper
                   ` (29 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

Clean up a bunch of cases where we could have strstr() fail and lead to
us dereferencing NULL.

We'll still leak memory in some cases (loops don't clean up allocations
from earlier iterations if a later iteration fails) but at least we're
not crashing.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 31bbc9acc..201097fda 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -578,7 +578,16 @@ grub_lvm_detect (grub_disk_t disk,
 			}
 
 		      if (seg->node_count != 1)
-			seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
+			{
+			  seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
+			  if (p == NULL)
+			    {
+#ifdef GRUB_UTIL
+			      grub_util_info ("unknown stripe_size");
+#endif
+			      goto lvs_segment_fail;
+			    }
+			}
 
 		      seg->nodes = grub_calloc (seg->node_count,
 						sizeof (*stripe));
@@ -598,7 +607,7 @@ grub_lvm_detect (grub_disk_t disk,
 			{
 			  p = grub_strchr (p, '"');
 			  if (p == NULL)
-			    continue;
+			    goto lvs_segment_fail2;
 			  q = ++p;
 			  while (*q != '"')
 			    q++;
@@ -617,7 +626,10 @@ grub_lvm_detect (grub_disk_t disk,
 			  stripe->start = grub_lvm_getvalue (&p, ",")
 			    * vg->extent_size;
 			  if (p == NULL)
-			    continue;
+			    {
+			      grub_free (stripe->name);
+			      goto lvs_segment_fail2;
+			    }
 
 			  stripe++;
 			}
@@ -654,7 +666,7 @@ grub_lvm_detect (grub_disk_t disk,
 
 			  p = grub_strchr (p, '"');
 			  if (p == NULL)
-			    continue;
+			    goto lvs_segment_fail2;
 			  q = ++p;
 			  while (*q != '"')
 			    q++;
@@ -742,7 +754,7 @@ grub_lvm_detect (grub_disk_t disk,
 			  p = p ? grub_strchr (p + 1, '"') : 0;
 			  p = p ? grub_strchr (p + 1, '"') : 0;
 			  if (p == NULL)
-			    continue;
+			    goto lvs_segment_fail2;
 			  q = ++p;
 			  while (*q != '"')
 			    q++;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 090/117] disk/lvm: Do not overread metadata
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (88 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 089/117] disk/lvm: Do not crash if an expected string is not found Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 091/117] disk/lvm: Sanitize rlocn->offset to prevent wild read Daniel Kiper
                   ` (28 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

We could reach the end of valid metadata and not realize, leading to
some buffer overreads. Check if we have reached the end and bail.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 201097fda..7efbaec79 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -352,17 +352,23 @@ grub_lvm_detect (grub_disk_t disk,
 	  while (1)
 	    {
 	      grub_ssize_t s;
-	      while (grub_isspace (*p))
+	      while (grub_isspace (*p) && p < mda_end)
 		p++;
 
+	      if (p == mda_end)
+		goto fail4;
+
 	      if (*p == '}')
 		break;
 
 	      pv = grub_zalloc (sizeof (*pv));
 	      q = p;
-	      while (*q != ' ')
+	      while (*q != ' ' && q < mda_end)
 		q++;
 
+	      if (q == mda_end)
+		goto pvs_fail_noname;
+
 	      s = q - p;
 	      pv->name = grub_malloc (s + 1);
 	      grub_memcpy (pv->name, p, s);
@@ -405,6 +411,7 @@ grub_lvm_detect (grub_disk_t disk,
 	      continue;
 	    pvs_fail:
 	      grub_free (pv->name);
+	    pvs_fail_noname:
 	      grub_free (pv);
 	      goto fail4;
 	    }
@@ -426,18 +433,24 @@ grub_lvm_detect (grub_disk_t disk,
 	      struct grub_diskfilter_segment *seg;
 	      int is_pvmove;
 
-	      while (grub_isspace (*p))
+	      while (grub_isspace (*p) && p < mda_end)
 		p++;
 
+	      if (p == mda_end)
+		goto fail4;
+
 	      if (*p == '}')
 		break;
 
 	      lv = grub_zalloc (sizeof (*lv));
 
 	      q = p;
-	      while (*q != ' ')
+	      while (*q != ' ' && q < mda_end)
 		q++;
 
+	      if (q == mda_end)
+		goto lvs_fail;
+
 	      s = q - p;
 	      lv->name = grub_strndup (p, s);
 	      if (!lv->name)
@@ -609,9 +622,12 @@ grub_lvm_detect (grub_disk_t disk,
 			  if (p == NULL)
 			    goto lvs_segment_fail2;
 			  q = ++p;
-			  while (*q != '"')
+			  while (q < mda_end && *q != '"')
 			    q++;
 
+			  if (q == mda_end)
+			    goto lvs_segment_fail2;
+
 			  s = q - p;
 
 			  stripe->name = grub_malloc (s + 1);
@@ -668,9 +684,12 @@ grub_lvm_detect (grub_disk_t disk,
 			  if (p == NULL)
 			    goto lvs_segment_fail2;
 			  q = ++p;
-			  while (*q != '"')
+			  while (q < mda_end && *q != '"')
 			    q++;
 
+			  if (q == mda_end)
+			    goto lvs_segment_fail2;
+
 			  s = q - p;
 
 			  lvname = grub_malloc (s + 1);
@@ -826,6 +845,8 @@ grub_lvm_detect (grub_disk_t disk,
 			goto cache_lv_fail;
 
 		      p3 = ++p2;
+		      if (p3 == mda_end)
+			goto cache_lv_fail;
 		      p3 = grub_strchr (p3, '"');
 		      if (!p3)
 			goto cache_lv_fail;
@@ -847,6 +868,8 @@ grub_lvm_detect (grub_disk_t disk,
 			goto cache_lv_fail;
 
 		      p3 = ++p2;
+		      if (p3 == mda_end)
+			goto cache_lv_fail;
 		      p3 = grub_strchr (p3, '"');
 		      if (!p3)
 			goto cache_lv_fail;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 091/117] disk/lvm: Sanitize rlocn->offset to prevent wild read
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (89 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 090/117] disk/lvm: Do not overread metadata Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 092/117] disk/lvm: Do not allow a LV to be it's own segment's node's LV Daniel Kiper
                   ` (27 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

rlocn->offset is read directly from disk and added to the metadatabuf
pointer to create a pointer to a block of metadata. It's a 64-bit
quantity so as long as you don't overflow you can set subsequent
pointers to point anywhere in memory.

Require that rlocn->offset fits within the metadata buffer size.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 7efbaec79..4e17b8897 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -248,6 +248,14 @@ grub_lvm_detect (grub_disk_t disk,
     }
 
   rlocn = mdah->raw_locns;
+  if (grub_le_to_cpu64 (rlocn->offset) >= grub_le_to_cpu64 (mda_size))
+    {
+#ifdef GRUB_UTIL
+      grub_util_info ("metadata offset is beyond end of metadata area");
+#endif
+      goto fail2;
+    }
+
   if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) >
       grub_le_to_cpu64 (mdah->size))
     {
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 092/117] disk/lvm: Do not allow a LV to be it's own segment's node's LV
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (90 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 091/117] disk/lvm: Sanitize rlocn->offset to prevent wild read Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 093/117] fs/btrfs: Validate the number of stripes/parities in RAID5/6 Daniel Kiper
                   ` (26 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

This prevents infinite recursion in the diskfilter verification code.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/lvm.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 4e17b8897..8257159b3 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -981,9 +981,13 @@ grub_lvm_detect (grub_disk_t disk,
 		    }
 		if (lv1->segments[i].nodes[j].pv == NULL)
 		  for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
-		    if (grub_strcmp (lv2->name,
-				     lv1->segments[i].nodes[j].name) == 0)
-		      lv1->segments[i].nodes[j].lv = lv2;
+		    {
+		      if (lv1 == lv2)
+		        continue;
+		      if (grub_strcmp (lv2->name,
+				       lv1->segments[i].nodes[j].name) == 0)
+			lv1->segments[i].nodes[j].lv = lv2;
+		    }
 	      }
 	
       }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 093/117] fs/btrfs: Validate the number of stripes/parities in RAID5/6
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (91 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 092/117] disk/lvm: Do not allow a LV to be it's own segment's node's LV Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 094/117] fs/btrfs: Squash some uninitialized reads Daniel Kiper
                   ` (25 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

This prevents a divide by zero if nstripes == nparities, and
also prevents propagation of invalid values if nstripes ends up
less than nparities.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/btrfs.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 27339bdb3..c4ba5f110 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -1083,6 +1083,9 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
 	       * stripen is computed without the parities
 	       * (0 for A0, A1, A2, 1 for B0, B1, B2, etc.).
 	       */
+	      if (nparities >= nstripes)
+		return grub_error (GRUB_ERR_BAD_FS,
+				   "invalid RAID5/6: nparities >= nstripes");
 	      high = grub_divmod64 (stripe_nr, nstripes - nparities, &stripen);
 
 	      /*
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 094/117] fs/btrfs: Squash some uninitialized reads
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (92 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 093/117] fs/btrfs: Validate the number of stripes/parities in RAID5/6 Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 095/117] kern/parser: Fix a memory leak Daniel Kiper
                   ` (24 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Daniel Axtens <dja@axtens.net>

We need to check errors before calling into a function that uses the result.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/fs/btrfs.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index c4ba5f110..63203034d 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -383,9 +383,9 @@ next (struct grub_btrfs_data *data,
 
       err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr),
 				     &head, sizeof (head), 0);
+      if (err)
+	return -err;
       check_btrfs_header (data, &head, grub_le_to_cpu64 (node.addr));
-      if (err)
-	return -err;
 
       save_ref (desc, grub_le_to_cpu64 (node.addr), 0,
 		grub_le_to_cpu32 (head.nitems), !head.level);
@@ -445,9 +445,9 @@ lower_bound (struct grub_btrfs_data *data,
       /* FIXME: preread few nodes into buffer. */
       err = grub_btrfs_read_logical (data, addr, &head, sizeof (head),
 				     recursion_depth + 1);
+      if (err)
+	return err;
       check_btrfs_header (data, &head, addr);
-      if (err)
-	return err;
       addr += sizeof (head);
       if (head.level)
 	{
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 095/117] kern/parser: Fix a memory leak
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (93 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 094/117] fs/btrfs: Squash some uninitialized reads Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 096/117] kern/parser: Introduce process_char() helper Daniel Kiper
                   ` (23 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

The getline() function supplied to grub_parser_split_cmdline() returns
a newly allocated buffer and can be called multiple times, but the
returned buffer is never freed.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/parser.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index d1cf061ad..39e4df65b 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -140,6 +140,7 @@ grub_parser_split_cmdline (const char *cmdline,
   char buffer[1024];
   char *bp = buffer;
   char *rd = (char *) cmdline;
+  char *rp = rd;
   char varname[200];
   char *vp = varname;
   char *args;
@@ -149,10 +150,18 @@ grub_parser_split_cmdline (const char *cmdline,
   *argv = NULL;
   do
     {
-      if (!rd || !*rd)
+      if (rp == NULL || *rp == '\0')
 	{
+	  if (rd != cmdline)
+	    {
+	      grub_free (rd);
+	      rd = rp = NULL;
+	    }
 	  if (getline)
-	    getline (&rd, 1, getline_data);
+	    {
+	      getline (&rd, 1, getline_data);
+	      rp = rd;
+	    }
 	  else
 	    break;
 	}
@@ -160,12 +169,12 @@ grub_parser_split_cmdline (const char *cmdline,
       if (!rd)
 	break;
 
-      for (; *rd; rd++)
+      for (; *rp != '\0'; rp++)
 	{
 	  grub_parser_state_t newstate;
 	  char use;
 
-	  newstate = grub_parser_cmdline_state (state, *rd, &use);
+	  newstate = grub_parser_cmdline_state (state, *rp, &use);
 
 	  /* If a variable was being processed and this character does
 	     not describe the variable anymore, write the variable to
@@ -198,6 +207,9 @@ grub_parser_split_cmdline (const char *cmdline,
     }
   while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
 
+  if (rd != cmdline)
+    grub_free (rd);
+
   /* A special case for when the last character was part of a
      variable.  */
   add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 096/117] kern/parser: Introduce process_char() helper
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (94 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 095/117] kern/parser: Fix a memory leak Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 097/117] kern/parser: Introduce terminate_arg() helper Daniel Kiper
                   ` (22 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

grub_parser_split_cmdline() iterates over each command line character.
In order to add error checking and to simplify the subsequent error
handling, split the character processing in to a separate function.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/parser.c | 74 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 46 insertions(+), 28 deletions(-)

diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 39e4df65b..0d3582bd8 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -1,7 +1,7 @@
 /* parser.c - the part of the parser that can return partial tokens */
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2005,2007,2009  Free Software Foundation, Inc.
+ *  Copyright (C) 2005,2007,2009,2021  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
@@ -129,6 +129,46 @@ add_var (char *varname, char **bp, char **vp,
     *((*bp)++) = *val;
 }
 
+static grub_err_t
+process_char (char c, char *buffer, char **bp, char *varname, char **vp,
+	      grub_parser_state_t state, int *argc,
+	      grub_parser_state_t *newstate)
+{
+  char use;
+
+  *newstate = grub_parser_cmdline_state (state, c, &use);
+
+  /*
+   * If a variable was being processed and this character does
+   * not describe the variable anymore, write the variable to
+   * the buffer.
+   */
+  add_var (varname, bp, vp, state, *newstate);
+
+  if (check_varstate (*newstate))
+    {
+      if (use)
+	*((*vp)++) = use;
+    }
+  else if (*newstate == GRUB_PARSER_STATE_TEXT &&
+	   state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
+    {
+      /*
+       * Don't add more than one argument if multiple
+       * spaces are used.
+       */
+      if (*bp != buffer && *((*bp) - 1) != '\0')
+	{
+	  *((*bp)++) = '\0';
+	  (*argc)++;
+	}
+    }
+  else if (use)
+    *((*bp)++) = use;
+
+  return GRUB_ERR_NONE;
+}
+
 grub_err_t
 grub_parser_split_cmdline (const char *cmdline,
 			   grub_reader_getline_t getline, void *getline_data,
@@ -172,35 +212,13 @@ grub_parser_split_cmdline (const char *cmdline,
       for (; *rp != '\0'; rp++)
 	{
 	  grub_parser_state_t newstate;
-	  char use;
 
-	  newstate = grub_parser_cmdline_state (state, *rp, &use);
-
-	  /* If a variable was being processed and this character does
-	     not describe the variable anymore, write the variable to
-	     the buffer.  */
-	  add_var (varname, &bp, &vp, state, newstate);
-
-	  if (check_varstate (newstate))
-	    {
-	      if (use)
-		*(vp++) = use;
-	    }
-	  else
+	  if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
+			    &newstate) != GRUB_ERR_NONE)
 	    {
-	      if (newstate == GRUB_PARSER_STATE_TEXT
-		  && state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
-		{
-		  /* Don't add more than one argument if multiple
-		     spaces are used.  */
-		  if (bp != buffer && *(bp - 1))
-		    {
-		      *(bp++) = '\0';
-		      (*argc)++;
-		    }
-		}
-	      else if (use)
-		*(bp++) = use;
+	      if (rd != cmdline)
+		grub_free (rd);
+	      return grub_errno;
 	    }
 	  state = newstate;
 	}
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 097/117] kern/parser: Introduce terminate_arg() helper
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (95 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 096/117] kern/parser: Introduce process_char() helper Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 098/117] kern/parser: Refactor grub_parser_split_cmdline() cleanup Daniel Kiper
                   ` (21 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

process_char() and grub_parser_split_cmdline() use similar code for
terminating the most recent argument. Add a helper function for this.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/parser.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 0d3582bd8..572c67089 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -129,6 +129,16 @@ add_var (char *varname, char **bp, char **vp,
     *((*bp)++) = *val;
 }
 
+static void
+terminate_arg (char *buffer, char **bp, int *argc)
+{
+  if (*bp != buffer && *((*bp) - 1) != '\0')
+    {
+      *((*bp)++) = '\0';
+      (*argc)++;
+    }
+}
+
 static grub_err_t
 process_char (char c, char *buffer, char **bp, char *varname, char **vp,
 	      grub_parser_state_t state, int *argc,
@@ -157,11 +167,7 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
        * Don't add more than one argument if multiple
        * spaces are used.
        */
-      if (*bp != buffer && *((*bp) - 1) != '\0')
-	{
-	  *((*bp)++) = '\0';
-	  (*argc)++;
-	}
+      terminate_arg (buffer, bp, argc);
     }
   else if (use)
     *((*bp)++) = use;
@@ -232,11 +238,8 @@ grub_parser_split_cmdline (const char *cmdline,
      variable.  */
   add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
 
-  if (bp != buffer && *(bp - 1))
-    {
-      *(bp++) = '\0';
-      (*argc)++;
-    }
+  /* Ensure that the last argument is terminated. */
+  terminate_arg (buffer, &bp, argc);
 
   /* If there are no args, then we're done. */
   if (!*argc)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 098/117] kern/parser: Refactor grub_parser_split_cmdline() cleanup
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (96 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 097/117] kern/parser: Introduce terminate_arg() helper Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 099/117] kern/buffer: Add variable sized heap buffer Daniel Kiper
                   ` (20 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

Introduce a common function epilogue used for cleaning up on all
return paths, which will simplify additional error handling to be
introduced in a subsequent commit.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/parser.c | 35 ++++++++++++++++++++---------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 572c67089..e010eaa1f 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -221,19 +221,13 @@ grub_parser_split_cmdline (const char *cmdline,
 
 	  if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
 			    &newstate) != GRUB_ERR_NONE)
-	    {
-	      if (rd != cmdline)
-		grub_free (rd);
-	      return grub_errno;
-	    }
+	    goto fail;
+
 	  state = newstate;
 	}
     }
   while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
 
-  if (rd != cmdline)
-    grub_free (rd);
-
   /* A special case for when the last character was part of a
      variable.  */
   add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
@@ -243,20 +237,20 @@ grub_parser_split_cmdline (const char *cmdline,
 
   /* If there are no args, then we're done. */
   if (!*argc)
-    return 0;
+    {
+      grub_errno = GRUB_ERR_NONE;
+      goto out;
+    }
 
   /* Reserve memory for the return values.  */
   args = grub_malloc (bp - buffer);
   if (!args)
-    return grub_errno;
+    goto fail;
   grub_memcpy (args, buffer, bp - buffer);
 
   *argv = grub_calloc (*argc + 1, sizeof (char *));
   if (!*argv)
-    {
-      grub_free (args);
-      return grub_errno;
-    }
+    goto fail;
 
   /* The arguments are separated with 0's, setup argv so it points to
      the right values.  */
@@ -269,7 +263,18 @@ grub_parser_split_cmdline (const char *cmdline,
       bp++;
     }
 
-  return 0;
+  grub_errno = GRUB_ERR_NONE;
+
+ out:
+  if (rd != cmdline)
+    grub_free (rd);
+
+  return grub_errno;
+
+ fail:
+  grub_free (*argv);
+  grub_free (args);
+  goto out;
 }
 
 /* Helper for grub_parser_execute.  */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 099/117] kern/buffer: Add variable sized heap buffer
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (97 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 098/117] kern/parser: Refactor grub_parser_split_cmdline() cleanup Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow Daniel Kiper
                   ` (19 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

Add a new variable sized heap buffer type (grub_buffer_t) with simple
operations for appending data, accessing the data and maintaining
a read cursor.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/Makefile.core.def |   1 +
 grub-core/kern/buffer.c     | 117 +++++++++++++++++++++++++++++++++++
 include/grub/buffer.h       | 144 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 262 insertions(+)
 create mode 100644 grub-core/kern/buffer.c
 create mode 100644 include/grub/buffer.h

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1f450a98f..8022e1c0a 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -123,6 +123,7 @@ kernel = {
   riscv32_efi_startup = kern/riscv/efi/startup.S;
   riscv64_efi_startup = kern/riscv/efi/startup.S;
 
+  common = kern/buffer.c;
   common = kern/command.c;
   common = kern/corecmd.c;
   common = kern/device.c;
diff --git a/grub-core/kern/buffer.c b/grub-core/kern/buffer.c
new file mode 100644
index 000000000..9f5f8b867
--- /dev/null
+++ b/grub-core/kern/buffer.c
@@ -0,0 +1,117 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2021  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/>.
+ */
+
+#include <grub/buffer.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/safemath.h>
+#include <grub/types.h>
+
+grub_buffer_t
+grub_buffer_new (grub_size_t sz)
+{
+  struct grub_buffer *ret;
+
+  ret = (struct grub_buffer *) grub_malloc (sizeof (*ret));
+  if (ret == NULL)
+    return NULL;
+
+  ret->data = (grub_uint8_t *) grub_malloc (sz);
+  if (ret->data == NULL)
+    {
+      grub_free (ret);
+      return NULL;
+    }
+
+  ret->sz = sz;
+  ret->pos = 0;
+  ret->used = 0;
+
+  return ret;
+}
+
+void
+grub_buffer_free (grub_buffer_t buf)
+{
+  grub_free (buf->data);
+  grub_free (buf);
+}
+
+grub_err_t
+grub_buffer_ensure_space (grub_buffer_t buf, grub_size_t req)
+{
+  grub_uint8_t *d;
+  grub_size_t newsz = 1;
+
+  /* Is the current buffer size adequate? */
+  if (buf->sz >= req)
+    return GRUB_ERR_NONE;
+
+  /* Find the smallest power-of-2 size that satisfies the request. */
+  while (newsz < req)
+    {
+      if (newsz == 0)
+	return grub_error (GRUB_ERR_OUT_OF_RANGE,
+			   N_("requested buffer size is too large"));
+      newsz <<= 1;
+    }
+
+  d = (grub_uint8_t *) grub_realloc (buf->data, newsz);
+  if (d == NULL)
+    return grub_errno;
+
+  buf->data = d;
+  buf->sz = newsz;
+
+  return GRUB_ERR_NONE;
+}
+
+void *
+grub_buffer_take_data (grub_buffer_t buf)
+{
+  void *data = buf->data;
+
+  buf->data = NULL;
+  buf->sz = buf->pos = buf->used = 0;
+
+  return data;
+}
+
+void
+grub_buffer_reset (grub_buffer_t buf)
+{
+  buf->pos = buf->used = 0;
+}
+
+grub_err_t
+grub_buffer_advance_read_pos (grub_buffer_t buf, grub_size_t n)
+{
+  grub_size_t newpos;
+
+  if (grub_add (buf->pos, n, &newpos))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+
+  if (newpos > buf->used)
+    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+		       N_("new read is position beyond the end of the written data"));
+
+  buf->pos = newpos;
+
+  return GRUB_ERR_NONE;
+}
diff --git a/include/grub/buffer.h b/include/grub/buffer.h
new file mode 100644
index 000000000..f4b10cf28
--- /dev/null
+++ b/include/grub/buffer.h
@@ -0,0 +1,144 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2021  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/>.
+ */
+
+#ifndef GRUB_BUFFER_H
+#define GRUB_BUFFER_H	1
+
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/safemath.h>
+#include <grub/types.h>
+
+struct grub_buffer
+{
+  grub_uint8_t *data;
+  grub_size_t sz;
+  grub_size_t pos;
+  grub_size_t used;
+};
+
+/*
+ * grub_buffer_t represents a simple variable sized byte buffer with
+ * read and write cursors. It currently only implements
+ * functionality required by the only user in GRUB (append byte[s],
+ * peeking data at a specified position and updating the read cursor.
+ * Some things that this doesn't do yet are:
+ * - Reading a portion of the buffer by copying data from the current
+ *   read position in to a caller supplied destination buffer and then
+ *   automatically updating the read cursor.
+ * - Dropping the read part at the start of the buffer when an append
+ *   requires more space.
+ */
+typedef struct grub_buffer *grub_buffer_t;
+
+/* Allocate a new buffer with the specified initial size. */
+extern grub_buffer_t grub_buffer_new (grub_size_t sz);
+
+/* Free the buffer and its resources. */
+extern void grub_buffer_free (grub_buffer_t buf);
+
+/* Return the number of unread bytes in this buffer. */
+static inline grub_size_t
+grub_buffer_get_unread_bytes (grub_buffer_t buf)
+{
+  return buf->used - buf->pos;
+}
+
+/*
+ * Ensure that the buffer size is at least the requested
+ * number of bytes.
+ */
+extern grub_err_t grub_buffer_ensure_space (grub_buffer_t buf, grub_size_t req);
+
+/*
+ * Append the specified number of bytes from the supplied
+ * data to the buffer.
+ */
+static inline grub_err_t
+grub_buffer_append_data (grub_buffer_t buf, const void *data, grub_size_t len)
+{
+  grub_size_t req;
+
+  if (grub_add (buf->used, len, &req))
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+
+  if (grub_buffer_ensure_space (buf, req) != GRUB_ERR_NONE)
+    return grub_errno;
+
+  grub_memcpy (&buf->data[buf->used], data, len);
+  buf->used = req;
+
+  return GRUB_ERR_NONE;
+}
+
+/* Append the supplied character to the buffer. */
+static inline grub_err_t
+grub_buffer_append_char (grub_buffer_t buf, char c)
+{
+  return grub_buffer_append_data (buf, &c, 1);
+}
+
+/*
+ * Forget and return the underlying data buffer. The caller
+ * becomes the owner of this buffer, and must free it when it
+ * is no longer required.
+ */
+extern void *grub_buffer_take_data (grub_buffer_t buf);
+
+/* Reset this buffer. Note that this does not deallocate any resources. */
+void grub_buffer_reset (grub_buffer_t buf);
+
+/*
+ * Return a pointer to the underlying data buffer at the specified
+ * offset from the current read position. Note that this pointer may
+ * become invalid if the buffer is mutated further.
+ */
+static inline void *
+grub_buffer_peek_data_at (grub_buffer_t buf, grub_size_t off)
+{
+  if (grub_add (buf->pos, off, &off))
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected."));
+      return NULL;
+    }
+
+  if (off >= buf->used)
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("peek out of range"));
+      return NULL;
+    }
+
+  return &buf->data[off];
+}
+
+/*
+ * Return a pointer to the underlying data buffer at the current
+ * read position. Note that this pointer may become invalid if the
+ * buffer is mutated further.
+ */
+static inline void *
+grub_buffer_peek_data (grub_buffer_t buf)
+{
+  return grub_buffer_peek_data_at (buf, 0);
+}
+
+/* Advance the read position by the specified number of bytes. */
+extern grub_err_t grub_buffer_advance_read_pos (grub_buffer_t buf, grub_size_t n);
+
+#endif /* GRUB_BUFFER_H */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (98 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 099/117] kern/buffer: Add variable sized heap buffer Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-06-10 11:55   ` Paul Menzel
  2021-03-02 18:01 ` [SECURITY PATCH 101/117] kern/efi: Add initial stack protector implementation Daniel Kiper
                   ` (18 subsequent siblings)
  118 siblings, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

grub_parser_split_cmdline() expands variable names present in the supplied
command line in to their corresponding variable contents and uses a 1 kiB
stack buffer for temporary storage without sufficient bounds checking. If
the function is called with a command line that references a variable with
a sufficiently large payload, it is possible to overflow the stack
buffer via tab completion, corrupt the stack frame and potentially
control execution.

Fixes: CVE-2020-27749

Reported-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/parser.c | 110 +++++++++++++++++++++++++++++-------------------
 1 file changed, 67 insertions(+), 43 deletions(-)

diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index e010eaa1f..6ab7aa427 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -18,6 +18,7 @@
  */
 
 #include <grub/parser.h>
+#include <grub/buffer.h>
 #include <grub/env.h>
 #include <grub/misc.h>
 #include <grub/mm.h>
@@ -107,8 +108,8 @@ check_varstate (grub_parser_state_t s)
 }
 
 
-static void
-add_var (char *varname, char **bp, char **vp,
+static grub_err_t
+add_var (grub_buffer_t varname, grub_buffer_t buf,
 	 grub_parser_state_t state, grub_parser_state_t newstate)
 {
   const char *val;
@@ -116,31 +117,41 @@ add_var (char *varname, char **bp, char **vp,
   /* Check if a variable was being read in and the end of the name
      was reached.  */
   if (!(check_varstate (state) && !check_varstate (newstate)))
-    return;
+    return GRUB_ERR_NONE;
 
-  *((*vp)++) = '\0';
-  val = grub_env_get (varname);
-  *vp = varname;
+  if (grub_buffer_append_char (varname, '\0') != GRUB_ERR_NONE)
+    return grub_errno;
+
+  val = grub_env_get ((const char *) grub_buffer_peek_data (varname));
+  grub_buffer_reset (varname);
   if (!val)
-    return;
+    return GRUB_ERR_NONE;
 
   /* Insert the contents of the variable in the buffer.  */
-  for (; *val; val++)
-    *((*bp)++) = *val;
+  return grub_buffer_append_data (buf, val, grub_strlen (val));
 }
 
-static void
-terminate_arg (char *buffer, char **bp, int *argc)
+static grub_err_t
+terminate_arg (grub_buffer_t buffer, int *argc)
 {
-  if (*bp != buffer && *((*bp) - 1) != '\0')
-    {
-      *((*bp)++) = '\0';
-      (*argc)++;
-    }
+  grub_size_t unread = grub_buffer_get_unread_bytes (buffer);
+
+  if (unread == 0)
+    return GRUB_ERR_NONE;
+
+  if (*(const char *) grub_buffer_peek_data_at (buffer, unread - 1) == '\0')
+    return GRUB_ERR_NONE;
+
+  if (grub_buffer_append_char (buffer, '\0') != GRUB_ERR_NONE)
+    return grub_errno;
+
+  (*argc)++;
+
+  return GRUB_ERR_NONE;
 }
 
 static grub_err_t
-process_char (char c, char *buffer, char **bp, char *varname, char **vp,
+process_char (char c, grub_buffer_t buffer, grub_buffer_t varname,
 	      grub_parser_state_t state, int *argc,
 	      grub_parser_state_t *newstate)
 {
@@ -153,12 +164,13 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
    * not describe the variable anymore, write the variable to
    * the buffer.
    */
-  add_var (varname, bp, vp, state, *newstate);
+  if (add_var (varname, buffer, state, *newstate) != GRUB_ERR_NONE)
+    return grub_errno;
 
   if (check_varstate (*newstate))
     {
       if (use)
-	*((*vp)++) = use;
+        return grub_buffer_append_char (varname, use);
     }
   else if (*newstate == GRUB_PARSER_STATE_TEXT &&
 	   state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
@@ -167,10 +179,10 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
        * Don't add more than one argument if multiple
        * spaces are used.
        */
-      terminate_arg (buffer, bp, argc);
+      return terminate_arg (buffer, argc);
     }
   else if (use)
-    *((*bp)++) = use;
+    return grub_buffer_append_char (buffer, use);
 
   return GRUB_ERR_NONE;
 }
@@ -181,19 +193,22 @@ grub_parser_split_cmdline (const char *cmdline,
 			   int *argc, char ***argv)
 {
   grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
-  /* XXX: Fixed size buffer, perhaps this buffer should be dynamically
-     allocated.  */
-  char buffer[1024];
-  char *bp = buffer;
+  grub_buffer_t buffer, varname;
   char *rd = (char *) cmdline;
   char *rp = rd;
-  char varname[200];
-  char *vp = varname;
-  char *args;
   int i;
 
   *argc = 0;
   *argv = NULL;
+
+  buffer = grub_buffer_new (1024);
+  if (buffer == NULL)
+    return grub_errno;
+
+  varname = grub_buffer_new (200);
+  if (varname == NULL)
+    goto fail;
+
   do
     {
       if (rp == NULL || *rp == '\0')
@@ -219,7 +234,7 @@ grub_parser_split_cmdline (const char *cmdline,
 	{
 	  grub_parser_state_t newstate;
 
-	  if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
+	  if (process_char (*rp, buffer, varname, state, argc,
 			    &newstate) != GRUB_ERR_NONE)
 	    goto fail;
 
@@ -230,10 +245,12 @@ grub_parser_split_cmdline (const char *cmdline,
 
   /* A special case for when the last character was part of a
      variable.  */
-  add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
+  if (add_var (varname, buffer, state, GRUB_PARSER_STATE_TEXT) != GRUB_ERR_NONE)
+    goto fail;
 
   /* Ensure that the last argument is terminated. */
-  terminate_arg (buffer, &bp, argc);
+  if (terminate_arg (buffer, argc) != GRUB_ERR_NONE)
+    goto fail;
 
   /* If there are no args, then we're done. */
   if (!*argc)
@@ -242,38 +259,45 @@ grub_parser_split_cmdline (const char *cmdline,
       goto out;
     }
 
-  /* Reserve memory for the return values.  */
-  args = grub_malloc (bp - buffer);
-  if (!args)
-    goto fail;
-  grub_memcpy (args, buffer, bp - buffer);
-
   *argv = grub_calloc (*argc + 1, sizeof (char *));
   if (!*argv)
     goto fail;
 
   /* The arguments are separated with 0's, setup argv so it points to
      the right values.  */
-  bp = args;
   for (i = 0; i < *argc; i++)
     {
-      (*argv)[i] = bp;
-      while (*bp)
-	bp++;
-      bp++;
+      char *arg;
+
+      if (i > 0)
+	{
+	  if (grub_buffer_advance_read_pos (buffer, 1) != GRUB_ERR_NONE)
+	    goto fail;
+	}
+
+      arg = (char *) grub_buffer_peek_data (buffer);
+      if (arg == NULL ||
+	  grub_buffer_advance_read_pos (buffer, grub_strlen (arg)) != GRUB_ERR_NONE)
+	goto fail;
+
+      (*argv)[i] = arg;
     }
 
+  /* Keep memory for the return values. */
+  grub_buffer_take_data (buffer);
+
   grub_errno = GRUB_ERR_NONE;
 
  out:
   if (rd != cmdline)
     grub_free (rd);
+  grub_buffer_free (buffer);
+  grub_buffer_free (varname);
 
   return grub_errno;
 
  fail:
   grub_free (*argv);
-  grub_free (args);
   goto out;
 }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 101/117] kern/efi: Add initial stack protector implementation
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (99 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 102/117] util/mkimage: Remove unused code to add BSS section Daniel Kiper
                   ` (17 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Chris Coulson <chris.coulson@canonical.com>

It works only on UEFI platforms but can be quite easily extended to
others architectures and platforms if needed.

Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Marco A Benatto <mbenatto@redhat.com>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
---
 acinclude.m4                   | 38 +++++++++++++++++++++++++++--
 configure.ac                   | 44 ++++++++++++++++++++++++++++++----
 grub-core/Makefile.am          |  1 +
 grub-core/kern/efi/init.c      | 54 ++++++++++++++++++++++++++++++++++++++++++
 include/grub/efi/api.h         | 19 +++++++++++++++
 include/grub/stack_protector.h | 30 +++++++++++++++++++++++
 6 files changed, 179 insertions(+), 7 deletions(-)
 create mode 100644 include/grub/stack_protector.h

diff --git a/acinclude.m4 b/acinclude.m4
index 78cdf6e1d..6e14bb553 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -305,9 +305,9 @@ fi
 ])
 
 \f
-dnl Check if the C compiler supports `-fstack-protector'.
+dnl Check if the C compiler supports the stack protector
 AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[
-[# Smashing stack protector.
+[# Stack smashing protector.
 ssp_possible=yes]
 AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector'])
 # Is this a reliable test case?
@@ -324,6 +324,40 @@ else
   ssp_possible=no]
   AC_MSG_RESULT([no])
 [fi]
+[# Strong stack smashing protector.
+ssp_strong_possible=yes]
+AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector-strong'])
+# Is this a reliable test case?
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[
+void foo (void) { volatile char a[8]; a[3]; }
+]])])
+[# `$CC -c -o ...' might not be portable.  But, oh, well...  Is calling
+# `ac_compile' like this correct, after all?
+if eval "$ac_compile -S -fstack-protector-strong -o conftest.s" 2> /dev/null; then]
+  AC_MSG_RESULT([yes])
+  [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
+  rm -f conftest.s
+else
+  ssp_strong_possible=no]
+  AC_MSG_RESULT([no])
+[fi]
+[# Global stack smashing protector.
+ssp_global_possible=yes]
+AC_MSG_CHECKING([whether `$CC' accepts `-mstack-protector-guard=global'])
+# Is this a reliable test case?
+AC_LANG_CONFTEST([AC_LANG_SOURCE([[
+void foo (void) { volatile char a[8]; a[3]; }
+]])])
+[# `$CC -c -o ...' might not be portable.  But, oh, well...  Is calling
+# `ac_compile' like this correct, after all?
+if eval "$ac_compile -S -fstack-protector -mstack-protector-guard=global -o conftest.s" 2> /dev/null; then]
+  AC_MSG_RESULT([yes])
+  [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
+  rm -f conftest.s
+else
+  ssp_global_possible=no]
+  AC_MSG_RESULT([no])
+[fi]
 ])
 
 dnl Check if the C compiler supports `-mstack-arg-probe' (Cygwin).
diff --git a/configure.ac b/configure.ac
index 7c10a4db7..676137deb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1312,12 +1312,41 @@ fi]
 
 CFLAGS="$TARGET_CFLAGS"
 
-# Smashing stack protector.
+# Stack smashing protector.
 grub_CHECK_STACK_PROTECTOR
-# Need that, because some distributions ship compilers that include
-# `-fstack-protector' in the default specs.
-if test "x$ssp_possible" = xyes; then
-  TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector"
+AC_ARG_ENABLE([stack-protector],
+	      AS_HELP_STRING([--enable-stack-protector],
+			     [enable the stack protector]),
+	      [],
+	      [enable_stack_protector=no])
+if test "x$enable_stack_protector" = xno; then
+  if test "x$ssp_possible" = xyes; then
+    # Need that, because some distributions ship compilers that include
+    # `-fstack-protector' in the default specs.
+    TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector"
+  fi
+elif test "x$platform" != xefi; then
+  AC_MSG_ERROR([--enable-stack-protector is only supported on EFI platforms])
+elif test "x$ssp_global_possible" != xyes; then
+  AC_MSG_ERROR([--enable-stack-protector is not supported (compiler doesn't support -mstack-protector-guard=global)])
+else
+  TARGET_CFLAGS="$TARGET_CFLAGS -mstack-protector-guard=global"
+  if test "x$enable_stack_protector" = xyes; then
+    if test "x$ssp_possible" != xyes; then
+      AC_MSG_ERROR([--enable-stack-protector is not supported (compiler doesn't support -fstack-protector)])
+    fi
+    TARGET_CFLAGS="$TARGET_CFLAGS -fstack-protector"
+  elif test "x$enable_stack_protector" = xstrong; then
+    if test "x$ssp_strong_possible" != xyes; then
+      AC_MSG_ERROR([--enable-stack-protector=strong is not supported (compiler doesn't support -fstack-protector-strong)])
+    fi
+    TARGET_CFLAGS="$TARGET_CFLAGS -fstack-protector-strong"
+  else
+    # Note, -fstack-protector-all requires that the protector is disabled for
+    # functions that appear in the call stack when the canary is initialized.
+    AC_MSG_ERROR([invalid value $enable_stack_protector for --enable-stack-protector])
+  fi
+  TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DGRUB_STACK_PROTECTOR=1"
 fi
 
 CFLAGS="$TARGET_CFLAGS"
@@ -2132,5 +2161,10 @@ echo "Without liblzma (no support for XZ-compressed mips images) ($liblzma_excus
 else
 echo "With liblzma from $LIBLZMA (support for XZ-compressed mips images)"
 fi
+if test "x$enable_stack_protector" != xno; then
+echo "With stack smashing protector: Yes"
+else
+echo "With stack smashing protector: No"
+fi
 echo "*******************************************************"
 ]
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 30e23ada2..ee88e44e9 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -90,6 +90,7 @@ endif
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/verify.h
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index 133346509..7facacf09 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -27,6 +27,58 @@
 #include <grub/env.h>
 #include <grub/mm.h>
 #include <grub/kernel.h>
+#include <grub/stack_protector.h>
+
+#ifdef GRUB_STACK_PROTECTOR
+
+static grub_efi_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID;
+
+/*
+ * Don't put this on grub_efi_init()'s local stack to avoid it
+ * getting a stack check.
+ */
+static grub_efi_uint8_t stack_chk_guard_buf[32];
+
+grub_addr_t __stack_chk_guard;
+
+void __attribute__ ((noreturn))
+__stack_chk_fail (void)
+{
+  /*
+   * Assume it's not safe to call into EFI Boot Services. Sorry, that
+   * means no console message here.
+   */
+  do
+    {
+      /* Do not optimize out the loop. */
+      asm volatile ("");
+    }
+  while (1);
+}
+
+static void
+stack_protector_init (void)
+{
+  grub_efi_rng_protocol_t *rng;
+
+  /* Set up the stack canary. Make errors here non-fatal for now. */
+  rng = grub_efi_locate_protocol (&rng_protocol_guid, NULL);
+  if (rng != NULL)
+    {
+      grub_efi_status_t status;
+
+      status = efi_call_4 (rng->get_rng, rng, NULL, sizeof (stack_chk_guard_buf),
+			   stack_chk_guard_buf);
+      if (status == GRUB_EFI_SUCCESS)
+	grub_memcpy (&__stack_chk_guard, stack_chk_guard_buf, sizeof (__stack_chk_guard));
+    }
+}
+#else
+static void
+stack_protector_init (void)
+{
+}
+#endif
 
 grub_addr_t grub_modbase;
 
@@ -38,6 +90,8 @@ grub_efi_init (void)
      messages.  */
   grub_console_init ();
 
+  stack_protector_init ();
+
   /* Initialize the memory management system.  */
   grub_efi_mm_init ();
 
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 39733585b..297a17074 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -344,6 +344,11 @@
     { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
   }
 
+#define GRUB_EFI_RNG_PROTOCOL_GUID \
+  { 0x3152bca5, 0xeade, 0x433d, \
+    { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \
+  }
+
 struct grub_efi_sal_system_table
 {
   grub_uint32_t signature;
@@ -1705,6 +1710,20 @@ struct grub_efi_shim_lock_protocol
 };
 typedef struct grub_efi_shim_lock_protocol grub_efi_shim_lock_protocol_t;
 
+typedef grub_efi_guid_t grub_efi_rng_algorithm_t;
+
+struct grub_efi_rng_protocol
+{
+  grub_efi_status_t (*get_info) (struct grub_efi_rng_protocol *this,
+				 grub_efi_uintn_t *rng_algorithm_list_size,
+				 grub_efi_rng_algorithm_t *rng_algorithm_list);
+  grub_efi_status_t (*get_rng) (struct grub_efi_rng_protocol *this,
+				grub_efi_rng_algorithm_t *rng_algorithm,
+				grub_efi_uintn_t rng_value_length,
+				grub_efi_uint8_t *rng_value);
+};
+typedef struct grub_efi_rng_protocol grub_efi_rng_protocol_t;
+
 #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
   || defined(__riscv)
diff --git a/include/grub/stack_protector.h b/include/grub/stack_protector.h
new file mode 100644
index 000000000..c88dc00b5
--- /dev/null
+++ b/include/grub/stack_protector.h
@@ -0,0 +1,30 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2021  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/>.
+ */
+
+#ifndef GRUB_STACK_PROTECTOR_H
+#define GRUB_STACK_PROTECTOR_H	1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+
+#ifdef GRUB_STACK_PROTECTOR
+extern grub_addr_t EXPORT_VAR (__stack_chk_guard);
+extern void __attribute__ ((noreturn)) EXPORT_FUNC (__stack_chk_fail) (void);
+#endif
+
+#endif /* GRUB_STACK_PROTECTOR_H */
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 102/117] util/mkimage: Remove unused code to add BSS section
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (100 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 101/117] kern/efi: Add initial stack protector implementation Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 103/117] util/mkimage: Use grub_host_to_target32() instead of grub_cpu_to_le32() Daniel Kiper
                   ` (16 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Javier Martinez Canillas <javierm@redhat.com>

The code is compiled out so there is no reason to keep it.

Additionally, don't set bss_size field since we do not add a BSS section.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/mkimage.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/util/mkimage.c b/util/mkimage.c
index 37d6249f1..32bb8ea68 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1304,7 +1304,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	    o->code_size = grub_host_to_target32 (layout.exec_size);
 	    o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
 					     - header_size);
-	    o->bss_size = grub_cpu_to_le32 (layout.bss_size);
 	    o->entry_addr = grub_cpu_to_le32 (layout.start_address);
 	    o->code_base = grub_cpu_to_le32 (header_size);
 
@@ -1342,7 +1341,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	    o->code_size = grub_host_to_target32 (layout.exec_size);
 	    o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
 					     - header_size);
-	    o->bss_size = grub_cpu_to_le32 (layout.bss_size);
 	    o->entry_addr = grub_cpu_to_le32 (layout.start_address);
 	    o->code_base = grub_cpu_to_le32 (header_size);
 	    o->image_base = 0;
@@ -1387,21 +1385,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
 			      | GRUB_PE32_SCN_MEM_READ
 			      | GRUB_PE32_SCN_MEM_WRITE);
-
-#if 0
-	bss_section = data_section + 1;
-	strcpy (bss_section->name, ".bss");
-	bss_section->virtual_size = grub_cpu_to_le32 (layout.bss_size);
-	bss_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size);
-	bss_section->raw_data_size = 0;
-	bss_section->raw_data_offset = 0;
-	bss_section->characteristics
-	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_MEM_READ
-			      | GRUB_PE32_SCN_MEM_WRITE
-			      | GRUB_PE32_SCN_ALIGN_64BYTES
-			      | GRUB_PE32_SCN_CNT_INITIALIZED_DATA
-			      | 0x80);
-#endif
     
 	mods_section = data_section + 1;
 	strcpy (mods_section->name, "mods");
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 103/117] util/mkimage: Use grub_host_to_target32() instead of grub_cpu_to_le32()
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (101 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 102/117] util/mkimage: Remove unused code to add BSS section Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 104/117] util/mkimage: Always use grub_host_to_target32() to initialize PE stack and heap stuff Daniel Kiper
                   ` (15 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Peter Jones <pjones@redhat.com>

The latter doesn't take into account the target image endianness. There is
a grub_cpu_to_le32_compile_time() but no compile time variant for function
grub_host_to_target32(). So, let's keep using the other one for this case.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/mkimage.c | 44 ++++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/util/mkimage.c b/util/mkimage.c
index 32bb8ea68..02944f28e 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1302,10 +1302,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	       + sizeof (struct grub_pe32_coff_header));
 	    o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
 	    o->code_size = grub_host_to_target32 (layout.exec_size);
-	    o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
+	    o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
 					     - header_size);
-	    o->entry_addr = grub_cpu_to_le32 (layout.start_address);
-	    o->code_base = grub_cpu_to_le32 (header_size);
+	    o->entry_addr = grub_host_to_target32 (layout.start_address);
+	    o->code_base = grub_host_to_target32 (header_size);
 
 	    o->data_base = grub_host_to_target32 (header_size + layout.exec_size);
 
@@ -1339,10 +1339,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	       + sizeof (struct grub_pe32_coff_header));
 	    o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
 	    o->code_size = grub_host_to_target32 (layout.exec_size);
-	    o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
+	    o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
 					     - header_size);
-	    o->entry_addr = grub_cpu_to_le32 (layout.start_address);
-	    o->code_base = grub_cpu_to_le32 (header_size);
+	    o->entry_addr = grub_host_to_target32 (layout.start_address);
+	    o->code_base = grub_host_to_target32 (header_size);
 	    o->image_base = 0;
 	    o->section_alignment = grub_host_to_target32 (image_target->section_align);
 	    o->file_alignment = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
@@ -1366,10 +1366,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	/* The sections.  */
 	text_section = sections;
 	strcpy (text_section->name, ".text");
-	text_section->virtual_size = grub_cpu_to_le32 (layout.exec_size);
-	text_section->virtual_address = grub_cpu_to_le32 (header_size);
-	text_section->raw_data_size = grub_cpu_to_le32 (layout.exec_size);
-	text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
+	text_section->virtual_size = grub_host_to_target32 (layout.exec_size);
+	text_section->virtual_address = grub_host_to_target32 (header_size);
+	text_section->raw_data_size = grub_host_to_target32 (layout.exec_size);
+	text_section->raw_data_offset = grub_host_to_target32 (header_size);
 	text_section->characteristics = grub_cpu_to_le32_compile_time (
 						  GRUB_PE32_SCN_CNT_CODE
 						| GRUB_PE32_SCN_MEM_EXECUTE
@@ -1377,10 +1377,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 
 	data_section = text_section + 1;
 	strcpy (data_section->name, ".data");
-	data_section->virtual_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
-	data_section->virtual_address = grub_cpu_to_le32 (header_size + layout.exec_size);
-	data_section->raw_data_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
-	data_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.exec_size);
+	data_section->virtual_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
+	data_section->virtual_address = grub_host_to_target32 (header_size + layout.exec_size);
+	data_section->raw_data_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
+	data_section->raw_data_offset = grub_host_to_target32 (header_size + layout.exec_size);
 	data_section->characteristics
 	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
 			      | GRUB_PE32_SCN_MEM_READ
@@ -1388,10 +1388,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
     
 	mods_section = data_section + 1;
 	strcpy (mods_section->name, "mods");
-	mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
-	mods_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size + layout.bss_size);
-	mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
-	mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.kernel_size);
+	mods_section->virtual_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
+	mods_section->virtual_address = grub_host_to_target32 (header_size + layout.kernel_size + layout.bss_size);
+	mods_section->raw_data_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
+	mods_section->raw_data_offset = grub_host_to_target32 (header_size + layout.kernel_size);
 	mods_section->characteristics
 	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
 			      | GRUB_PE32_SCN_MEM_READ
@@ -1399,10 +1399,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 
 	reloc_section = mods_section + 1;
 	strcpy (reloc_section->name, ".reloc");
-	reloc_section->virtual_size = grub_cpu_to_le32 (layout.reloc_size);
-	reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + layout.bss_size);
-	reloc_section->raw_data_size = grub_cpu_to_le32 (layout.reloc_size);
-	reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
+	reloc_section->virtual_size = grub_host_to_target32 (layout.reloc_size);
+	reloc_section->virtual_address = grub_host_to_target32 (reloc_addr + layout.bss_size);
+	reloc_section->raw_data_size = grub_host_to_target32 (layout.reloc_size);
+	reloc_section->raw_data_offset = grub_host_to_target32 (reloc_addr);
 	reloc_section->characteristics
 	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
 			      | GRUB_PE32_SCN_MEM_DISCARDABLE
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 104/117] util/mkimage: Always use grub_host_to_target32() to initialize PE stack and heap stuff
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (102 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 103/117] util/mkimage: Use grub_host_to_target32() instead of grub_cpu_to_le32() Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 105/117] util/mkimage: Unify more of the PE32 and PE32+ header set-up Daniel Kiper
                   ` (14 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Peter Jones <pjones@redhat.com>

This change does not impact final result of initialization itself.
However, it eases PE code unification in subsequent patches.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/mkimage.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/util/mkimage.c b/util/mkimage.c
index 02944f28e..b94bfb781 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1351,10 +1351,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	    o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
 
 	    /* Do these really matter? */
-	    o->stack_reserve_size = grub_host_to_target64 (0x10000);
-	    o->stack_commit_size = grub_host_to_target64 (0x10000);
-	    o->heap_reserve_size = grub_host_to_target64 (0x10000);
-	    o->heap_commit_size = grub_host_to_target64 (0x10000);
+	    o->stack_reserve_size = grub_host_to_target32 (0x10000);
+	    o->stack_commit_size = grub_host_to_target32 (0x10000);
+	    o->heap_reserve_size = grub_host_to_target32 (0x10000);
+	    o->heap_commit_size = grub_host_to_target32 (0x10000);
     
 	    o->num_data_directories
 	      = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 105/117] util/mkimage: Unify more of the PE32 and PE32+ header set-up
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (103 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 104/117] util/mkimage: Always use grub_host_to_target32() to initialize PE stack and heap stuff Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 106/117] util/mkimage: Reorder PE optional header fields set-up Daniel Kiper
                   ` (13 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Peter Jones <pjones@redhat.com>

There's quite a bit of code duplication in the code that sets the optional
header for PE32 and PE32+. The two are very similar with the exception of
a few fields that have type grub_uint64_t instead of grub_uint32_t.

Factor out the common code and add a PE_OHDR() macro that simplifies the
set-up and make the code more readable.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/mkimage.c | 111 ++++++++++++++++++++++++++-------------------------------
 1 file changed, 51 insertions(+), 60 deletions(-)

diff --git a/util/mkimage.c b/util/mkimage.c
index b94bfb781..a039039db 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -816,6 +816,21 @@ grub_install_get_image_targets_string (void)
   return formats;
 }
 
+/*
+ * tmp_ is just here so the compiler knows we'll never derefernce a NULL.
+ * It should get fully optimized away.
+ */
+#define PE_OHDR(o32, o64, field) (*(		\
+{						\
+  __typeof__((o64)->field) tmp_;		\
+  __typeof__((o64)->field) *ret_ = &tmp_;	\
+  if (o32)					\
+    ret_ = (void *)(&((o32)->field));		\
+  else if (o64)				\
+    ret_ = (void *)(&((o64)->field));		\
+  ret_;					\
+}))
+
 void
 grub_install_generate_image (const char *dir, const char *prefix,
 			     FILE *out, const char *outname, char *mods[],
@@ -1252,6 +1267,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
 	int header_size;
 	int reloc_addr;
+	struct grub_pe32_optional_header *o32 = NULL;
+	struct grub_pe64_optional_header *o64 = NULL;
 
 	if (image_target->voidp_sizeof == 4)
 	  header_size = EFI32_HEADER_SIZE;
@@ -1293,76 +1310,50 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	/* The PE Optional header.  */
 	if (image_target->voidp_sizeof == 4)
 	  {
-	    struct grub_pe32_optional_header *o;
-
 	    c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe32_optional_header));
 
-	    o = (struct grub_pe32_optional_header *)
-	      (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
-	       + sizeof (struct grub_pe32_coff_header));
-	    o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
-	    o->code_size = grub_host_to_target32 (layout.exec_size);
-	    o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
-					     - header_size);
-	    o->entry_addr = grub_host_to_target32 (layout.start_address);
-	    o->code_base = grub_host_to_target32 (header_size);
+	    o32 = (struct grub_pe32_optional_header *)
+              (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE +
+               sizeof (struct grub_pe32_coff_header));
+	    o32->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
+	    o32->data_base = grub_host_to_target32 (header_size + layout.exec_size);
 
-	    o->data_base = grub_host_to_target32 (header_size + layout.exec_size);
-
-	    o->image_base = 0;
-	    o->section_alignment = grub_host_to_target32 (image_target->section_align);
-	    o->file_alignment = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
-	    o->image_size = grub_host_to_target32 (pe_size);
-	    o->header_size = grub_host_to_target32 (header_size);
-	    o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
-
-	    /* Do these really matter? */
-	    o->stack_reserve_size = grub_host_to_target32 (0x10000);
-	    o->stack_commit_size = grub_host_to_target32 (0x10000);
-	    o->heap_reserve_size = grub_host_to_target32 (0x10000);
-	    o->heap_commit_size = grub_host_to_target32 (0x10000);
-    
-	    o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
-
-	    o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
-	    o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
-	    sections = o + 1;
+	    sections = o32 + 1;
 	  }
 	else
 	  {
-	    struct grub_pe64_optional_header *o;
-
 	    c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
 
-	    o = (struct grub_pe64_optional_header *) 
-	      (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
-	       + sizeof (struct grub_pe32_coff_header));
-	    o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
-	    o->code_size = grub_host_to_target32 (layout.exec_size);
-	    o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
-					     - header_size);
-	    o->entry_addr = grub_host_to_target32 (layout.start_address);
-	    o->code_base = grub_host_to_target32 (header_size);
-	    o->image_base = 0;
-	    o->section_alignment = grub_host_to_target32 (image_target->section_align);
-	    o->file_alignment = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
-	    o->image_size = grub_host_to_target32 (pe_size);
-	    o->header_size = grub_host_to_target32 (header_size);
-	    o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
+	    o64 = (struct grub_pe64_optional_header *)
+		  (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE +
+                   sizeof (struct grub_pe32_coff_header));
+	    o64->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
 
-	    /* Do these really matter? */
-	    o->stack_reserve_size = grub_host_to_target32 (0x10000);
-	    o->stack_commit_size = grub_host_to_target32 (0x10000);
-	    o->heap_reserve_size = grub_host_to_target32 (0x10000);
-	    o->heap_commit_size = grub_host_to_target32 (0x10000);
-    
-	    o->num_data_directories
-	      = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
-
-	    o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
-	    o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
-	    sections = o + 1;
+	    sections = o64 + 1;
 	  }
+
+	PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
+	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+	PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address);
+	PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
+
+	PE_OHDR (o32, o64, image_base) = 0;
+	PE_OHDR (o32, o64, section_alignment) = grub_host_to_target32 (image_target->section_align);
+	PE_OHDR (o32, o64, file_alignment) = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
+	PE_OHDR (o32, o64, image_size) = grub_host_to_target32 (pe_size);
+	PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
+	PE_OHDR (o32, o64, subsystem) = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
+
+	/* Do these really matter? */
+	PE_OHDR (o32, o64, stack_reserve_size) = grub_host_to_target32 (0x10000);
+	PE_OHDR (o32, o64, stack_commit_size) = grub_host_to_target32 (0x10000);
+	PE_OHDR (o32, o64, heap_reserve_size) = grub_host_to_target32 (0x10000);
+	PE_OHDR (o32, o64, heap_commit_size) = grub_host_to_target32 (0x10000);
+
+	PE_OHDR (o32, o64, num_data_directories) = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
+	PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
+	PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
+
 	/* The sections.  */
 	text_section = sections;
 	strcpy (text_section->name, ".text");
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 106/117] util/mkimage: Reorder PE optional header fields set-up
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (104 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 105/117] util/mkimage: Unify more of the PE32 and PE32+ header set-up Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 107/117] util/mkimage: Improve data_size value calculation Daniel Kiper
                   ` (12 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Peter Jones <pjones@redhat.com>

This makes the PE32 and PE32+ header fields set-up easier to follow by
setting them closer to the initialization of their related sections.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/mkimage.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/util/mkimage.c b/util/mkimage.c
index a039039db..deaef5666 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1332,16 +1332,12 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	    sections = o64 + 1;
 	  }
 
-	PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
-	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+	PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
 	PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address);
-	PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
-
 	PE_OHDR (o32, o64, image_base) = 0;
+	PE_OHDR (o32, o64, image_size) = grub_host_to_target32 (pe_size);
 	PE_OHDR (o32, o64, section_alignment) = grub_host_to_target32 (image_target->section_align);
 	PE_OHDR (o32, o64, file_alignment) = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
-	PE_OHDR (o32, o64, image_size) = grub_host_to_target32 (pe_size);
-	PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
 	PE_OHDR (o32, o64, subsystem) = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
 
 	/* Do these really matter? */
@@ -1351,10 +1347,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	PE_OHDR (o32, o64, heap_commit_size) = grub_host_to_target32 (0x10000);
 
 	PE_OHDR (o32, o64, num_data_directories) = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
-	PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
-	PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
 
 	/* The sections.  */
+	PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
+	PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
 	text_section = sections;
 	strcpy (text_section->name, ".text");
 	text_section->virtual_size = grub_host_to_target32 (layout.exec_size);
@@ -1366,6 +1362,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
 						| GRUB_PE32_SCN_MEM_EXECUTE
 						| GRUB_PE32_SCN_MEM_READ);
 
+	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+
 	data_section = text_section + 1;
 	strcpy (data_section->name, ".data");
 	data_section->virtual_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
@@ -1388,6 +1386,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			      | GRUB_PE32_SCN_MEM_READ
 			      | GRUB_PE32_SCN_MEM_WRITE);
 
+	PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
+	PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
 	reloc_section = mods_section + 1;
 	strcpy (reloc_section->name, ".reloc");
 	reloc_section->virtual_size = grub_host_to_target32 (layout.reloc_size);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 107/117] util/mkimage: Improve data_size value calculation
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (105 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 106/117] util/mkimage: Reorder PE optional header fields set-up Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper Daniel Kiper
                   ` (11 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Peter Jones <pjones@redhat.com>

According to "Microsoft Portable Executable and Common Object File Format
Specification", the Optional Header SizeOfInitializedData field contains:

  Size of the initialized data section, or the sum of all such sections if
  there are multiple data sections.

Make this explicit by adding the GRUB kernel data size to the sum of all
the modules sizes. The ALIGN_UP() is not required by the PE spec but do
it to avoid alignment issues.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/mkimage.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/util/mkimage.c b/util/mkimage.c
index deaef5666..853a52179 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1260,6 +1260,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	void *pe_img;
 	grub_uint8_t *header;
 	void *sections;
+	size_t scn_size;
 	size_t pe_size;
 	struct grub_pe32_coff_header *c;
 	struct grub_pe32_section_table *text_section, *data_section;
@@ -1362,7 +1363,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 						| GRUB_PE32_SCN_MEM_EXECUTE
 						| GRUB_PE32_SCN_MEM_READ);
 
-	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+	scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
+	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size +
+							       ALIGN_UP (total_module_size,
+									 GRUB_PE32_FILE_ALIGNMENT));
 
 	data_section = text_section + 1;
 	strcpy (data_section->name, ".data");
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (106 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 107/117] util/mkimage: Improve data_size value calculation Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-18  8:38   ` John Paul Adrian Glaubitz
  2021-03-02 18:01 ` [SECURITY PATCH 109/117] util/mkimage: Add an option to import SBAT metadata into a .sbat section Daniel Kiper
                   ` (10 subsequent siblings)
  118 siblings, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Peter Jones <pjones@redhat.com>

Add a init_pe_section() helper function to setup PE sections. This makes
the code simpler and easier to read.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 util/mkimage.c | 141 +++++++++++++++++++++++++++++++--------------------------
 1 file changed, 76 insertions(+), 65 deletions(-)

diff --git a/util/mkimage.c b/util/mkimage.c
index 853a52179..8b475a691 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -817,6 +817,38 @@ grub_install_get_image_targets_string (void)
 }
 
 /*
+ * The image_target parameter is used by the grub_host_to_target32() macro.
+ */
+static struct grub_pe32_section_table *
+init_pe_section(const struct grub_install_image_target_desc *image_target,
+		struct grub_pe32_section_table *section,
+		const char * const name,
+		grub_uint32_t *vma, grub_uint32_t vsz, grub_uint32_t valign,
+		grub_uint32_t *rda, grub_uint32_t rsz,
+		grub_uint32_t characteristics)
+{
+  size_t len = strlen (name);
+
+  if (len > sizeof (section->name))
+    grub_util_error (_("section name %s length is bigger than %lu"),
+		     name, (unsigned long) sizeof (section->name));
+
+  memcpy (section->name, name, len);
+
+  section->virtual_address = grub_host_to_target32 (*vma);
+  section->virtual_size = grub_host_to_target32 (vsz);
+  (*vma) = ALIGN_UP (*vma + vsz, valign);
+
+  section->raw_data_offset = grub_host_to_target32 (*rda);
+  section->raw_data_size = grub_host_to_target32 (rsz);
+  (*rda) = ALIGN_UP (*rda + rsz, GRUB_PE32_FILE_ALIGNMENT);
+
+  section->characteristics = grub_host_to_target32 (characteristics);
+
+  return section + 1;
+}
+
+/*
  * tmp_ is just here so the compiler knows we'll never derefernce a NULL.
  * It should get fully optimized away.
  */
@@ -1257,17 +1289,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
       break;
     case IMAGE_EFI:
       {
-	void *pe_img;
-	grub_uint8_t *header;
-	void *sections;
+	char *pe_img, *header;
+	struct grub_pe32_section_table *section;
 	size_t scn_size;
-	size_t pe_size;
+	grub_uint32_t vma, raw_data;
+	size_t pe_size, header_size;
 	struct grub_pe32_coff_header *c;
-	struct grub_pe32_section_table *text_section, *data_section;
-	struct grub_pe32_section_table *mods_section, *reloc_section;
 	static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
-	int header_size;
-	int reloc_addr;
 	struct grub_pe32_optional_header *o32 = NULL;
 	struct grub_pe64_optional_header *o64 = NULL;
 
@@ -1276,17 +1304,12 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	else
 	  header_size = EFI64_HEADER_SIZE;
 
-	reloc_addr = ALIGN_UP (header_size + core_size,
-			       GRUB_PE32_FILE_ALIGNMENT);
+	vma = raw_data = header_size;
+	pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) +
+          ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT);
+	header = pe_img = xcalloc (1, pe_size);
 
-	pe_size = ALIGN_UP (reloc_addr + layout.reloc_size,
-			    GRUB_PE32_FILE_ALIGNMENT);
-	pe_img = xmalloc (reloc_addr + layout.reloc_size);
-	memset (pe_img, 0, header_size);
-	memcpy ((char *) pe_img + header_size, core_img, core_size);
-	memset ((char *) pe_img + header_size + core_size, 0, reloc_addr - (header_size + core_size));
-	memcpy ((char *) pe_img + reloc_addr, layout.reloc_section, layout.reloc_size);
-	header = pe_img;
+	memcpy (pe_img + raw_data, core_img, core_size);
 
 	/* The magic.  */
 	memcpy (header, stub, GRUB_PE32_MSDOS_STUB_SIZE);
@@ -1319,18 +1342,17 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	    o32->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
 	    o32->data_base = grub_host_to_target32 (header_size + layout.exec_size);
 
-	    sections = o32 + 1;
+	    section = (struct grub_pe32_section_table *)(o32 + 1);
 	  }
 	else
 	  {
 	    c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
-
 	    o64 = (struct grub_pe64_optional_header *)
 		  (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE +
                    sizeof (struct grub_pe32_coff_header));
 	    o64->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
 
-	    sections = o64 + 1;
+	    section = (struct grub_pe32_section_table *)(o64 + 1);
 	  }
 
 	PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
@@ -1350,58 +1372,47 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	PE_OHDR (o32, o64, num_data_directories) = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
 
 	/* The sections.  */
-	PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
+	PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (vma);
 	PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
-	text_section = sections;
-	strcpy (text_section->name, ".text");
-	text_section->virtual_size = grub_host_to_target32 (layout.exec_size);
-	text_section->virtual_address = grub_host_to_target32 (header_size);
-	text_section->raw_data_size = grub_host_to_target32 (layout.exec_size);
-	text_section->raw_data_offset = grub_host_to_target32 (header_size);
-	text_section->characteristics = grub_cpu_to_le32_compile_time (
-						  GRUB_PE32_SCN_CNT_CODE
-						| GRUB_PE32_SCN_MEM_EXECUTE
-						| GRUB_PE32_SCN_MEM_READ);
+	section = init_pe_section (image_target, section, ".text",
+				   &vma, layout.exec_size,
+				   image_target->section_align,
+				   &raw_data, layout.exec_size,
+				   GRUB_PE32_SCN_CNT_CODE |
+				   GRUB_PE32_SCN_MEM_EXECUTE |
+				   GRUB_PE32_SCN_MEM_READ);
 
 	scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
 	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size +
 							       ALIGN_UP (total_module_size,
 									 GRUB_PE32_FILE_ALIGNMENT));
 
-	data_section = text_section + 1;
-	strcpy (data_section->name, ".data");
-	data_section->virtual_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
-	data_section->virtual_address = grub_host_to_target32 (header_size + layout.exec_size);
-	data_section->raw_data_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
-	data_section->raw_data_offset = grub_host_to_target32 (header_size + layout.exec_size);
-	data_section->characteristics
-	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
-			      | GRUB_PE32_SCN_MEM_READ
-			      | GRUB_PE32_SCN_MEM_WRITE);
-    
-	mods_section = data_section + 1;
-	strcpy (mods_section->name, "mods");
-	mods_section->virtual_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
-	mods_section->virtual_address = grub_host_to_target32 (header_size + layout.kernel_size + layout.bss_size);
-	mods_section->raw_data_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
-	mods_section->raw_data_offset = grub_host_to_target32 (header_size + layout.kernel_size);
-	mods_section->characteristics
-	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
-			      | GRUB_PE32_SCN_MEM_READ
-			      | GRUB_PE32_SCN_MEM_WRITE);
+	section = init_pe_section (image_target, section, ".data",
+				   &vma, scn_size, image_target->section_align,
+				   &raw_data, scn_size,
+				   GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+				   GRUB_PE32_SCN_MEM_READ |
+				   GRUB_PE32_SCN_MEM_WRITE);
+
+	scn_size = pe_size - layout.reloc_size - raw_data;
+	section = init_pe_section (image_target, section, "mods",
+				   &vma, scn_size, image_target->section_align,
+				   &raw_data, scn_size,
+				   GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+				   GRUB_PE32_SCN_MEM_READ |
+				   GRUB_PE32_SCN_MEM_WRITE);
+
+	scn_size = layout.reloc_size;
+	PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma);
+	PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size);
+	memcpy (pe_img + raw_data, layout.reloc_section, scn_size);
+	init_pe_section (image_target, section, ".reloc",
+			 &vma, scn_size, image_target->section_align,
+			 &raw_data, scn_size,
+			 GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+			 GRUB_PE32_SCN_MEM_DISCARDABLE |
+			 GRUB_PE32_SCN_MEM_READ);
 
-	PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
-	PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
-	reloc_section = mods_section + 1;
-	strcpy (reloc_section->name, ".reloc");
-	reloc_section->virtual_size = grub_host_to_target32 (layout.reloc_size);
-	reloc_section->virtual_address = grub_host_to_target32 (reloc_addr + layout.bss_size);
-	reloc_section->raw_data_size = grub_host_to_target32 (layout.reloc_size);
-	reloc_section->raw_data_offset = grub_host_to_target32 (reloc_addr);
-	reloc_section->characteristics
-	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
-			      | GRUB_PE32_SCN_MEM_DISCARDABLE
-			      | GRUB_PE32_SCN_MEM_READ);
 	free (core_img);
 	core_img = pe_img;
 	core_size = pe_size;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 109/117] util/mkimage: Add an option to import SBAT metadata into a .sbat section
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (107 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 110/117] grub-install-common: Add --sbat option Daniel Kiper
                   ` (9 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Peter Jones <pjones@redhat.com>

Add a --sbat option to the grub-mkimage tool which allows us to import
an SBAT metadata formatted as a CSV file into a .sbat section of the
EFI binary.

Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi              | 19 +++++++++++++++++++
 include/grub/util/install.h |  3 ++-
 include/grub/util/mkimage.h |  1 +
 util/grub-install-common.c  |  2 +-
 util/grub-mkimage.c         | 15 ++++++++++++++-
 util/mkimage.c              | 43 ++++++++++++++++++++++++++++++++++++-------
 6 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index c5fc3904f..81b90947a 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5784,6 +5784,7 @@ environment variables and commands are listed in the same order.
 * Authentication and authorisation:: Users and access control
 * Using digital signatures::         Booting digitally signed code
 * UEFI secure boot and shim::        Booting digitally signed PE files
+* Secure Boot Advanced Targeting::   Embedded information for generation number based revocation
 * Measured Boot::                    Measuring boot components
 * Lockdown::                         Lockdown when booting on a secure setup
 @end menu
@@ -5958,6 +5959,24 @@ and @command{memrw} will not be available when the UEFI secure boot is enabled.
 This is done for security reasons and are enforced by the GRUB Lockdown mechanism
 (@pxref{Lockdown}).
 
+@node Secure Boot Advanced Targeting
+@section Embedded information for generation number based revocation
+
+The Secure Boot Advanced Targeting (SBAT) is a mechanism to allow the revocation
+of components in the boot path by using generation numbers embedded into the EFI
+binaries. The SBAT metadata is located in an .sbat data section that has set of
+UTF-8 strings as comma-separated values (CSV). See
+@uref{https://github.com/rhboot/shim/blob/main/SBAT.md} for more details.
+
+To add a data section containing the SBAT information into the binary, the
+@option{--sbat} option of @command{grub-mkimage} command should be used. The content
+of a CSV file, encoded with UTF-8, is copied as is to the .sbat data section into
+the generated EFI binary. The CSV file can be stored anywhere on the file system.
+
+@example
+grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efinet tftp
+@end example
+
 @node Measured Boot
 @section Measuring boot components
 
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 8cbbc4139..3736a16aa 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -183,7 +183,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     char *config_path,
 			     const struct grub_install_image_target_desc *image_target,
 			     int note,
-			     grub_compression_t comp, const char *dtb_file);
+			     grub_compression_t comp, const char *dtb_file,
+			     const char *sbat_path);
 
 const struct grub_install_image_target_desc *
 grub_install_get_image_target (const char *arg);
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index ba9f568f6..3819a6744 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -24,6 +24,7 @@ struct grub_mkimage_layout
   size_t exec_size;
   size_t kernel_size;
   size_t bss_size;
+  size_t sbat_size;
   grub_uint64_t start_address;
   void *reloc_section;
   size_t reloc_size;
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 08d3eb668..56dcb52bf 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -536,7 +536,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_install_generate_image (dir, prefix, fp, outname,
 			       modules.entries, memdisk_path,
 			       pubkeys, npubkeys, config_path, tgt,
-			       note, compression, dtb);
+			       note, compression, dtb, NULL);
   while (dc--)
     grub_install_pop_module ();
 }
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index 912564e36..75b884710 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -81,6 +81,7 @@ static struct argp_option options[] = {
   {"output",  'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0},
   {"format",  'O', N_("FORMAT"), 0, 0, 0},
   {"compression",  'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
+  {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
   { 0, 0, 0, 0, 0, 0 }
 };
@@ -123,6 +124,7 @@ struct arguments
   size_t npubkeys;
   char *font;
   char *config;
+  char *sbat;
   int note;
   const struct grub_install_image_target_desc *image_target;
   grub_compression_t comp;
@@ -224,6 +226,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
       arguments->prefix = xstrdup (arg);
       break;
 
+    case 's':
+      if (arguments->sbat)
+	free (arguments->sbat);
+
+      arguments->sbat = xstrdup (arg);
+      break;
+
     case 'v':
       verbosity++;
       break;
@@ -309,7 +318,8 @@ main (int argc, char *argv[])
 			       arguments.memdisk, arguments.pubkeys,
 			       arguments.npubkeys, arguments.config,
 			       arguments.image_target, arguments.note,
-			       arguments.comp, arguments.dtb);
+			       arguments.comp, arguments.dtb,
+			       arguments.sbat);
 
   if (grub_util_file_sync (fp) < 0)
     grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
@@ -328,5 +338,8 @@ main (int argc, char *argv[])
   if (arguments.output)
     free (arguments.output);
 
+  if (arguments.sbat)
+    free (arguments.sbat);
+
   return 0;
 }
diff --git a/util/mkimage.c b/util/mkimage.c
index 8b475a691..b354ec1d9 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -869,12 +869,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     char *memdisk_path, char **pubkey_paths,
 			     size_t npubkeys, char *config_path,
 			     const struct grub_install_image_target_desc *image_target,
-			     int note, grub_compression_t comp, const char *dtb_path)
+			     int note, grub_compression_t comp, const char *dtb_path,
+			     const char *sbat_path)
 {
   char *kernel_img, *core_img;
   size_t total_module_size, core_size;
   size_t memdisk_size = 0, config_size = 0;
-  size_t prefix_size = 0, dtb_size = 0;
+  size_t prefix_size = 0, dtb_size = 0, sbat_size = 0;
   char *kernel_path;
   size_t offset;
   struct grub_util_path_list *path_list, *p;
@@ -925,6 +926,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
       total_module_size += dtb_size + sizeof (struct grub_module_header);
     }
 
+  if (sbat_path != NULL && image_target->id != IMAGE_EFI)
+    grub_util_error (_(".sbat section can be embedded into EFI images only"));
+
   if (config_path)
     {
       config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@@ -1289,8 +1293,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
       break;
     case IMAGE_EFI:
       {
-	char *pe_img, *header;
+	char *pe_img, *pe_sbat, *header;
 	struct grub_pe32_section_table *section;
+	size_t n_sections = 4;
 	size_t scn_size;
 	grub_uint32_t vma, raw_data;
 	size_t pe_size, header_size;
@@ -1305,8 +1310,15 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	  header_size = EFI64_HEADER_SIZE;
 
 	vma = raw_data = header_size;
+
+	if (sbat_path != NULL)
+	  {
+	    sbat_size = ALIGN_ADDR (grub_util_get_image_size (sbat_path));
+	    sbat_size = ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT);
+	  }
+
 	pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) +
-          ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT);
+          ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT) + sbat_size;
 	header = pe_img = xcalloc (1, pe_size);
 
 	memcpy (pe_img + raw_data, core_img, core_size);
@@ -1321,7 +1333,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 					      + GRUB_PE32_SIGNATURE_SIZE);
 	c->machine = grub_host_to_target16 (image_target->pe_target);
 
-	c->num_sections = grub_host_to_target16 (4);
+	if (sbat_path != NULL)
+	  n_sections++;
+
+	c->num_sections = grub_host_to_target16 (n_sections);
 	c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP);
 	c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
 						    | GRUB_PE32_LINE_NUMS_STRIPPED
@@ -1383,7 +1398,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
 				   GRUB_PE32_SCN_MEM_READ);
 
 	scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
-	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size +
+	/* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */
+	PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size +
 							       ALIGN_UP (total_module_size,
 									 GRUB_PE32_FILE_ALIGNMENT));
 
@@ -1394,7 +1410,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 				   GRUB_PE32_SCN_MEM_READ |
 				   GRUB_PE32_SCN_MEM_WRITE);
 
-	scn_size = pe_size - layout.reloc_size - raw_data;
+	scn_size = pe_size - layout.reloc_size - sbat_size - raw_data;
 	section = init_pe_section (image_target, section, "mods",
 				   &vma, scn_size, image_target->section_align,
 				   &raw_data, scn_size,
@@ -1402,6 +1418,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
 				   GRUB_PE32_SCN_MEM_READ |
 				   GRUB_PE32_SCN_MEM_WRITE);
 
+	if (sbat_path != NULL)
+	  {
+	    pe_sbat = pe_img + raw_data;
+	    grub_util_load_image (sbat_path, pe_sbat);
+
+	    section = init_pe_section (image_target, section, ".sbat",
+				       &vma, sbat_size,
+				       image_target->section_align,
+				       &raw_data, sbat_size,
+				       GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+				       GRUB_PE32_SCN_MEM_READ);
+	  }
+
 	scn_size = layout.reloc_size;
 	PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma);
 	PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 110/117] grub-install-common: Add --sbat option
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (108 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 109/117] util/mkimage: Add an option to import SBAT metadata into a .sbat section Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 111/117] shim_lock: Only skip loading shim_lock verifier with explicit consent Daniel Kiper
                   ` (8 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Dimitri John Ledkov <xnox@ubuntu.com>

Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 include/grub/util/install.h |  5 ++++-
 util/grub-install-common.c  | 12 ++++++++++--
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 3736a16aa..c14985858 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -63,6 +63,8 @@
     /* TRANSLATORS: "embed" is a verb (command description).  "*/	\
   { "pubkey",   'k', N_("FILE"), 0,					\
       N_("embed FILE as public key for signature checking"), 0},	\
+  { "sbat", GRUB_INSTALL_OPTIONS_SBAT, N_("FILE"), 0,			\
+      N_("SBAT metadata"), 0 },						\
   { "verbose", 'v', 0, 0,						\
     N_("print verbose messages."), 1 }
 
@@ -122,7 +124,8 @@ enum grub_install_options {
   GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY,
   GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
   GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
-  GRUB_INSTALL_OPTIONS_DTB
+  GRUB_INSTALL_OPTIONS_DTB,
+  GRUB_INSTALL_OPTIONS_SBAT
 };
 
 extern char *grub_install_source_directory;
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 56dcb52bf..89af26c26 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -332,6 +332,7 @@ handle_install_list (struct install_list *il, const char *val,
 
 static char **pubkeys;
 static size_t npubkeys;
+static char *sbat;
 static grub_compression_t compression;
 
 int
@@ -362,6 +363,12 @@ grub_install_parse (int key, char *arg)
 			  * (npubkeys + 1));
       pubkeys[npubkeys++] = xstrdup (arg);
       return 1;
+    case GRUB_INSTALL_OPTIONS_SBAT:
+      if (sbat)
+	free (sbat);
+
+      sbat = xstrdup (arg);
+      return 1;
 
     case GRUB_INSTALL_OPTIONS_VERBOSITY:
       verbosity++;
@@ -523,9 +530,10 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'"
 		  " --output '%s' "
 		  " --dtb '%s' "
+		  "--sbat '%s' "
 		  "--format '%s' --compression '%s' %s %s\n",
 		  dir, prefix,
-		  outname, dtb ? : "", mkimage_target,
+		  outname, dtb ? : "", sbat ? : "", mkimage_target,
 		  compnames[compression], note ? "--note" : "", s);
   free (s);
 
@@ -536,7 +544,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_install_generate_image (dir, prefix, fp, outname,
 			       modules.entries, memdisk_path,
 			       pubkeys, npubkeys, config_path, tgt,
-			       note, compression, dtb, NULL);
+			       note, compression, dtb, sbat);
   while (dc--)
     grub_install_pop_module ();
 }
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 111/117] shim_lock: Only skip loading shim_lock verifier with explicit consent
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (109 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 110/117] grub-install-common: Add --sbat option Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:01 ` [SECURITY PATCH 112/117] kern/misc: Split parse_printf_args() into format parsing and va_list handling Daniel Kiper
                   ` (7 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Dimitri John Ledkov <xnox@ubuntu.com>

Commit 32ddc42c (efi: Only register shim_lock verifier if shim_lock
protocol is found and SB enabled) reintroduced CVE-2020-15705 which
previously only existed in the out-of-tree linuxefi patches and was
fixed as part of the BootHole patch series.

Under Secure Boot enforce loading shim_lock verifier. Allow skipping
shim_lock verifier if SecureBoot/MokSBState EFI variables indicate
skipping validations, or if GRUB image is built with --disable-shim-lock.

Fixes: 132ddc42c (efi: Only register shim_lock verifier if shim_lock
       protocol is found and SB enabled)
Fixes: CVE-2020-15705
Fixes: CVE-2021-3418

Reported-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi              |  5 ++++-
 grub-core/kern/efi/sb.c     | 17 ++++++++++++++++-
 include/grub/kernel.h       |  3 ++-
 include/grub/util/install.h |  7 +++++--
 util/grub-install-common.c  | 12 +++++++++---
 util/grub-mkimage.c         |  8 +++++++-
 util/mkimage.c              | 15 ++++++++++++++-
 7 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 81b90947a..2f2ae2228 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5950,7 +5950,10 @@ secure boot chain.
 The GRUB, except the @command{chainloader} command, works with the UEFI secure
 boot and the shim. This functionality is provided by the shim_lock verifier. It
 is built into the @file{core.img} and is registered if the UEFI secure boot is
-enabled.
+enabled. The @samp{shim_lock} variable is set to @samp{y} when shim_lock verifier
+is registered. If it is desired to use UEFI secure boot without shim, one can
+disable shim_lock by disabling shim verification with MokSbState UEFI variable
+or by building grub image with @samp{--disable-shim-lock} option.
 
 All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables,
 Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 5d7210a82..41dadcd14 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -21,9 +21,11 @@
 #include <grub/efi/efi.h>
 #include <grub/efi/pe32.h>
 #include <grub/efi/sb.h>
+#include <grub/env.h>
 #include <grub/err.h>
 #include <grub/file.h>
 #include <grub/i386/linux.h>
+#include <grub/kernel.h>
 #include <grub/mm.h>
 #include <grub/types.h>
 #include <grub/verify.h>
@@ -160,14 +162,27 @@ struct grub_file_verifier shim_lock_verifier =
 void
 grub_shim_lock_verifier_setup (void)
 {
+  struct grub_module_header *header;
   grub_efi_shim_lock_protocol_t *sl =
     grub_efi_locate_protocol (&shim_lock_guid, 0);
 
+  /* shim_lock is missing, check if GRUB image is built with --disable-shim-lock. */
   if (!sl)
-    return;
+    {
+      FOR_MODULES (header)
+	{
+	  if (header->type == OBJ_TYPE_DISABLE_SHIM_LOCK)
+	    return;
+	}
+    }
 
+  /* Secure Boot is off. Do not load shim_lock. */
   if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
     return;
 
+  /* Enforce shim_lock_verifier. */
   grub_verifier_register (&shim_lock_verifier);
+
+  grub_env_set ("shim_lock", "y");
+  grub_env_export ("shim_lock");
 }
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index 133a37c8d..abbca5ea3 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -29,7 +29,8 @@ enum
   OBJ_TYPE_CONFIG,
   OBJ_TYPE_PREFIX,
   OBJ_TYPE_PUBKEY,
-  OBJ_TYPE_DTB
+  OBJ_TYPE_DTB,
+  OBJ_TYPE_DISABLE_SHIM_LOCK
 };
 
 /* The module header.  */
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index c14985858..b93c73caa 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -65,6 +65,8 @@
       N_("embed FILE as public key for signature checking"), 0},	\
   { "sbat", GRUB_INSTALL_OPTIONS_SBAT, N_("FILE"), 0,			\
       N_("SBAT metadata"), 0 },						\
+  { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0,	\
+      N_("disable shim_lock verifier"), 0 },				\
   { "verbose", 'v', 0, 0,						\
     N_("print verbose messages."), 1 }
 
@@ -125,7 +127,8 @@ enum grub_install_options {
   GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
   GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
   GRUB_INSTALL_OPTIONS_DTB,
-  GRUB_INSTALL_OPTIONS_SBAT
+  GRUB_INSTALL_OPTIONS_SBAT,
+  GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK
 };
 
 extern char *grub_install_source_directory;
@@ -187,7 +190,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     const struct grub_install_image_target_desc *image_target,
 			     int note,
 			     grub_compression_t comp, const char *dtb_file,
-			     const char *sbat_path);
+			     const char *sbat_path, const int disable_shim_lock);
 
 const struct grub_install_image_target_desc *
 grub_install_get_image_target (const char *arg);
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 89af26c26..b4f28840f 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -333,6 +333,7 @@ handle_install_list (struct install_list *il, const char *val,
 static char **pubkeys;
 static size_t npubkeys;
 static char *sbat;
+static int disable_shim_lock;
 static grub_compression_t compression;
 
 int
@@ -369,6 +370,9 @@ grub_install_parse (int key, char *arg)
 
       sbat = xstrdup (arg);
       return 1;
+    case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
+      disable_shim_lock = 1;
+      return 1;
 
     case GRUB_INSTALL_OPTIONS_VERBOSITY:
       verbosity++;
@@ -531,10 +535,11 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
 		  " --output '%s' "
 		  " --dtb '%s' "
 		  "--sbat '%s' "
-		  "--format '%s' --compression '%s' %s %s\n",
+		  "--format '%s' --compression '%s' %s %s %s\n",
 		  dir, prefix,
 		  outname, dtb ? : "", sbat ? : "", mkimage_target,
-		  compnames[compression], note ? "--note" : "", s);
+		  compnames[compression], note ? "--note" : "",
+		  disable_shim_lock ? "--disable-shim-lock" : "", s);
   free (s);
 
   tgt = grub_install_get_image_target (mkimage_target);
@@ -544,7 +549,8 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_install_generate_image (dir, prefix, fp, outname,
 			       modules.entries, memdisk_path,
 			       pubkeys, npubkeys, config_path, tgt,
-			       note, compression, dtb, sbat);
+			       note, compression, dtb, sbat,
+			       disable_shim_lock);
   while (dc--)
     grub_install_pop_module ();
 }
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index 75b884710..c0d559937 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -82,6 +82,7 @@ static struct argp_option options[] = {
   {"format",  'O', N_("FORMAT"), 0, 0, 0},
   {"compression",  'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
   {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
+  {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
   { 0, 0, 0, 0, 0, 0 }
 };
@@ -126,6 +127,7 @@ struct arguments
   char *config;
   char *sbat;
   int note;
+  int disable_shim_lock;
   const struct grub_install_image_target_desc *image_target;
   grub_compression_t comp;
 };
@@ -233,6 +235,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
       arguments->sbat = xstrdup (arg);
       break;
 
+    case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
+      arguments->disable_shim_lock = 1;
+      break;
+
     case 'v':
       verbosity++;
       break;
@@ -319,7 +325,7 @@ main (int argc, char *argv[])
 			       arguments.npubkeys, arguments.config,
 			       arguments.image_target, arguments.note,
 			       arguments.comp, arguments.dtb,
-			       arguments.sbat);
+			       arguments.sbat, arguments.disable_shim_lock);
 
   if (grub_util_file_sync (fp) < 0)
     grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
diff --git a/util/mkimage.c b/util/mkimage.c
index b354ec1d9..a26cf76f7 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -870,7 +870,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     size_t npubkeys, char *config_path,
 			     const struct grub_install_image_target_desc *image_target,
 			     int note, grub_compression_t comp, const char *dtb_path,
-			     const char *sbat_path)
+			     const char *sbat_path, int disable_shim_lock)
 {
   char *kernel_img, *core_img;
   size_t total_module_size, core_size;
@@ -929,6 +929,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
   if (sbat_path != NULL && image_target->id != IMAGE_EFI)
     grub_util_error (_(".sbat section can be embedded into EFI images only"));
 
+  if (disable_shim_lock)
+    total_module_size += sizeof (struct grub_module_header);
+
   if (config_path)
     {
       config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@@ -1065,6 +1068,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
       offset += dtb_size;
     }
 
+  if (disable_shim_lock)
+    {
+      struct grub_module_header *header;
+
+      header = (struct grub_module_header *) (kernel_img + offset);
+      header->type = grub_host_to_target32 (OBJ_TYPE_DISABLE_SHIM_LOCK);
+      header->size = grub_host_to_target32 (sizeof (*header));
+      offset += sizeof (*header);
+    }
+
   if (config_path)
     {
       struct grub_module_header *header;
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 112/117] kern/misc: Split parse_printf_args() into format parsing and va_list handling
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (110 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 111/117] shim_lock: Only skip loading shim_lock verifier with explicit consent Daniel Kiper
@ 2021-03-02 18:01 ` Daniel Kiper
  2021-03-02 18:02 ` [SECURITY PATCH 113/117] kern/misc: Add STRING type for internal printf() format handling Daniel Kiper
                   ` (6 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:01 UTC (permalink / raw)
  To: grub-devel

From: Thomas Frauendorfer | Miray Software <tf@miray.de>

This patch is preparing for a follow up patch which will use
the format parsing part to compare the arguments in a printf()
format from an external source against a printf() format with
expected arguments.

Signed-off-by: Thomas Frauendorfer | Miray Software <tf@miray.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/misc.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 430e72340..c58857ca2 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -645,8 +645,7 @@ grub_lltoa (char *str, int c, unsigned long long n)
 }
 
 static void
-parse_printf_args (const char *fmt0, struct printf_args *args,
-		   va_list args_in)
+parse_printf_arg_fmt (const char *fmt0, struct printf_args *args)
 {
   const char *fmt;
   char c;
@@ -804,6 +803,14 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
 	  break;
 	}
     }
+}
+
+static void
+parse_printf_args (const char *fmt0, struct printf_args *args, va_list args_in)
+{
+  grub_size_t n;
+
+  parse_printf_arg_fmt (fmt0, args);
 
   for (n = 0; n < args->count; n++)
     switch (args->ptr[n].type)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 113/117] kern/misc: Add STRING type for internal printf() format handling
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (111 preceding siblings ...)
  2021-03-02 18:01 ` [SECURITY PATCH 112/117] kern/misc: Split parse_printf_args() into format parsing and va_list handling Daniel Kiper
@ 2021-03-02 18:02 ` Daniel Kiper
  2021-03-02 18:02 ` [SECURITY PATCH 114/117] kern/misc: Add function to check printf() format against expected format Daniel Kiper
                   ` (5 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:02 UTC (permalink / raw)
  To: grub-devel

From: Thomas Frauendorfer | Miray Software <tf@miray.de>

Set printf() argument type for "%s" to new type STRING. This is in
preparation for a follow up patch to compare a printf() format string
against an expected printf() format string.

For "%s" the corresponding printf() argument is dereferenced as pointer
while all other argument types are defined as integer value. However,
when validating a printf() format it is necessary to differentiate "%s"
from "%p" and other integers. So, let's do that.

Signed-off-by: Thomas Frauendorfer | Miray Software <tf@miray.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/misc.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index c58857ca2..074728b2b 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -33,7 +33,8 @@ union printf_arg
   enum
     {
       INT, LONG, LONGLONG,
-      UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG
+      UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG,
+      STRING
     } type;
   long long ll;
 };
@@ -791,12 +792,14 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args)
 	  args->ptr[curn].type = INT + longfmt;
 	  break;
 	case 'p':
-	case 's':
 	  if (sizeof (void *) == sizeof (long long))
 	    args->ptr[curn].type = UNSIGNED_LONGLONG;
 	  else
 	    args->ptr[curn].type = UNSIGNED_INT;
 	  break;
+	case 's':
+	  args->ptr[curn].type = STRING;
+	  break;
 	case 'C':
 	case 'c':
 	  args->ptr[curn].type = INT;
@@ -831,6 +834,12 @@ parse_printf_args (const char *fmt0, struct printf_args *args, va_list args_in)
       case UNSIGNED_LONGLONG:
 	args->ptr[n].ll = va_arg (args_in, long long);
 	break;
+      case STRING:
+	if (sizeof (void *) == sizeof (long long))
+	  args->ptr[n].ll = va_arg (args_in, long long);
+	else
+	  args->ptr[n].ll = va_arg (args_in, unsigned int);
+	break;
       }
 }
 
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 114/117] kern/misc: Add function to check printf() format against expected format
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (112 preceding siblings ...)
  2021-03-02 18:02 ` [SECURITY PATCH 113/117] kern/misc: Add STRING type for internal printf() format handling Daniel Kiper
@ 2021-03-02 18:02 ` Daniel Kiper
  2021-03-18  1:30   ` Colin Watson
  2021-03-02 18:02 ` [SECURITY PATCH 115/117] gfxmenu/gui: Check printf() format in the gui_progress_bar and gui_label Daniel Kiper
                   ` (4 subsequent siblings)
  118 siblings, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:02 UTC (permalink / raw)
  To: grub-devel

From: Thomas Frauendorfer | Miray Software <tf@miray.de>

The grub_printf_fmt_check() function parses the arguments of an untrusted
printf() format and an expected printf() format and then compares the
arguments counts and arguments types. The arguments count in the untrusted
format string must be less or equal to the arguments count in the expected
format string and both arguments types must match.

To do this the parse_printf_arg_fmt() helper function is extended in the
following way:

  1. Add a return value to report errors to the grub_printf_fmt_check().

  2. Add the fmt_check argument to enable stricter format verification:
     - the function expects that arguments definitions are always
       terminated by a supported conversion specifier.
     - positional parameters, "$", are not allowed, as they cannot be
       validated correctly with the current implementation. For example
       "%s%1$d" would assign the first args entry twice while leaving the
       second one unchanged.
     - Return an error if preallocated space in args is too small and
       allocation fails for the needed size. The grub_printf_fmt_check()
       should verify all arguments. So, if validation is not possible for
       any reason it should return an error.
     This also adds a case entry to handle "%%", which is the escape
     sequence to print "%" character.

  3. Add the max_args argument to check for the maximum allowed arguments
     count in a printf() string. This should be set to the arguments count
     of the expected format. Then the parse_printf_arg_fmt() function will
     return an error if the arguments count is exceeded.

The two additional arguments allow us to use parse_printf_arg_fmt() in
printf() and grub_printf_fmt_check() calls.

When parse_printf_arg_fmt() is used by grub_printf_fmt_check() the
function parse user provided untrusted format string too. So, in
that case it is better to be too strict than too lenient.

Signed-off-by: Thomas Frauendorfer | Miray Software <tf@miray.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/misc.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++---
 include/grub/misc.h   | 16 ++++++++++
 2 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
index 074728b2b..3af336ee2 100644
--- a/grub-core/kern/misc.c
+++ b/grub-core/kern/misc.c
@@ -645,8 +645,26 @@ grub_lltoa (char *str, int c, unsigned long long n)
   return p;
 }
 
-static void
-parse_printf_arg_fmt (const char *fmt0, struct printf_args *args)
+/*
+ * Parse printf() fmt0 string into args arguments.
+ *
+ * The parsed arguments are either used by a printf() function to format the fmt0
+ * string or they are used to compare a format string from an untrusted source
+ * against a format string with expected arguments.
+ *
+ * When the fmt_check is set to !0, e.g. 1, then this function is executed in
+ * printf() format check mode. This enforces stricter rules for parsing the
+ * fmt0 to limit exposure to possible errors in printf() handling. It also
+ * disables positional parameters, "$", because some formats, e.g "%s%1$d",
+ * cannot be validated with the current implementation.
+ *
+ * The max_args allows to set a maximum number of accepted arguments. If the fmt0
+ * string defines more arguments than the max_args then the parse_printf_arg_fmt()
+ * function returns an error. This is currently used for format check only.
+ */
+static grub_err_t
+parse_printf_arg_fmt (const char *fmt0, struct printf_args *args,
+		      int fmt_check, grub_size_t max_args)
 {
   const char *fmt;
   char c;
@@ -673,7 +691,12 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args)
 	fmt++;
 
       if (*fmt == '$')
-	fmt++;
+	{
+	  if (fmt_check)
+	    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+			       "positional arguments are not supported");
+	  fmt++;
+	}
 
       if (*fmt =='-')
 	fmt++;
@@ -705,9 +728,19 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args)
 	case 's':
 	  args->count++;
 	  break;
+	case '%':
+	  /* "%%" is the escape sequence to output "%". */
+	  break;
+	default:
+	  if (fmt_check)
+	    return grub_error (GRUB_ERR_BAD_ARGUMENT, "unexpected format");
+	  break;
 	}
     }
 
+  if (fmt_check && args->count > max_args)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments");
+
   if (args->count <= ARRAY_SIZE (args->prealloc))
     args->ptr = args->prealloc;
   else
@@ -715,6 +748,9 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args)
       args->ptr = grub_calloc (args->count, sizeof (args->ptr[0]));
       if (!args->ptr)
 	{
+	  if (fmt_check)
+	    return grub_errno;
+
 	  grub_errno = GRUB_ERR_NONE;
 	  args->ptr = args->prealloc;
 	  args->count = ARRAY_SIZE (args->prealloc);
@@ -806,6 +842,8 @@ parse_printf_arg_fmt (const char *fmt0, struct printf_args *args)
 	  break;
 	}
     }
+
+  return GRUB_ERR_NONE;
 }
 
 static void
@@ -813,7 +851,7 @@ parse_printf_args (const char *fmt0, struct printf_args *args, va_list args_in)
 {
   grub_size_t n;
 
-  parse_printf_arg_fmt (fmt0, args);
+  parse_printf_arg_fmt (fmt0, args, 0, 0);
 
   for (n = 0; n < args->count; n++)
     switch (args->ptr[n].type)
@@ -1121,6 +1159,42 @@ grub_xasprintf (const char *fmt, ...)
   return ret;
 }
 
+grub_err_t
+grub_printf_fmt_check (const char *fmt, const char *fmt_expected)
+{
+  struct printf_args args_expected, args_fmt;
+  grub_err_t ret;
+  grub_size_t n;
+
+  if (fmt == NULL || fmt_expected == NULL)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid format");
+
+  ret = parse_printf_arg_fmt (fmt_expected, &args_expected, 1, GRUB_SIZE_MAX);
+  if (ret != GRUB_ERR_NONE)
+    return ret;
+
+  /* Limit parsing to the number of expected arguments. */
+  ret = parse_printf_arg_fmt (fmt, &args_fmt, 1, args_expected.count);
+  if (ret != GRUB_ERR_NONE)
+    {
+      free_printf_args (&args_expected);
+      return ret;
+    }
+
+  for (n = 0; n < args_fmt.count; n++)
+    if (args_fmt.ptr[n].type != args_expected.ptr[n].type)
+     {
+	ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments types do not match");
+	break;
+     }
+
+  free_printf_args (&args_expected);
+  free_printf_args (&args_fmt);
+
+  return ret;
+}
+
+
 /* Abort GRUB. This function does not return.  */
 static void __attribute__ ((noreturn))
 grub_abort (void)
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 1d6124a7a..7d2b55196 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -459,6 +459,22 @@ grub_error_load (const struct grub_error_saved *save)
   grub_errno = save->grub_errno;
 }
 
+/*
+ * grub_printf_fmt_checks() a fmt string for printf() against an expected
+ * format. It is intended for cases where the fmt string could come from
+ * an outside source and cannot be trusted.
+ *
+ * While expected fmt accepts a printf() format string it should be kept
+ * as simple as possible. The printf() format strings with positional
+ * parameters are NOT accepted, neither for fmt nor for fmt_expected.
+ *
+ * The fmt is accepted if it has equal or less arguments than fmt_expected
+ * and if the type of all arguments match.
+ *
+ * Returns GRUB_ERR_NONE if fmt is acceptable.
+ */
+grub_err_t EXPORT_FUNC (grub_printf_fmt_check) (const char *fmt, const char *fmt_expected);
+
 #if BOOT_TIME_STATS
 struct grub_boot_time
 {
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 115/117] gfxmenu/gui: Check printf() format in the gui_progress_bar and gui_label
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (113 preceding siblings ...)
  2021-03-02 18:02 ` [SECURITY PATCH 114/117] kern/misc: Add function to check printf() format against expected format Daniel Kiper
@ 2021-03-02 18:02 ` Daniel Kiper
  2021-03-02 18:02 ` [SECURITY PATCH 116/117] templates: Disable the os-prober by default Daniel Kiper
                   ` (3 subsequent siblings)
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:02 UTC (permalink / raw)
  To: grub-devel

From: Thomas Frauendorfer | Miray Software <tf@miray.de>

The gui_progress_bar and gui_label components can display the timeout
value. The format string can be set through a theme file. This patch
adds a validation step to the format string.

If a user loads a theme file into the GRUB without this patch then
a GUI label with the following settings

  + label {
  ...
  id = "__timeout__"
  text = "%s"
  }

will interpret the current timeout value as string pointer and print the
memory at that position on the screen. It is not desired behavior.

Signed-off-by: Thomas Frauendorfer | Miray Software <tf@miray.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/gfxmenu/gui_label.c        | 4 ++++
 grub-core/gfxmenu/gui_progress_bar.c | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c
index a4c817891..1c190542a 100644
--- a/grub-core/gfxmenu/gui_label.c
+++ b/grub-core/gfxmenu/gui_label.c
@@ -193,6 +193,10 @@ label_set_property (void *vself, const char *name, const char *value)
 	   else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0)
 	    value = _("enter: boot, `e': options, `c': cmd-line");
 	   /* FIXME: Add more templates here if needed.  */
+
+	  if (grub_printf_fmt_check(value, "%d") != GRUB_ERR_NONE)
+	    value = ""; /* Unsupported format. */
+
 	  self->template = grub_strdup (value);
 	  self->text = grub_xasprintf (value, self->value);
 	}
diff --git a/grub-core/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c
index b128f0866..ace85a125 100644
--- a/grub-core/gfxmenu/gui_progress_bar.c
+++ b/grub-core/gfxmenu/gui_progress_bar.c
@@ -348,6 +348,9 @@ progress_bar_set_property (void *vself, const char *name, const char *value)
 	   Please use the shortest form available in you language.  */
 	value = _("%ds");
 
+      if (grub_printf_fmt_check(value, "%d") != GRUB_ERR_NONE)
+	value = ""; /* Unsupported format. */
+
       self->template = grub_strdup (value);
     }
   else if (grub_strcmp (name, "font") == 0)
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (114 preceding siblings ...)
  2021-03-02 18:02 ` [SECURITY PATCH 115/117] gfxmenu/gui: Check printf() format in the gui_progress_bar and gui_label Daniel Kiper
@ 2021-03-02 18:02 ` Daniel Kiper
  2021-03-02 21:49   ` Didier Spaier
  2021-03-02 18:02 ` [SECURITY PATCH 117/117] kern/mm: Fix grub_debug_calloc() compilation error Daniel Kiper
                   ` (2 subsequent siblings)
  118 siblings, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:02 UTC (permalink / raw)
  To: grub-devel

From: Alex Burmashev <alexander.burmashev@oracle.com>

The os-prober is enabled by default what may lead to potentially
dangerous use cases and borderline opening attack vectors. This
patch disables the os-prober, adds warning messages and updates
GRUB_DISABLE_OS_PROBER configuration option documentation. This
way we make it clear that the os-prober usage is not recommended.

Simplistic nature of this change allows downstream vendors, who
really want os-prober to be enabled out of the box in their
relevant products, easily revert to it's old behavior.

Reported-by: NyankoSec (<nyanko@10x.moe>, https://twitter.com/NyankoSec),
             working with SSD Secure Disclosure
Signed-off-by: Alex Burmashev <alexander.burmashev@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi              | 18 ++++++++++--------
 util/grub.d/30_os-prober.in |  5 ++++-
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 2f2ae2228..cb5fe6e08 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1519,10 +1519,13 @@ boot sequence.  If you have problems, set this option to @samp{text} and
 GRUB will tell Linux to boot in normal text mode.
 
 @item GRUB_DISABLE_OS_PROBER
-Normally, @command{grub-mkconfig} will try to use the external
-@command{os-prober} program, if installed, to discover other operating
-systems installed on the same system and generate appropriate menu entries
-for them.  Set this option to @samp{true} to disable this.
+The @command{grub-mkconfig} has a feature to use the external
+@command{os-prober} program to discover other operating systems installed on
+the same machine and generate appropriate menu entries for them. It is disabled
+by default since automatic and silent execution of @command{os-prober}, and
+creating boot entries based on that data, is a potential attack vector. Set
+this option to @samp{false} to enable this feature in the
+@command{grub-mkconfig} command.
 
 @item GRUB_OS_PROBER_SKIP_LIST
 List of space-separated FS UUIDs of filesystems to be ignored from os-prober
@@ -1850,10 +1853,9 @@ than zero; otherwise 0.
 @section Multi-boot manual config
 
 Currently autogenerating config files for multi-boot environments depends on
-os-prober and has several shortcomings. While fixing it is scheduled for the
-next release, meanwhile you can make use of the power of GRUB syntax and do it
-yourself. A possible configuration is detailed here, feel free to adjust to your
-needs.
+os-prober and has several shortcomings. Due to that it is disabled by default.
+It is advised to use the power of GRUB syntax and do it yourself. A possible
+configuration is detailed here, feel free to adjust to your needs.
 
 First create a separate GRUB partition, big enough to hold GRUB. Some of the
 following entries show how to load OS installer images from this same partition,
diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
index 1b91c102f..80685b15f 100644
--- a/util/grub.d/30_os-prober.in
+++ b/util/grub.d/30_os-prober.in
@@ -26,7 +26,8 @@ export TEXTDOMAINDIR="@localedir@"
 
 . "$pkgdatadir/grub-mkconfig_lib"
 
-if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
+if [ "x${GRUB_DISABLE_OS_PROBER}" = "xfalse" ]; then
+  gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.\n"
   exit 0
 fi
 
@@ -39,6 +40,8 @@ OSPROBED="`os-prober | tr ' ' '^' | paste -s -d ' '`"
 if [ -z "${OSPROBED}" ] ; then
   # empty os-prober output, nothing doing
   exit 0
+else
+  grub_warn "$(gettext_printf "os-prober was executed to detect other bootable partitions.\nIt's output will be used to detect bootable binaries on them and create new boot entries.")"
 fi
 
 osx_entry() {
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [SECURITY PATCH 117/117] kern/mm: Fix grub_debug_calloc() compilation error
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (115 preceding siblings ...)
  2021-03-02 18:02 ` [SECURITY PATCH 116/117] templates: Disable the os-prober by default Daniel Kiper
@ 2021-03-02 18:02 ` Daniel Kiper
  2021-03-02 19:37 ` [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round John Paul Adrian Glaubitz
  2021-03-18  8:58 ` Paul Menzel
  118 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 18:02 UTC (permalink / raw)
  To: grub-devel

From: Marco A Benatto <mbenatto@redhat.com>

Fix compilation error due to missing parameter to
grub_printf() when MM_DEBUG is defined.

Fixes: 64e26162e (calloc: Make sure we always have an overflow-checking calloc() available)

Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/kern/mm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
index f2822a836..c070afc62 100644
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -594,7 +594,7 @@ grub_debug_calloc (const char *file, int line, grub_size_t nmemb, grub_size_t si
 
   if (grub_mm_debug)
     grub_printf ("%s:%d: calloc (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ",
-		 file, line, size);
+		 file, line, nmemb, size);
   ptr = grub_calloc (nmemb, size);
   if (grub_mm_debug)
     grub_printf ("%p\n", ptr);
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (116 preceding siblings ...)
  2021-03-02 18:02 ` [SECURITY PATCH 117/117] kern/mm: Fix grub_debug_calloc() compilation error Daniel Kiper
@ 2021-03-02 19:37 ` John Paul Adrian Glaubitz
  2021-03-02 20:00   ` Bruce Dubbs
  2021-03-02 20:49   ` Daniel Kiper
  2021-03-18  8:58 ` Paul Menzel
  118 siblings, 2 replies; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-02 19:37 UTC (permalink / raw)
  To: The development of GNU GRUB, Daniel Kiper
  Cc: 93sam, alexander.burmashev, chrco, chris.coulson, cjwatson,
	corsac, cperry, darren.kenny, dja, eric.snowberg, ilya.okomin,
	ivansprundel, jan.setjeeilers, jaredz, javierm, jerecox,
	john.haxby, joseph.tartaro, julian.klode, kanth.ghatraju, km,
	konrad.wilk, mario.limonciello, mbenatto, mjg59, noamr, nyanko,
	pfsmorigo, phcoder, pjones, rhughes, sajacobu, teddy.reed, tf,
	u.bauer, xnox

Hi Daniel!

On 3/2/21 7:00 PM, Daniel Kiper wrote:
> The BootHole vulnerability [1][2] announced last year encouraged many people to
> take a closer look at the security of boot process in general and the GRUB
> bootloader in particular. Due to that, during past few months we were getting
> reports of, and also discovering various security flaws in the GRUB ourselves.
> You can find the list of most severe ones which got CVEs assigned at the end of
> this message. The patch bundle fixing all these issues in the upstream GRUB
> contains 117 patches.

Huge thanks and kudos to everyone involved fixing all these vulnerabilities!

Given the amount of patches, wouldn't it make sense to push an RC candidate
for 2.06 in the near future so that distributions can start shipping the pre-
release and avoiding to carry this large amount of patches?

Thanks,
Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
  2021-03-02 19:37 ` [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round John Paul Adrian Glaubitz
@ 2021-03-02 20:00   ` Bruce Dubbs
  2021-03-02 20:49   ` Daniel Kiper
  1 sibling, 0 replies; 147+ messages in thread
From: Bruce Dubbs @ 2021-03-02 20:00 UTC (permalink / raw)
  To: grub-devel

On 3/2/21 1:37 PM, John Paul Adrian Glaubitz wrote:
> Hi Daniel!
> 
> On 3/2/21 7:00 PM, Daniel Kiper wrote:
>> The BootHole vulnerability [1][2] announced last year encouraged many people to
>> take a closer look at the security of boot process in general and the GRUB
>> bootloader in particular. Due to that, during past few months we were getting
>> reports of, and also discovering various security flaws in the GRUB ourselves.
>> You can find the list of most severe ones which got CVEs assigned at the end of
>> this message. The patch bundle fixing all these issues in the upstream GRUB
>> contains 117 patches.
> 
> Huge thanks and kudos to everyone involved fixing all these vulnerabilities!
> 
> Given the amount of patches, wouldn't it make sense to push an RC candidate
> for 2.06 in the near future so that distributions can start shipping the pre-
> release and avoiding to carry this large amount of patches?

It makes sense to not rely on distros to do the job of GRUB.  It's time 
to get on a release schedule and stick to it.  Very complex packages 
like gcc, glibc, and binutils are on a six month schedule.  Why not GRUB?

 From https://ftp.gnu.org/gnu/grub/:
grub-1.99.tar.gz	2011-05-14
grub-2.00.tar.gz	2012-06-27
grub-2.02.tar.gz	2017-04-26
grub-2.04.tar.gz	2019-07-05
grub-2.06.tar.gz        202?-??-??

If you are waiting for perfection, you will never get there.

   -- Bruce


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
  2021-03-02 19:37 ` [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round John Paul Adrian Glaubitz
  2021-03-02 20:00   ` Bruce Dubbs
@ 2021-03-02 20:49   ` Daniel Kiper
  2021-03-09 15:57     ` Neal Gompa
  1 sibling, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-02 20:49 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz
  Cc: The development of GNU GRUB, 93sam, alexander.burmashev, chrco,
	chris.coulson, cjwatson, corsac, cperry, darren.kenny, dja,
	eric.snowberg, ilya.okomin, ivansprundel, jan.setjeeilers,
	jaredz, javierm, jerecox, john.haxby, joseph.tartaro,
	julian.klode, kanth.ghatraju, km, konrad.wilk, mario.limonciello,
	mbenatto, mjg59, noamr, nyanko, pfsmorigo, phcoder, pjones,
	rhughes, sajacobu, teddy.reed, tf, u.bauer, xnox

Hi Adrian,

On Tue, Mar 02, 2021 at 08:37:14PM +0100, John Paul Adrian Glaubitz wrote:
> Hi Daniel!
>
> On 3/2/21 7:00 PM, Daniel Kiper wrote:
> > The BootHole vulnerability [1][2] announced last year encouraged many people to
> > take a closer look at the security of boot process in general and the GRUB
> > bootloader in particular. Due to that, during past few months we were getting
> > reports of, and also discovering various security flaws in the GRUB ourselves.
> > You can find the list of most severe ones which got CVEs assigned at the end of
> > this message. The patch bundle fixing all these issues in the upstream GRUB
> > contains 117 patches.
>
> Huge thanks and kudos to everyone involved fixing all these vulnerabilities!
>
> Given the amount of patches, wouldn't it make sense to push an RC candidate
> for 2.06 in the near future so that distributions can start shipping the pre-
> release and avoiding to carry this large amount of patches?

I am planning to cut 2.06-rc1 in matter of days...

Daniel


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-02 18:02 ` [SECURITY PATCH 116/117] templates: Disable the os-prober by default Daniel Kiper
@ 2021-03-02 21:49   ` Didier Spaier
  2021-03-03 13:13     ` Daniel Kiper
  0 siblings, 1 reply; 147+ messages in thread
From: Didier Spaier @ 2021-03-02 21:49 UTC (permalink / raw)
  To: grub-devel

Le 02/03/2021 à 19:02, Daniel Kiper a écrit :
> From: Alex Burmashev <alexander.burmashev@oracle.com>
> diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
> index 1b91c102f..80685b15f 100644
> --- a/util/grub.d/30_os-prober.in
> +++ b/util/grub.d/30_os-prober.in
> @@ -26,7 +26,8 @@ export TEXTDOMAINDIR="@localedir@"
>   
>   . "$pkgdatadir/grub-mkconfig_lib"
>   
> -if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
> +if [ "x${GRUB_DISABLE_OS_PROBER}" = "xfalse" ]; then
> +  gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.\n"
>     exit 0
>   fi

This is confusing: now to get boot entries from os-prober one have to
set:
GRUB_DISABLE_OS_PROBER=true
in /etc/default/grub.

Either revert that, or (better, in my opinion) label the variable
GRUB_ENABLE_OS_PROBER and set it to false by default.

Tested from grub pulled from git master with all patches committed.

Best regards,
Didier


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-02 21:49   ` Didier Spaier
@ 2021-03-03 13:13     ` Daniel Kiper
  2021-03-03 17:28       ` Lennart Sorensen
  2021-03-03 18:43       ` John Paul Adrian Glaubitz
  0 siblings, 2 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-03 13:13 UTC (permalink / raw)
  To: Didier Spaier; +Cc: grub-devel

On Tue, Mar 02, 2021 at 10:49:16PM +0100, Didier Spaier wrote:
> Le 02/03/2021 à 19:02, Daniel Kiper a écrit :
> > From: Alex Burmashev <alexander.burmashev@oracle.com>
> > diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
> > index 1b91c102f..80685b15f 100644
> > --- a/util/grub.d/30_os-prober.in
> > +++ b/util/grub.d/30_os-prober.in
> > @@ -26,7 +26,8 @@ export TEXTDOMAINDIR="@localedir@"
> >   . "$pkgdatadir/grub-mkconfig_lib"
> > -if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
> > +if [ "x${GRUB_DISABLE_OS_PROBER}" = "xfalse" ]; then
> > +  gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.\n"
> >     exit 0
> >   fi
>
> This is confusing: now to get boot entries from os-prober one have to
> set:
> GRUB_DISABLE_OS_PROBER=true
> in /etc/default/grub.
>
> Either revert that, or (better, in my opinion) label the variable
> GRUB_ENABLE_OS_PROBER and set it to false by default.

When we worked on this patch we considered that. However, after some
thinking we stated that renaming to GRUB_ENABLE_OS_PROBER will make
more confusion. So, we decided to stick to existing name even if it
is not the best one.

> Tested from grub pulled from git master with all patches committed.

Thank you for doing tests.

Daniel


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-03 13:13     ` Daniel Kiper
@ 2021-03-03 17:28       ` Lennart Sorensen
  2021-03-03 18:43       ` John Paul Adrian Glaubitz
  1 sibling, 0 replies; 147+ messages in thread
From: Lennart Sorensen @ 2021-03-03 17:28 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Didier Spaier

On Wed, Mar 03, 2021 at 02:13:04PM +0100, Daniel Kiper wrote:
> On Tue, Mar 02, 2021 at 10:49:16PM +0100, Didier Spaier wrote:
> > Le 02/03/2021 à 19:02, Daniel Kiper a écrit :
> > > From: Alex Burmashev <alexander.burmashev@oracle.com>
> > > diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in
> > > index 1b91c102f..80685b15f 100644
> > > --- a/util/grub.d/30_os-prober.in
> > > +++ b/util/grub.d/30_os-prober.in
> > > @@ -26,7 +26,8 @@ export TEXTDOMAINDIR="@localedir@"
> > >   . "$pkgdatadir/grub-mkconfig_lib"
> > > -if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then
> > > +if [ "x${GRUB_DISABLE_OS_PROBER}" = "xfalse" ]; then
> > > +  gettext_printf "os-prober will not be executed to detect other bootable partitions.\nSystems on them will not be added to the GRUB boot configuration.\nCheck GRUB_DISABLE_OS_PROBER documentation entry.\n"
> > >     exit 0
> > >   fi
> >
> > This is confusing: now to get boot entries from os-prober one have to
> > set:
> > GRUB_DISABLE_OS_PROBER=true
> > in /etc/default/grub.
> >
> > Either revert that, or (better, in my opinion) label the variable
> > GRUB_ENABLE_OS_PROBER and set it to false by default.
> 
> When we worked on this patch we considered that. However, after some
> thinking we stated that renaming to GRUB_ENABLE_OS_PROBER will make
> more confusion. So, we decided to stick to existing name even if it
> is not the best one.

How does that make any sense?

You can disable it by default, but leave the meaning of true and false
and the name the same.  Someone would then have to explicitly set
GRUB_DISABLE_OS_PROBER to false if they want to use it still.  At least
then it makes some sense.

And what does the code do now if someone already has it set to true in
order to disable it, as is in all existing examples and documentation
about the option?  Does it now actually get enabled which is the opposite
of what they wanted?

Something sure looks wrong with this.

-- 
Len Sorensen


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-03 13:13     ` Daniel Kiper
  2021-03-03 17:28       ` Lennart Sorensen
@ 2021-03-03 18:43       ` John Paul Adrian Glaubitz
  2021-03-03 19:05         ` Lennart Sorensen
  2021-03-03 19:38         ` Daniel Kiper
  1 sibling, 2 replies; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-03 18:43 UTC (permalink / raw)
  To: Daniel Kiper, Didier Spaier; +Cc: The development of GNU GRUB

Hi Daniel!

On 3/3/21 2:13 PM, Daniel Kiper wrote:
>> This is confusing: now to get boot entries from os-prober one have to
>> set:
>> GRUB_DISABLE_OS_PROBER=true
>> in /etc/default/grub.
>>
>> Either revert that, or (better, in my opinion) label the variable
>> GRUB_ENABLE_OS_PROBER and set it to false by default.
> 
> When we worked on this patch we considered that. However, after some
> thinking we stated that renaming to GRUB_ENABLE_OS_PROBER will make
> more confusion. So, we decided to stick to existing name even if it
> is not the best one.

I'm not sure I'm able to follow the motivation to keep the naming scheme
as is.

If I have an option called "DISABLE_FEATURE_X", then I would expect setting
it to "true" would mean that the feature is disabled not the other way around.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-03 18:43       ` John Paul Adrian Glaubitz
@ 2021-03-03 19:05         ` Lennart Sorensen
  2021-03-03 19:11           ` Didier Spaier
  2021-03-03 19:38         ` Daniel Kiper
  1 sibling, 1 reply; 147+ messages in thread
From: Lennart Sorensen @ 2021-03-03 19:05 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Daniel Kiper, Didier Spaier

On Wed, Mar 03, 2021 at 07:43:23PM +0100, John Paul Adrian Glaubitz wrote:
> I'm not sure I'm able to follow the motivation to keep the naming scheme
> as is.
> 
> If I have an option called "DISABLE_FEATURE_X", then I would expect setting
> it to "true" would mean that the feature is disabled not the other way around.

And existing users have already set it to true to disable it, so true
better mean disabled.

-- 
Len Sorensen


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-03 19:05         ` Lennart Sorensen
@ 2021-03-03 19:11           ` Didier Spaier
  0 siblings, 0 replies; 147+ messages in thread
From: Didier Spaier @ 2021-03-03 19:11 UTC (permalink / raw)
  To: grub-devel



Le 03/03/2021 à 20:05, Lennart Sorensen a écrit :
> On Wed, Mar 03, 2021 at 07:43:23PM +0100, John Paul Adrian Glaubitz wrote:
>> I'm not sure I'm able to follow the motivation to keep the naming scheme
>> as is.
>>
>> If I have an option called "DISABLE_FEATURE_X", then I would expect setting
>> it to "true" would mean that the feature is disabled not the other way around.
> 
> And existing users have already set it to true to disable it, so true
> better mean disabled.

And at least one existing user had willingly set it to false and didn't
understand why the expected boot entries were not generated after
having upgraded, as they were previously.

Didier


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-03 18:43       ` John Paul Adrian Glaubitz
  2021-03-03 19:05         ` Lennart Sorensen
@ 2021-03-03 19:38         ` Daniel Kiper
  2021-03-03 20:13           ` John Paul Adrian Glaubitz
  1 sibling, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-03 19:38 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz
  Cc: Didier Spaier, lsorense, The development of GNU GRUB

On Wed, Mar 03, 2021 at 07:43:23PM +0100, John Paul Adrian Glaubitz wrote:
> Hi Daniel!
>
> On 3/3/21 2:13 PM, Daniel Kiper wrote:
> >> This is confusing: now to get boot entries from os-prober one have to
> >> set:
> >> GRUB_DISABLE_OS_PROBER=true
> >> in /etc/default/grub.
> >>
> >> Either revert that, or (better, in my opinion) label the variable
> >> GRUB_ENABLE_OS_PROBER and set it to false by default.
> >
> > When we worked on this patch we considered that. However, after some
> > thinking we stated that renaming to GRUB_ENABLE_OS_PROBER will make
> > more confusion. So, we decided to stick to existing name even if it
> > is not the best one.
>
> I'm not sure I'm able to follow the motivation to keep the naming scheme
> as is.
>
> If I have an option called "DISABLE_FEATURE_X", then I would expect setting
> it to "true" would mean that the feature is disabled not the other way around.

Huh! I have just realized that we did not drop "if" change from earlier version
of patch which also changed variable name. Interestingly doc update is correct.
Anyway, sorry for the confusion. I asked Alex to post a fix for this.

Daniel


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 116/117] templates: Disable the os-prober by default
  2021-03-03 19:38         ` Daniel Kiper
@ 2021-03-03 20:13           ` John Paul Adrian Glaubitz
  0 siblings, 0 replies; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-03 20:13 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: Didier Spaier, lsorense, The development of GNU GRUB

Hi Daniel!

On 3/3/21 8:38 PM, Daniel Kiper wrote:
>> I'm not sure I'm able to follow the motivation to keep the naming scheme
>> as is.
>>
>> If I have an option called "DISABLE_FEATURE_X", then I would expect setting
>> it to "true" would mean that the feature is disabled not the other way around.
> 
> Huh! I have just realized that we did not drop "if" change from earlier version
> of patch which also changed variable name. Interestingly doc update is correct.
> Anyway, sorry for the confusion. I asked Alex to post a fix for this.

I'm glad we were able to resolve this. I was already questioning my sanity :D.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
  2021-03-02 20:49   ` Daniel Kiper
@ 2021-03-09 15:57     ` Neal Gompa
  2021-03-09 16:58       ` Daniel Kiper
  0 siblings, 1 reply; 147+ messages in thread
From: Neal Gompa @ 2021-03-09 15:57 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: John Paul Adrian Glaubitz, 93sam, alexander.burmashev, chrco,
	chris.coulson, cjwatson, corsac, cperry, darren.kenny, dja,
	eric.snowberg, ilya.okomin, ivansprundel, jan.setjeeilers,
	jaredz, Javier Martinez Canillas, jerecox, john.haxby,
	joseph.tartaro, Julian Andres Klode, kanth.ghatraju, km,
	konrad.wilk, mario.limonciello, mbenatto, mjg59, noamr, nyanko,
	pfsmorigo, phcoder, Peter Jones, Richard Hughes, sajacobu,
	teddy.reed, tf, u.bauer, xnox

On Tue, Mar 2, 2021 at 4:08 PM Daniel Kiper <daniel.kiper@oracle.com> wrote:
>
> Hi Adrian,
>
> On Tue, Mar 02, 2021 at 08:37:14PM +0100, John Paul Adrian Glaubitz wrote:
> > Hi Daniel!
> >
> > On 3/2/21 7:00 PM, Daniel Kiper wrote:
> > > The BootHole vulnerability [1][2] announced last year encouraged many people to
> > > take a closer look at the security of boot process in general and the GRUB
> > > bootloader in particular. Due to that, during past few months we were getting
> > > reports of, and also discovering various security flaws in the GRUB ourselves.
> > > You can find the list of most severe ones which got CVEs assigned at the end of
> > > this message. The patch bundle fixing all these issues in the upstream GRUB
> > > contains 117 patches.
> >
> > Huge thanks and kudos to everyone involved fixing all these vulnerabilities!
> >
> > Given the amount of patches, wouldn't it make sense to push an RC candidate
> > for 2.06 in the near future so that distributions can start shipping the pre-
> > release and avoiding to carry this large amount of patches?
>
> I am planning to cut 2.06-rc1 in matter of days...
>

Any status update on this? The delta between 2.04 and HEAD is huge,
and I'd rather have a release to work from now...


-- 
真実はいつも一つ!/ Always, there's only one truth!


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
  2021-03-09 15:57     ` Neal Gompa
@ 2021-03-09 16:58       ` Daniel Kiper
  0 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-09 16:58 UTC (permalink / raw)
  To: Neal Gompa
  Cc: The development of GNU GRUB, John Paul Adrian Glaubitz, 93sam,
	alexander.burmashev, chrco, chris.coulson, cjwatson, corsac,
	cperry, darren.kenny, dja, eric.snowberg, ilya.okomin,
	ivansprundel, jan.setjeeilers, jaredz, Javier Martinez Canillas,
	jerecox, john.haxby, joseph.tartaro, Julian Andres Klode,
	kanth.ghatraju, km, konrad.wilk, mario.limonciello, mbenatto,
	mjg59, noamr, nyanko, pfsmorigo, phcoder, Peter Jones,
	Richard Hughes, sajacobu, teddy.reed, tf, u.bauer, xnox

On Tue, Mar 09, 2021 at 10:57:36AM -0500, Neal Gompa wrote:
> On Tue, Mar 2, 2021 at 4:08 PM Daniel Kiper <daniel.kiper@oracle.com> wrote:
> >
> > Hi Adrian,
> >
> > On Tue, Mar 02, 2021 at 08:37:14PM +0100, John Paul Adrian Glaubitz wrote:
> > > Hi Daniel!
> > >
> > > On 3/2/21 7:00 PM, Daniel Kiper wrote:
> > > > The BootHole vulnerability [1][2] announced last year encouraged many people to
> > > > take a closer look at the security of boot process in general and the GRUB
> > > > bootloader in particular. Due to that, during past few months we were getting
> > > > reports of, and also discovering various security flaws in the GRUB ourselves.
> > > > You can find the list of most severe ones which got CVEs assigned at the end of
> > > > this message. The patch bundle fixing all these issues in the upstream GRUB
> > > > contains 117 patches.
> > >
> > > Huge thanks and kudos to everyone involved fixing all these vulnerabilities!
> > >
> > > Given the amount of patches, wouldn't it make sense to push an RC candidate
> > > for 2.06 in the near future so that distributions can start shipping the pre-
> > > release and avoiding to carry this large amount of patches?
> >
> > I am planning to cut 2.06-rc1 in matter of days...
> >
>
> Any status update on this? The delta between 2.04 and HEAD is huge,
> and I'd rather have a release to work from now...

WIP, expect rc1 by the end of this week...

> 真実はいつも一つ!/ Always, there's only one truth!

Hmmm... Interesting... :-)

Daniel


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image
  2021-03-02 18:00 ` [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image Daniel Kiper
@ 2021-03-18  1:22   ` Colin Watson
  2021-03-18  7:04     ` Michael Chang
  0 siblings, 1 reply; 147+ messages in thread
From: Colin Watson @ 2021-03-18  1:22 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Marco A Benatto, Javier Martinez Canillas, Daniel Kiper, 984488, 985374

On Tue, Mar 02, 2021 at 07:00:08PM +0100, Daniel Kiper wrote:
> From: Marco A Benatto <mbenatto@redhat.com>
> 
> Move verifiers API from a module to the kernel image, so it can be
> used there as well. There are no functional changes in this patch.

I've had reports in Debian that the i386-pc image no longer fits in the
MBR in some configurations (e.g. https://bugs.debian.org/984488,
https://bugs.debian.org/985374).

(Yes, I know, MBR is awful and even people who have to use it should put
the first partition at more like 1MiB rather than 63 sectors, but it
isn't practical for non-experts to fix up existing systems without a
complete reinstallation, so breaking this in a security update is pretty
bad.)

Since I suspected that a lot of this was due to organic growth of the
image as the security patch series made various bits of code more
careful, I wrote a script to build each revision along the upstream
changes from Debian version 2.04-15 to 2.04-16 and build an image with
the following modules, extracted from one of those bug reports: ext2
part_msdos diskfilter mdraid09 biosdisk.  Here's a report of the
resulting image sizes and commits:

  30884 2bd6855d2 grub-install: Fix inverted test for NLS enabled when copying locales
  31427 0d324ad1b verifiers: Move verifiers API to kernel image
  31446 6e14c57c6 kern: Add lockdown support
  31446 f1d70c97b kern/lockdown: Set a variable if the GRUB is locked down
  31446 71b48a193 efi: Lockdown the GRUB when the UEFI Secure Boot is enabled
  31446 3d8afd579 efi: Use grub_is_lockdown() instead of hardcoding a disabled modules list
  31446 c3037730d acpi: Don't register the acpi command when locked down
  31446 5d58cce5c mmap: Don't register cutmem and badram commands when lockdown is enforced
  31446 22f08600d commands: Restrict commands that can load BIOS or DT blobs when locked down
  31446 bf939ef4e commands/setpci: Restrict setpci command when locked down
  31446 ad9d55e50 commands/hdparm: Restrict hdparm command when locked down
  31446 13a1fa9c1 gdb: Restrict GDB access when locked down
  31446 b1e1dd471 loader/xnu: Don't allow loading extension and packages when locked down
  31446 9042c1bc8 docs: Document the cutmem command
  31452 9e6b789fa dl: Only allow unloading modules that are not dependencies
  31452 d26f10df9 usb: Avoid possible out-of-bound accesses caused by malicious devices
  31452 a993a2006 mmap: Fix memory leak when iterating over mapped memory
  31452 60709e32e net/net: Fix possible dereference to of a NULL pointer
  31452 118fe4df3 net/tftp: Fix dangling memory pointer
  31473 967b95c4e kern/parser: Fix resource leak if argc == 0
  31473 42b46cb07 kern/efi: Fix memory leak on failure
  31473 10f42aeff kern/efi/mm: Fix possible NULL pointer dereference
  31473 ad3b3b125 gnulib/regexec: Resolve unused variable
  31473 a0b08bad3 gnulib/regcomp: Fix uninitialized token structure
  31473 3131d3ff8 gnulib/argp-help: Fix dereference of a possibly NULL state
  31473 dc28cd75d gnulib/regexec: Fix possible null-dereference
  31473 711dd9d97 gnulib/regcomp: Fix uninitialized re_token
  31473 28314f6c1 io/lzopio: Resolve unnecessary self-assignment errors
  31473 f4eb2c3dd zstd: Initialize seq_t structure fully
  31482 6d368ec03 kern/partition: Check for NULL before dereferencing input string
  31482 e743b06fc disk/ldm: Make sure comp data is freed before exiting from make_vg()
  31482 af94bf626 disk/ldm: If failed then free vg variable too
  31482 8e43b154c disk/ldm: Fix memory leak on uninserted lv references
  31482 0beb60002 disk/cryptodisk: Fix potential integer overflow
  31482 20ddfae56 hfsplus: Check that the volume name length is valid
  31482 d8fa680fe zfs: Fix possible negative shift operation
  31482 1b80d2dde zfs: Fix resource leaks while constructing path
  31482 2b07acad0 zfs: Fix possible integer overflows
  31482 0283863c7 zfsinfo: Correct a check for error allocating memory
  31482 ad663e4ea affs: Fix memory leaks
  31482 8d9e05f24 libgcrypt/mpi: Fix possible unintended sign extension
  31482 3120a6835 libgcrypt/mpi: Fix possible NULL dereference
  31482 6d38008dd syslinux: Fix memory leak while parsing
  31482 06f86bc0d normal/completion: Fix leaking of memory when processing a completion
  31482 e31e8ecbc commands/hashsum: Fix a memory leak
  31482 74d544182 video/efi_gop: Remove unnecessary return value of grub_video_gop_fill_mode_info()
  31482 e07f13cfa video/fb/fbfill: Fix potential integer overflow
  31482 fffc476df video/fb/video_fb: Fix multiple integer overflows
  31482 786656dc8 video/fb/video_fb: Fix possible integer overflow
  31482 bf3df4eeb video/readers/jpeg: Test for an invalid next marker reference from a jpeg file
  31482 f9b9c56e2 gfxmenu/gui_list: Remove code that coverity is flagging as dead
  31482 11cf998c2 loader/bsd: Check for NULL arg up-front
  31482 d311599e4 loader/xnu: Fix memory leak
  31482 986de6735 loader/xnu: Free driverkey data when an error is detected in grub_xnu_writetree_toheap()
  31482 f851813cd loader/xnu: Check if pointer is NULL before using it
  31482 4f7bde3ab util/grub-install: Fix NULL pointer dereferences
  31482 fd0e3f964 util/grub-editenv: Fix incorrect casting of a signed value
  31482 d86e80fe0 util/glue-efi: Fix incorrect use of a possibly negative value
  31482 6a84527d4 script/execute: Fix NULL dereference in grub_script_execute_cmdline()
  31482 f785f176a commands/ls: Require device_name is not NULL before printing
  31482 12f5e77dc script/execute: Avoid crash when using "$#" outside a function scope
  31482 82446d230 lib/arg: Block repeated short options that require an argument
  31482 121811a98 script/execute: Don't crash on a "for" loop with no items
  31482 3c5bfae9e commands/menuentry: Fix quoting in setparams_prefix()
  31474 abdc1e40a kern/misc: Always set *end in grub_strtoull()
  31474 b189d92cb video/readers/jpeg: Catch files with unsupported quantization or Huffman tables
  31474 7b5a6dc77 video/readers/jpeg: Catch OOB reads/writes in grub_jpeg_decode_du()
  31474 14cc3bde4 video/readers/jpeg: Don't decode data before start of stream
  31474 0013a6fa9 term/gfxterm: Don't set up a font with glyphs that are too big
  31508 2832f9ed4 fs/fshelp: Catch impermissibly large block sizes in read helper
  31508 0a8501280 fs/hfsplus: Don't fetch a key beyond the end of the node
  31508 1632d4751 fs/hfsplus: Don't use uninitialized data on corrupt filesystems
  31508 3dbfcb563 fs/hfs: Disable under lockdown
  31508 0e5a7bb86 fs/sfs: Fix over-read of root object name
  31508 4089be10f fs/jfs: Do not move to leaf level if name length is negative
  31508 2de73233c fs/jfs: Limit the extents that getblk() can consider
  31508 751f1ad0b fs/jfs: Catch infinite recursion
  31508 64b8e6ab3 fs/nilfs2: Reject too-large keys
  31508 e5b544089 fs/nilfs2: Don't search children if provided number is too large
  31508 6187f84c0 fs/nilfs2: Properly bail on errors in grub_nilfs2_btree_node_lookup()
  31508 ab6d7615d io/gzio: Bail if gzio->tl/td is NULL
  31508 b3c863498 io/gzio: Add init_dynamic_block() clean up if unpacking codes fails
  31508 fd737860d io/gzio: Catch missing values in huft_build() and bail
  31508 2df30bf33 io/gzio: Zero gzio->tl/td in init_dynamic_block() if huft_build() fails
  31508 64eb78f6c disk/lvm: Don't go beyond the end of the data we read from disk
  31508 b448c78a1 disk/lvm: Don't blast past the end of the circular metadata buffer
  31508 ff49d996d disk/lvm: Bail on missing PV list
  31508 87625cadf disk/lvm: Do not crash if an expected string is not found
  31508 aed3e7107 disk/lvm: Do not overread metadata
  31508 3fc149f18 disk/lvm: Sanitize rlocn->offset to prevent wild read
  31508 e8f1ae648 disk/lvm: Do not allow a LV to be it's own segment's node's LV
  31508 bd87498f4 fs/btrfs: Validate the number of stripes/parities in RAID5/6
  31508 99572884b fs/btrfs: Squash some uninitialized reads
  31529 3f1acab9c kern/parser: Fix a memory leak
  31529 7feb878e8 kern/parser: Introduce process_char() helper
  31556 3ab27438b kern/parser: Introduce terminate_arg() helper
  31541 782fb1971 kern/parser: Refactor grub_parser_split_cmdline() cleanup
  31698 fc938b31c kern/buffer: Add variable sized heap buffer
  31826 596d36219 kern/parser: Fix a stack buffer overflow
  31826 149524eaa kern/efi: Add initial stack protector implementation
  31826 039725fe7 util/mkimage: Remove unused code to add BSS section
  31826 0a6005c74 util/mkimage: Use grub_host_to_target32() instead of grub_cpu_to_le32()
  31826 cf179bd80 util/mkimage: Always use grub_host_to_target32() to initialize PE stack and heap stuff
  31826 2aa0ef41c util/mkimage: Unify more of the PE32 and PE32+ header set-up
  31826 1aa253780 util/mkimage: Reorder PE optional header fields set-up
  31826 99f02aab1 util/mkimage: Improve data_size value calculation
  31826 1c810627e util/mkimage: Refactor section setup to use a helper
  31826 26ff81d1e util/mkimage: Add an option to import SBAT metadata into a .sbat section
  31826 2564455e7 grub-install-common: Add --sbat option
  31826 55c7de529 kern/misc: Split parse_printf_args() into format parsing and va_list handling
  31787 c8bc04397 kern/misc: Add STRING type for internal printf() format handling
  32060 834e5d238 kern/misc: Add function to check printf() format against expected format
  32060 c652b0e86 gfxmenu/gui: Check printf() format in the gui_progress_bar and gui_label
  32060 9cd32c576 kern/mm: Fix grub_debug_calloc() compilation error

I believe the practical threshold is 62 512-byte sectors, i.e. 31744
bytes.

As you can see, the biggest single change was induced by this patch,
which moves the verifiers API into the kernel image.  Makes sense.  Is
there anything we can do about this?

I'm a little confused why this change had to be made in this way.
grub_load_modules is called pretty early during kernel initialization,
and it initializes all embedded modules.  Wouldn't it have been
sufficient to leave verifiers as a module and simply include that module
in all UEFI-platform images?

If that wouldn't have worked for some reason, then perhaps it would be
possible to restructure things a bit more so that we could leave the
verifiers API as a module on i386-pc, e.g. by moving it back to
grub-core/commands/verifiers.c and having conditional code that either
registers/unregisters the filter in a module or registers it at kernel
startup, depending on the platform.  It wouldn't be especially pretty,
but I think we could tolerate that for the sake of fixing this
regression.

Thanks,

-- 
Colin Watson (he/him)                              [cjwatson@debian.org]


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 114/117] kern/misc: Add function to check printf() format against expected format
  2021-03-02 18:02 ` [SECURITY PATCH 114/117] kern/misc: Add function to check printf() format against expected format Daniel Kiper
@ 2021-03-18  1:30   ` Colin Watson
  0 siblings, 0 replies; 147+ messages in thread
From: Colin Watson @ 2021-03-18  1:30 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Thomas Frauendorfer | Miray Software, Daniel Kiper, 984488, 985374

On Tue, Mar 02, 2021 at 07:02:01PM +0100, Daniel Kiper wrote:
> @@ -1121,6 +1159,42 @@ grub_xasprintf (const char *fmt, ...)
>    return ret;
>  }
>  
> +grub_err_t
> +grub_printf_fmt_check (const char *fmt, const char *fmt_expected)
> +{
> +  struct printf_args args_expected, args_fmt;
> +  grub_err_t ret;
> +  grub_size_t n;
> +
> +  if (fmt == NULL || fmt_expected == NULL)
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid format");
> +
> +  ret = parse_printf_arg_fmt (fmt_expected, &args_expected, 1, GRUB_SIZE_MAX);
> +  if (ret != GRUB_ERR_NONE)
> +    return ret;
> +
> +  /* Limit parsing to the number of expected arguments. */
> +  ret = parse_printf_arg_fmt (fmt, &args_fmt, 1, args_expected.count);
> +  if (ret != GRUB_ERR_NONE)
> +    {
> +      free_printf_args (&args_expected);
> +      return ret;
> +    }
> +
> +  for (n = 0; n < args_fmt.count; n++)
> +    if (args_fmt.ptr[n].type != args_expected.ptr[n].type)
> +     {
> +	ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments types do not match");
> +	break;
> +     }
> +
> +  free_printf_args (&args_expected);
> +  free_printf_args (&args_fmt);
> +
> +  return ret;
> +}
> +
> +
>  /* Abort GRUB. This function does not return.  */
>  static void __attribute__ ((noreturn))
>  grub_abort (void)

This function is only used by gfxmenu.  Could it please be moved out of
the kernel and into a module, perhaps just gfxmenu itself?

As shown in the report from the other mail I just sent to this thread,
this patch costs an additional 273 bytes on i386-pc, where core image
size is at an extreme premium on some systems with limited space between
the MBR and the first partition; a plausible RAID setup used by some
Debian users is currently 316 bytes over the limit, so reclaiming this
space would be valuable.

Reclaiming all of those 273 bytes would probably involve duplicating
parse_printf_arg_fmt rather than having the fmt_check and max_args
arguments there, but I'm sure that even just moving the top-level
format-checking function would help.

Thanks,

-- 
Colin Watson (he/him)                              [cjwatson@debian.org]


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image
  2021-03-18  1:22   ` Colin Watson
@ 2021-03-18  7:04     ` Michael Chang
  0 siblings, 0 replies; 147+ messages in thread
From: Michael Chang @ 2021-03-18  7:04 UTC (permalink / raw)
  To: The development of GNU GRUB
  Cc: Marco A Benatto, Javier Martinez Canillas, Daniel Kiper, 984488, 985374

On Thu, Mar 18, 2021 at 01:22:19AM +0000, Colin Watson wrote:
> On Tue, Mar 02, 2021 at 07:00:08PM +0100, Daniel Kiper wrote:

[snip]

> I believe the practical threshold is 62 512-byte sectors, i.e. 31744
> bytes.
> 
> As you can see, the biggest single change was induced by this patch,
> which moves the verifiers API into the kernel image.  Makes sense.  Is
> there anything we can do about this?
> 
> I'm a little confused why this change had to be made in this way.
> grub_load_modules is called pretty early during kernel initialization,
> and it initializes all embedded modules.  Wouldn't it have been
> sufficient to leave verifiers as a module and simply include that module
> in all UEFI-platform images?
> 
> If that wouldn't have worked for some reason, then perhaps it would be
> possible to restructure things a bit more so that we could leave the
> verifiers API as a module on i386-pc, e.g. by moving it back to
> grub-core/commands/verifiers.c and having conditional code that either
> registers/unregisters the filter in a module or registers it at kernel
> startup, depending on the platform.  It wouldn't be especially pretty,
> but I think we could tolerate that for the sake of fixing this
> regression.

I fully concur with Colin's idea. It is unfortunate that short MBR gap
is still used, but it is also unnecessary to increase core image size to
support nonexistent efi lockdown on i386-pc platform. The only consumer
of the verifiers on the i386-pc platform is pgp module so it is good to
keep verifiers as module as long as autoload can keep existing
configuation to work transparently.

For that I've also worked out a patch and will post here for review. 

Thanks,
Michael

> 
> Thanks,
> 
> -- 
> Colin Watson (he/him)                              [cjwatson@debian.org]
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper
  2021-03-02 18:01 ` [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper Daniel Kiper
@ 2021-03-18  8:38   ` John Paul Adrian Glaubitz
  2021-03-20 15:05     ` John Paul Adrian Glaubitz
  2021-03-23 19:16     ` John Paul Adrian Glaubitz
  0 siblings, 2 replies; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-18  8:38 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: The development of GNU GRUB, Peter Jones, debian-ia64,
	Sergei Trofimovich, Jessica Clarke

Hi!

On 3/2/21 7:01 PM, Daniel Kiper wrote:
> From: Peter Jones <pjones@redhat.com>
> 
> Add a init_pe_section() helper function to setup PE sections. This makes
> the code simpler and easier to read.
> 
> Signed-off-by: Peter Jones <pjones@redhat.com>
> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

This change broke GRUB on ia64 for me. It now fails to perform any basic commands:

Loading.: grub                                                              
Starting: grub                                                              
Welcome to GRUB!                                                                                                                                                                                                                                         
error: unknown filesystem.
Entering rescue mode...
grub rescue> insmod ext2
error: unknown filesystem.
grub rescue> help
Unknown command `help'.
grub rescue> ?
Unknown command `?'.
grub rescue> linux
Unknown command `linux'.
grub rescue>

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 029/117] zstd: Initialize seq_t structure fully
  2021-03-02 18:00 ` [SECURITY PATCH 029/117] zstd: Initialize seq_t structure fully Daniel Kiper
@ 2021-03-18  8:50   ` Paul Menzel
  2021-03-18  9:37     ` Darren Kenny
  0 siblings, 1 reply; 147+ messages in thread
From: Paul Menzel @ 2021-03-18  8:50 UTC (permalink / raw)
  To: Daniel Kiper, Darren Kenny; +Cc: Nick Terrell, The development of GNU GRUB

Dear Darren, dear Daniel,


Am 02.03.21 um 19:00 schrieb Daniel Kiper:
> From: Darren Kenny <darren.kenny@oracle.com>
> 
> While many compilers will initialize this to zero, not all will,

Which ones do not?

> so it is better to be sure that fields not being explicitly set are at known
> values, and there is code that checks this fields value elsewhere in the
> code.
> 
> Fixes: CID 292440

What is the exact error? Is there a code flow, where one element does 
not get set. (The commit message would be incorrect if this is not the 
case.)

Lastly, this is imported from upstream. I created an issue upstream [1].

> Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> ---
>   grub-core/lib/zstd/zstd_decompress.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/grub-core/lib/zstd/zstd_decompress.c b/grub-core/lib/zstd/zstd_decompress.c
> index 711b5b6d7..e4b5670c2 100644
> --- a/grub-core/lib/zstd/zstd_decompress.c
> +++ b/grub-core/lib/zstd/zstd_decompress.c
> @@ -1325,7 +1325,7 @@ typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset
>   FORCE_INLINE_TEMPLATE seq_t
>   ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
>   {
> -    seq_t seq;
> +    seq_t seq = {0};
>       U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
>       U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
>       U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
> 

I once read, that compilers cannot warn you, if you miss setting an 
element if you initialize structures to 0 in the beginning.


Kind regards,

Paul


[1]: https://github.com/facebook/zstd/issues/2545


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
  2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
                   ` (117 preceding siblings ...)
  2021-03-02 19:37 ` [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round John Paul Adrian Glaubitz
@ 2021-03-18  8:58 ` Paul Menzel
  2021-03-22 15:50   ` Daniel Kiper
  118 siblings, 1 reply; 147+ messages in thread
From: Paul Menzel @ 2021-03-18  8:58 UTC (permalink / raw)
  To: Daniel Kiper, Darren Kenny
  Cc: 93sam, alexander.burmashev, chrco, chris.coulson, cjwatson,
	corsac, cperry, dja, eric.snowberg, ilya.okomin, ivansprundel,
	jan.setjeeilers, jaredz, javierm, jerecox, john.haxby,
	joseph.tartaro, julian.klode, kanth.ghatraju, km, konrad.wilk,
	mario.limonciello, mbenatto, mjg59, noamr, nyanko, pfsmorigo,
	phcoder, pjones, rhughes, sajacobu, teddy.reed, tf, u.bauer,
	xnox, grub-devel

Dear Darren, dear Darren,


Am 02.03.21 um 19:00 schrieb Daniel Kiper:

Thank you very much for finding and fixing all these issues, and 
coordinating the publication.

[…]

>   .../lib/gnulib-patches/fix-null-state-deref.patch  |  12 +
>   .../gnulib-patches/fix-regcomp-uninit-token.patch  |  15 +
>   .../gnulib-patches/fix-regexec-null-deref.patch    |  12 +
>   .../lib/gnulib-patches/fix-uninit-structure.patch  |  11 +
>   .../lib/gnulib-patches/fix-unused-value.patch      |  14 +
Just a small question, if all these fixes were sent and applied upstream.


Kind regards,

Paul


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 029/117] zstd: Initialize seq_t structure fully
  2021-03-18  8:50   ` Paul Menzel
@ 2021-03-18  9:37     ` Darren Kenny
  0 siblings, 0 replies; 147+ messages in thread
From: Darren Kenny @ 2021-03-18  9:37 UTC (permalink / raw)
  To: Paul Menzel, Daniel Kiper; +Cc: Nick Terrell, The development of GNU GRUB

Hi Paul,

On Thursday, 2021-03-18 at 09:50:00 +01, Paul Menzel wrote:
> Dear Darren, dear Daniel,
>
>
> Am 02.03.21 um 19:00 schrieb Daniel Kiper:
>> From: Darren Kenny <darren.kenny@oracle.com>
>> 
>> While many compilers will initialize this to zero, not all will,
>
> Which ones do not?

I have been working with C for a long time now, and there have been
compilers that don't initialize stack variables.

While many of the Linux compilers such as gcc and clang compilers often
do - depending on the optimization levels and building with debug or
not. (Debug code tends to be correctly zeroed out, but optimized doesn't
always)

I remember having to change a lot of GNOME C code being ported to
another platform, Solaris at the time, where that code always assumed
that it would be initialized to 0, and random things would happen
depending on what was on the stack.

The details of this are well documented and are a known security issue:

- CWE-457 (http://cwe.mitre.org/data/definitions/457.html)

>> so it is better to be sure that fields not being explicitly set are at known
>> values, and there is code that checks this fields value elsewhere in the
>> code.
>> 
>> Fixes: CID 292440
>
> What is the exact error? Is there a code flow, where one element does 
> not get set. (The commit message would be incorrect if this is not the 
> case.)

I can't honestly remember the details that Coverity had, but there was a
flow found by Coverity that did end up returning the value in seq
without touching all of the fields in the structure.

Looking through the code manually just now, I can see that seq.match is
never set during that code in ZSTD_decodeSequence(), so that is the most
likely cause of the error from Coverity.

All that it can do is report that it was not set before returning, it
cannot necessarily predict what will happen after that function returns
it, especially over time.

>
> Lastly, this is imported from upstream. I created an issue upstream [1].
>

Thanks, makes sense.

>> Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
>> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>> ---
>>   grub-core/lib/zstd/zstd_decompress.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/grub-core/lib/zstd/zstd_decompress.c b/grub-core/lib/zstd/zstd_decompress.c
>> index 711b5b6d7..e4b5670c2 100644
>> --- a/grub-core/lib/zstd/zstd_decompress.c
>> +++ b/grub-core/lib/zstd/zstd_decompress.c
>> @@ -1325,7 +1325,7 @@ typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset
>>   FORCE_INLINE_TEMPLATE seq_t
>>   ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
>>   {
>> -    seq_t seq;
>> +    seq_t seq = {0};
>>       U32 const llBits = seqState->stateLL.table[seqState->stateLL.state].nbAdditionalBits;
>>       U32 const mlBits = seqState->stateML.table[seqState->stateML.state].nbAdditionalBits;
>>       U32 const ofBits = seqState->stateOffb.table[seqState->stateOffb.state].nbAdditionalBits;
>> 
>
> I once read, that compilers cannot warn you, if you miss setting an 
> element if you initialize structures to 0 in the beginning.
>

That is true, since it has been initialized :)

But compilers won't always warn you either unless you ask them to, e.g.
gcc requires you to add the -Wuninitialized option, it isn't included in
-Wall (at lot aren't TBH, despite the name).

It is fine not to initialize while developing the code - if you want to
use that to catch such cases - but you should probably then also be
enabling every possible warning that a compiler may provide, maybe also
using some static code analysis (though compilers are improving a lot
here, e.g. in GCC 10) and most importantly fix them all before shipping
code :)

All to common is that people end up turning off the annoying warnings
rather than paying attention to them and resolving them.

Thanks,

Darren.

> Kind regards,
>
> Paul
>
>
> [1]: https://github.com/facebook/zstd/issues/2545


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper
  2021-03-18  8:38   ` John Paul Adrian Glaubitz
@ 2021-03-20 15:05     ` John Paul Adrian Glaubitz
  2021-03-20 15:06       ` John Paul Adrian Glaubitz
  2021-03-23 19:16     ` John Paul Adrian Glaubitz
  1 sibling, 1 reply; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-20 15:05 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: The development of GNU GRUB, Peter Jones, debian-ia64,
	Sergei Trofimovich, Jessica Clarke

Hello!

On 3/18/21 9:38 AM, John Paul Adrian Glaubitz wrote:
> This change broke GRUB on ia64 for me. It now fails to perform any basic commands:
> 
> Loading.: grub                                                              
> Starting: grub                                                              
> Welcome to GRUB!                                                                                                                                                                                                                                         
> error: unknown filesystem.
> Entering rescue mode...
> grub rescue> insmod ext2
> error: unknown filesystem.
> grub rescue> help
> Unknown command `help'.
> grub rescue> ?
> Unknown command `?'.
> grub rescue> linux
> Unknown command `linux'.
> grub rescue>

The problem seems that the module loader tries to load the modules from the address
mentioned in the PE header which has changed before this patch was introduced.

However, the modules are still located at the same address in memory which is why
the module loader can no longer find them.

For reference, here is a hex diff of core.efi for the working and non-working builds
(without and with the patch):

--- grub-working.txt	2021-03-20 15:45:43.788950935 +0100
+++ grub-broken.txt	2021-03-20 15:46:05.588885451 +0100
@@ -25,10 +25,10 @@
 00000180: 0000 0000 0000 0000 2e74 6578 7400 0000  .........text...
 00000190: 00e0 0100 0010 0000 00e0 0100 0010 0000  ................
 000001a0: 0000 0000 0000 0000 0000 0000 2000 0060  ............ ..`
-000001b0: 2e64 6174 6100 0000 e094 0100 00f0 0100  .data...........
-000001c0: e094 0100 00f0 0100 0000 0000 0000 0000  ................
+000001b0: 2e64 6174 6100 0000 00a0 0100 00f0 0100  .data...........
+000001c0: 00a0 0100 00f0 0100 0000 0000 0000 0000  ................
 000001d0: 0000 0000 4000 00c0 6d6f 6473 0000 0000  ....@...mods....
-000001e0: 206b 0000 e084 0300 206b 0000 e084 0300   k...... k......
+000001e0: 0060 0000 0090 0300 0060 0000 0090 0300  .`.......`......
 000001f0: 0000 0000 0000 0000 0000 0000 4000 00c0  ............@...
 00000200: 2e72 656c 6f63 0000 0010 0000 00f0 0300  .reloc..........
 00000210: 0010 0000 00f0 0300 0000 0000 0000 0000  ................

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper
  2021-03-20 15:05     ` John Paul Adrian Glaubitz
@ 2021-03-20 15:06       ` John Paul Adrian Glaubitz
  0 siblings, 0 replies; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-20 15:06 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: The development of GNU GRUB, Peter Jones, debian-ia64,
	Sergei Trofimovich, Jessica Clarke

On 3/20/21 4:05 PM, John Paul Adrian Glaubitz wrote:
> However, the modules are still located at the same address in memory which is why
> the module loader can no longer find them.

And the new address where the loader is looking for the modules is located at 0x39000
but the modules are still located at 0x384E0. Thus, mkimage should be patched to move
the modules to 39000 so that the loader can find them.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round
  2021-03-18  8:58 ` Paul Menzel
@ 2021-03-22 15:50   ` Daniel Kiper
  0 siblings, 0 replies; 147+ messages in thread
From: Daniel Kiper @ 2021-03-22 15:50 UTC (permalink / raw)
  To: Paul Menzel
  Cc: Daniel Kiper, Darren Kenny, 93sam, alexander.burmashev, chrco,
	chris.coulson, cjwatson, corsac, cperry, dja, eric.snowberg,
	ilya.okomin, ivansprundel, jan.setjeeilers, jaredz, javierm,
	jerecox, john.haxby, joseph.tartaro, julian.klode,
	kanth.ghatraju, km, konrad.wilk, mario.limonciello, mbenatto,
	mjg59, noamr, nyanko, pfsmorigo, phcoder, pjones, rhughes,
	sajacobu, teddy.reed, tf, u.bauer, xnox, grub-devel

On Thu, Mar 18, 2021 at 09:58:23AM +0100, Paul Menzel wrote:
> Dear Darren, dear Darren,
>
> Am 02.03.21 um 19:00 schrieb Daniel Kiper:
>
> Thank you very much for finding and fixing all these issues, and
> coordinating the publication.
>
> […]
>
> >   .../lib/gnulib-patches/fix-null-state-deref.patch  |  12 +
> >   .../gnulib-patches/fix-regcomp-uninit-token.patch  |  15 +
> >   .../gnulib-patches/fix-regexec-null-deref.patch    |  12 +
> >   .../lib/gnulib-patches/fix-uninit-structure.patch  |  11 +
> >   .../lib/gnulib-patches/fix-unused-value.patch      |  14 +
> Just a small question, if all these fixes were sent and applied upstream.

I am going to send all of these fixes upstream and bump the gnulib
version when they are applied or the issues are fixed in the other way.
Though after release. However, if you want to do it earlier go ahead.
Just keep me in the loop...

Daniel


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper
  2021-03-18  8:38   ` John Paul Adrian Glaubitz
  2021-03-20 15:05     ` John Paul Adrian Glaubitz
@ 2021-03-23 19:16     ` John Paul Adrian Glaubitz
  2021-03-23 19:35       ` Daniel Kiper
  1 sibling, 1 reply; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-23 19:16 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: The development of GNU GRUB, Peter Jones, debian-ia64,
	Sergei Trofimovich, Jessica Clarke

Hello!

On 3/18/21 9:38 AM, John Paul Adrian Glaubitz wrote:
> On 3/2/21 7:01 PM, Daniel Kiper wrote:
>> From: Peter Jones <pjones@redhat.com>
>>
>> Add a init_pe_section() helper function to setup PE sections. This makes
>> the code simpler and easier to read.
>>
>> Signed-off-by: Peter Jones <pjones@redhat.com>
>> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
>> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> 
> This change broke GRUB on ia64 for me. It now fails to perform any basic commands:

Any chance someone could have a look at this? As explained in the follow-up mails,
the problem is that the pointer pointing to the modules location in the core image
deviate from the actual modules location as the former was updated but the former
not.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper
  2021-03-23 19:16     ` John Paul Adrian Glaubitz
@ 2021-03-23 19:35       ` Daniel Kiper
  2021-03-23 20:32         ` John Paul Adrian Glaubitz
  0 siblings, 1 reply; 147+ messages in thread
From: Daniel Kiper @ 2021-03-23 19:35 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz
  Cc: The development of GNU GRUB, Peter Jones, debian-ia64,
	Sergei Trofimovich, Jessica Clarke

Hi Adrian,

On Tue, Mar 23, 2021 at 08:16:43PM +0100, John Paul Adrian Glaubitz wrote:
> Hello!
>
> On 3/18/21 9:38 AM, John Paul Adrian Glaubitz wrote:
> > On 3/2/21 7:01 PM, Daniel Kiper wrote:
> >> From: Peter Jones <pjones@redhat.com>
> >>
> >> Add a init_pe_section() helper function to setup PE sections. This makes
> >> the code simpler and easier to read.
> >>
> >> Signed-off-by: Peter Jones <pjones@redhat.com>
> >> Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
> >> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> >
> > This change broke GRUB on ia64 for me. It now fails to perform any basic commands:
>
> Any chance someone could have a look at this? As explained in the follow-up mails,
> the problem is that the pointer pointing to the modules location in the core image
> deviate from the actual modules location as the former was updated but the former
> not.

I chatted about that with Javier yesterday. He told me he will take
a look at the issue...

Daniel


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper
  2021-03-23 19:35       ` Daniel Kiper
@ 2021-03-23 20:32         ` John Paul Adrian Glaubitz
  0 siblings, 0 replies; 147+ messages in thread
From: John Paul Adrian Glaubitz @ 2021-03-23 20:32 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: The development of GNU GRUB, Peter Jones, debian-ia64,
	Sergei Trofimovich, Jessica Clarke

Hi Daniel!

On 3/23/21 8:35 PM, Daniel Kiper wrote:
>> Any chance someone could have a look at this? As explained in the follow-up mails,
>> the problem is that the pointer pointing to the modules location in the core image
>> deviate from the actual modules location as the former was updated but the former
>> not.
> 
> I chatted about that with Javier yesterday. He told me he will take
> a look at the issue...

Great, thanks.

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer - glaubitz@debian.org
`. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913



^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow
  2021-03-02 18:01 ` [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow Daniel Kiper
@ 2021-06-10 11:55   ` Paul Menzel
  2021-06-28 22:12     ` Paul Menzel
  2021-07-20 21:02     ` Chris Coulson
  0 siblings, 2 replies; 147+ messages in thread
From: Paul Menzel @ 2021-06-10 11:55 UTC (permalink / raw)
  To: Daniel Kiper, Chris Coulson, Alex Burmashev,
	Vladimir 'phcoder' Serbinenko, Daniel Kiper
  Cc: grub-devel

Dear Daniel, dear Chris,


Am 02.03.21 um 19:01 schrieb Daniel Kiper:
> From: Chris Coulson <chris.coulson@canonical.com>
> 
> grub_parser_split_cmdline() expands variable names present in the supplied
> command line in to their corresponding variable contents and uses a 1 kiB
> stack buffer for temporary storage without sufficient bounds checking. If
> the function is called with a command line that references a variable with
> a sufficiently large payload, it is possible to overflow the stack
> buffer via tab completion, corrupt the stack frame and potentially
> control execution.
> 
> Fixes: CVE-2020-27749
> 
> Reported-by: Chris Coulson <chris.coulson@canonical.com>
> Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
> Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> ---
>   grub-core/kern/parser.c | 110 +++++++++++++++++++++++++++++-------------------
>   1 file changed, 67 insertions(+), 43 deletions(-)
> 
> diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
> index e010eaa1f..6ab7aa427 100644
> --- a/grub-core/kern/parser.c
> +++ b/grub-core/kern/parser.c
> @@ -18,6 +18,7 @@
>    */
>   
>   #include <grub/parser.h>
> +#include <grub/buffer.h>
>   #include <grub/env.h>
>   #include <grub/misc.h>
>   #include <grub/mm.h>
> @@ -107,8 +108,8 @@ check_varstate (grub_parser_state_t s)
>   }
>   
>   
> -static void
> -add_var (char *varname, char **bp, char **vp,
> +static grub_err_t
> +add_var (grub_buffer_t varname, grub_buffer_t buf,
>   	 grub_parser_state_t state, grub_parser_state_t newstate)
>   {
>     const char *val;
> @@ -116,31 +117,41 @@ add_var (char *varname, char **bp, char **vp,
>     /* Check if a variable was being read in and the end of the name
>        was reached.  */
>     if (!(check_varstate (state) && !check_varstate (newstate)))
> -    return;
> +    return GRUB_ERR_NONE;
>   
> -  *((*vp)++) = '\0';
> -  val = grub_env_get (varname);
> -  *vp = varname;
> +  if (grub_buffer_append_char (varname, '\0') != GRUB_ERR_NONE)
> +    return grub_errno;
> +
> +  val = grub_env_get ((const char *) grub_buffer_peek_data (varname));
> +  grub_buffer_reset (varname);
>     if (!val)
> -    return;
> +    return GRUB_ERR_NONE;
>   
>     /* Insert the contents of the variable in the buffer.  */
> -  for (; *val; val++)
> -    *((*bp)++) = *val;
> +  return grub_buffer_append_data (buf, val, grub_strlen (val));
>   }
>   
> -static void
> -terminate_arg (char *buffer, char **bp, int *argc)
> +static grub_err_t
> +terminate_arg (grub_buffer_t buffer, int *argc)
>   {
> -  if (*bp != buffer && *((*bp) - 1) != '\0')
> -    {
> -      *((*bp)++) = '\0';
> -      (*argc)++;
> -    }
> +  grub_size_t unread = grub_buffer_get_unread_bytes (buffer);
> +
> +  if (unread == 0)
> +    return GRUB_ERR_NONE;
> +
> +  if (*(const char *) grub_buffer_peek_data_at (buffer, unread - 1) == '\0')
> +    return GRUB_ERR_NONE;
> +
> +  if (grub_buffer_append_char (buffer, '\0') != GRUB_ERR_NONE)
> +    return grub_errno;
> +
> +  (*argc)++;
> +
> +  return GRUB_ERR_NONE;
>   }
>   
>   static grub_err_t
> -process_char (char c, char *buffer, char **bp, char *varname, char **vp,
> +process_char (char c, grub_buffer_t buffer, grub_buffer_t varname,
>   	      grub_parser_state_t state, int *argc,
>   	      grub_parser_state_t *newstate)
>   {
> @@ -153,12 +164,13 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
>      * not describe the variable anymore, write the variable to
>      * the buffer.
>      */
> -  add_var (varname, bp, vp, state, *newstate);
> +  if (add_var (varname, buffer, state, *newstate) != GRUB_ERR_NONE)
> +    return grub_errno;
>   
>     if (check_varstate (*newstate))
>       {
>         if (use)
> -	*((*vp)++) = use;
> +        return grub_buffer_append_char (varname, use);
>       }
>     else if (*newstate == GRUB_PARSER_STATE_TEXT &&
>   	   state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
> @@ -167,10 +179,10 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
>          * Don't add more than one argument if multiple
>          * spaces are used.
>          */
> -      terminate_arg (buffer, bp, argc);
> +      return terminate_arg (buffer, argc);
>       }
>     else if (use)
> -    *((*bp)++) = use;
> +    return grub_buffer_append_char (buffer, use);
>   
>     return GRUB_ERR_NONE;
>   }
> @@ -181,19 +193,22 @@ grub_parser_split_cmdline (const char *cmdline,
>   			   int *argc, char ***argv)
>   {
>     grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
> -  /* XXX: Fixed size buffer, perhaps this buffer should be dynamically
> -     allocated.  */
> -  char buffer[1024];
> -  char *bp = buffer;
> +  grub_buffer_t buffer, varname;
>     char *rd = (char *) cmdline;
>     char *rp = rd;
> -  char varname[200];
> -  char *vp = varname;
> -  char *args;
>     int i;
>   
>     *argc = 0;
>     *argv = NULL;
> +
> +  buffer = grub_buffer_new (1024);
> +  if (buffer == NULL)
> +    return grub_errno;
> +
> +  varname = grub_buffer_new (200);
> +  if (varname == NULL)
> +    goto fail;
> +
>     do
>       {
>         if (rp == NULL || *rp == '\0')
> @@ -219,7 +234,7 @@ grub_parser_split_cmdline (const char *cmdline,
>   	{
>   	  grub_parser_state_t newstate;
>   
> -	  if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
> +	  if (process_char (*rp, buffer, varname, state, argc,
>   			    &newstate) != GRUB_ERR_NONE)
>   	    goto fail;
>   
> @@ -230,10 +245,12 @@ grub_parser_split_cmdline (const char *cmdline,
>   
>     /* A special case for when the last character was part of a
>        variable.  */
> -  add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
> +  if (add_var (varname, buffer, state, GRUB_PARSER_STATE_TEXT) != GRUB_ERR_NONE)
> +    goto fail;
>   
>     /* Ensure that the last argument is terminated. */
> -  terminate_arg (buffer, &bp, argc);
> +  if (terminate_arg (buffer, argc) != GRUB_ERR_NONE)
> +    goto fail;
>   
>     /* If there are no args, then we're done. */
>     if (!*argc)
> @@ -242,38 +259,45 @@ grub_parser_split_cmdline (const char *cmdline,
>         goto out;
>       }
>   
> -  /* Reserve memory for the return values.  */
> -  args = grub_malloc (bp - buffer);
> -  if (!args)
> -    goto fail;
> -  grub_memcpy (args, buffer, bp - buffer);
> -
>     *argv = grub_calloc (*argc + 1, sizeof (char *));
>     if (!*argv)
>       goto fail;
>   
>     /* The arguments are separated with 0's, setup argv so it points to
>        the right values.  */
> -  bp = args;
>     for (i = 0; i < *argc; i++)
>       {
> -      (*argv)[i] = bp;
> -      while (*bp)
> -	bp++;
> -      bp++;
> +      char *arg;
> +
> +      if (i > 0)
> +	{
> +	  if (grub_buffer_advance_read_pos (buffer, 1) != GRUB_ERR_NONE)
> +	    goto fail;
> +	}
> +
> +      arg = (char *) grub_buffer_peek_data (buffer);
> +      if (arg == NULL ||
> +	  grub_buffer_advance_read_pos (buffer, grub_strlen (arg)) != GRUB_ERR_NONE)
> +	goto fail;
> +
> +      (*argv)[i] = arg;
>       }
>   
> +  /* Keep memory for the return values. */
> +  grub_buffer_take_data (buffer);
> +
>     grub_errno = GRUB_ERR_NONE;
>   
>    out:
>     if (rd != cmdline)
>       grub_free (rd);
> +  grub_buffer_free (buffer);
> +  grub_buffer_free (varname);
>   
>     return grub_errno;
>   
>    fail:
>     grub_free (*argv);
> -  grub_free (args);
>     goto out;
>   }
>   

This commit causes a regresses. Building it as a coreboot payload with 
`-Os`, it crashes in QEMU. I am using Debian sid/unstable with GCC 10.2.

     $ gcc --version | head -1
     gcc (Debian 10.2.1-6) 10.2.1 20210110

Build the payload `default_payload.elf`.

     $ rm -rf build && mkdir build && cd build && ../configure 
CFLAGS=-O2 TARGET_CFLAGS=-Os --with-platform=coreboot 
--with-platform=coreboot --enable-boot-time --disable-werror && make -j4 
&& make default_payload.elf && cd ..

Clone coreboot, run `make menuconfig`, increase the ROM size to 2 MB and 
under *Payload* choose *Add a payload (An ELF executable payload)*, and 
select `default_payload.elf`. Run `make -j$(nproc)` and run the image in 
QEMU:

     $ qemu-system-i386 -enable-kvm -m 2G -bios build/coreboot.rom 
-serial stdio

Notice:

```
[…]
BS: BS_PAYLOAD_LOAD run times (exec / console): 44 / 12 ms
Jumping to boot code at 0x00009000(0x7ffa1000)
CPU Index 0 - APIC 0 Unexpected Exception:6 @ 10:00009016 - Halting
Code: 0 eflags: 00010002 cr2: 00000000
eax: 00000000 ebx: 7ffc39a4 ecx: 0001a9f8 edx: 000000ff
edi: 0000000b esi: 000001e4 ebp: 7ffc8fd8 esp: 7ffc8f7c

0x00008fd0:	00 00 00 00 00 00 00 00
0x00008fd8:	00 00 00 00 00 00 00 00
0x00008fe0:	00 00 00 00 00 00 00 00
0x00008fe8:	00 00 00 00 00 00 00 00
0x00008ff0:	00 00 00 00 00 00 00 00
0x00008ff8:	00 00 00 00 00 00 00 00
0x00009000:	52 52 68 f8 a9 01 00 6a
0x00009008:	0b e8 23 cd 00 00 83 c4
0x00009010:	10 a0 00 00 00 00 0f 0b
0x00009018:	51 51 68 0a aa 01 00 6a
0x00009020:	0b e8 0b cd 00 00 83 c4
0x00009028:	10 eb e6 90 bc f0 ff 07
0x00009030:	00 e9 64 d7 00 00 66 90
0x00009038:	02 b0 ad 1b 02 00 00 00
0x00009040:	fc 4f 52 e4 55 57 56 53
0x00009048:	83 ec 1c 8b 4c 24 30 8b
0x7ffc8ff8:	0x7ffc33e0
0x7ffc8ff4:	0xdeadbeef
0x7ffc8ff0:	0xdeadbeef
0x7ffc8fec:	0x7ffaa05f
0x7ffc8fe8:	0xdeadbeef
0x7ffc8fe4:	0xdeadbeef
0x7ffc8fe0:	0xdeadbeef
0x7ffc8fdc:	0x7ffaa05f
0x7ffc8fd8:	0x7ffdcfe8 <-ebp
0x7ffc8fd4:	0x7ffc9000
0x7ffc8fd0:	0x00000000
0x7ffc8fcc:	0x00000000
0x7ffc8fc8:	0x7ffc8ff0
0x7ffc8fc4:	0xdeadbeef
0x7ffc8fc0:	0xdeadbeef
0x7ffc8fbc:	0x7ffae54a
0x7ffc8fb8:	0x7ffc8fd8
0x7ffc8fb4:	0x0000000b
0x7ffc8fb0:	0x00000000
0x7ffc8fac:	0x7ffae55e
0x7ffc8fa8:	0x7ffc39a4
0x7ffc8fa4:	0x0000000b
0x7ffc8fa0:	0x000001b8
0x7ffc8f9c:	0x7ffae401
0x7ffc8f98:	0x7ffc3978
0x7ffc8f94:	0x18cd145c
0x7ffc8f90:	0x0000007b
0x7ffc8f8c:	0x7ffa1000
0x7ffc8f88:	0x00009000
0x7ffc8f84:	0x00000000
0x7ffc8f80:	0x7ffa1000
0x7ffc8f7c:	0x7ffb040d <-esp
```


Kind regards,

Paul


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow
  2021-06-10 11:55   ` Paul Menzel
@ 2021-06-28 22:12     ` Paul Menzel
  2021-07-20 21:02     ` Chris Coulson
  1 sibling, 0 replies; 147+ messages in thread
From: Paul Menzel @ 2021-06-28 22:12 UTC (permalink / raw)
  To: Daniel Kiper, Chris Coulson, Alex Burmashev,
	Vladimir 'phcoder' Serbinenko, Daniel Kiper
  Cc: grub-devel

Dear Daniel, dear Chris,


Am 10.06.21 um 13:55 schrieb Paul Menzel:

> Am 02.03.21 um 19:01 schrieb Daniel Kiper:
>> From: Chris Coulson <chris.coulson@canonical.com>
>>
>> grub_parser_split_cmdline() expands variable names present in the 
>> supplied
>> command line in to their corresponding variable contents and uses a 1 kiB
>> stack buffer for temporary storage without sufficient bounds checking. If
>> the function is called with a command line that references a variable 
>> with
>> a sufficiently large payload, it is possible to overflow the stack
>> buffer via tab completion, corrupt the stack frame and potentially
>> control execution.
>>
>> Fixes: CVE-2020-27749
>>
>> Reported-by: Chris Coulson <chris.coulson@canonical.com>
>> Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
>> Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
>> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>> ---
>>   grub-core/kern/parser.c | 110 +++++++++++++++++++++++++++++-------------------
>>   1 file changed, 67 insertions(+), 43 deletions(-)
>>
>> diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
>> index e010eaa1f..6ab7aa427 100644
>> --- a/grub-core/kern/parser.c
>> +++ b/grub-core/kern/parser.c
>> @@ -18,6 +18,7 @@
>>    */
>>   #include <grub/parser.h>
>> +#include <grub/buffer.h>
>>   #include <grub/env.h>
>>   #include <grub/misc.h>
>>   #include <grub/mm.h>
>> @@ -107,8 +108,8 @@ check_varstate (grub_parser_state_t s)
>>   }
>> -static void
>> -add_var (char *varname, char **bp, char **vp,
>> +static grub_err_t
>> +add_var (grub_buffer_t varname, grub_buffer_t buf,
>>        grub_parser_state_t state, grub_parser_state_t newstate)
>>   {
>>     const char *val;
>> @@ -116,31 +117,41 @@ add_var (char *varname, char **bp, char **vp,
>>     /* Check if a variable was being read in and the end of the name
>>        was reached.  */
>>     if (!(check_varstate (state) && !check_varstate (newstate)))
>> -    return;
>> +    return GRUB_ERR_NONE;
>> -  *((*vp)++) = '\0';
>> -  val = grub_env_get (varname);
>> -  *vp = varname;
>> +  if (grub_buffer_append_char (varname, '\0') != GRUB_ERR_NONE)
>> +    return grub_errno;
>> +
>> +  val = grub_env_get ((const char *) grub_buffer_peek_data (varname));
>> +  grub_buffer_reset (varname);
>>     if (!val)
>> -    return;
>> +    return GRUB_ERR_NONE;
>>     /* Insert the contents of the variable in the buffer.  */
>> -  for (; *val; val++)
>> -    *((*bp)++) = *val;
>> +  return grub_buffer_append_data (buf, val, grub_strlen (val));
>>   }
>> -static void
>> -terminate_arg (char *buffer, char **bp, int *argc)
>> +static grub_err_t
>> +terminate_arg (grub_buffer_t buffer, int *argc)
>>   {
>> -  if (*bp != buffer && *((*bp) - 1) != '\0')
>> -    {
>> -      *((*bp)++) = '\0';
>> -      (*argc)++;
>> -    }
>> +  grub_size_t unread = grub_buffer_get_unread_bytes (buffer);
>> +
>> +  if (unread == 0)
>> +    return GRUB_ERR_NONE;
>> +
>> +  if (*(const char *) grub_buffer_peek_data_at (buffer, unread - 1) 
>> == '\0')
>> +    return GRUB_ERR_NONE;
>> +
>> +  if (grub_buffer_append_char (buffer, '\0') != GRUB_ERR_NONE)
>> +    return grub_errno;
>> +
>> +  (*argc)++;
>> +
>> +  return GRUB_ERR_NONE;
>>   }
>>   static grub_err_t
>> -process_char (char c, char *buffer, char **bp, char *varname, char **vp,
>> +process_char (char c, grub_buffer_t buffer, grub_buffer_t varname,
>>             grub_parser_state_t state, int *argc,
>>             grub_parser_state_t *newstate)
>>   {
>> @@ -153,12 +164,13 @@ process_char (char c, char *buffer, char **bp, 
>> char *varname, char **vp,
>>      * not describe the variable anymore, write the variable to
>>      * the buffer.
>>      */
>> -  add_var (varname, bp, vp, state, *newstate);
>> +  if (add_var (varname, buffer, state, *newstate) != GRUB_ERR_NONE)
>> +    return grub_errno;
>>     if (check_varstate (*newstate))
>>       {
>>         if (use)
>> -    *((*vp)++) = use;
>> +        return grub_buffer_append_char (varname, use);
>>       }
>>     else if (*newstate == GRUB_PARSER_STATE_TEXT &&
>>          state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
>> @@ -167,10 +179,10 @@ process_char (char c, char *buffer, char **bp, 
>> char *varname, char **vp,
>>          * Don't add more than one argument if multiple
>>          * spaces are used.
>>          */
>> -      terminate_arg (buffer, bp, argc);
>> +      return terminate_arg (buffer, argc);
>>       }
>>     else if (use)
>> -    *((*bp)++) = use;
>> +    return grub_buffer_append_char (buffer, use);
>>     return GRUB_ERR_NONE;
>>   }
>> @@ -181,19 +193,22 @@ grub_parser_split_cmdline (const char *cmdline,
>>                  int *argc, char ***argv)
>>   {
>>     grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
>> -  /* XXX: Fixed size buffer, perhaps this buffer should be dynamically
>> -     allocated.  */
>> -  char buffer[1024];
>> -  char *bp = buffer;
>> +  grub_buffer_t buffer, varname;
>>     char *rd = (char *) cmdline;
>>     char *rp = rd;
>> -  char varname[200];
>> -  char *vp = varname;
>> -  char *args;
>>     int i;
>>     *argc = 0;
>>     *argv = NULL;
>> +
>> +  buffer = grub_buffer_new (1024);
>> +  if (buffer == NULL)
>> +    return grub_errno;
>> +
>> +  varname = grub_buffer_new (200);
>> +  if (varname == NULL)
>> +    goto fail;
>> +
>>     do
>>       {
>>         if (rp == NULL || *rp == '\0')
>> @@ -219,7 +234,7 @@ grub_parser_split_cmdline (const char *cmdline,
>>       {
>>         grub_parser_state_t newstate;
>> -      if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
>> +      if (process_char (*rp, buffer, varname, state, argc,
>>                   &newstate) != GRUB_ERR_NONE)
>>           goto fail;
>> @@ -230,10 +245,12 @@ grub_parser_split_cmdline (const char *cmdline,
>>     /* A special case for when the last character was part of a
>>        variable.  */
>> -  add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
>> +  if (add_var (varname, buffer, state, GRUB_PARSER_STATE_TEXT) != 
>> GRUB_ERR_NONE)
>> +    goto fail;
>>     /* Ensure that the last argument is terminated. */
>> -  terminate_arg (buffer, &bp, argc);
>> +  if (terminate_arg (buffer, argc) != GRUB_ERR_NONE)
>> +    goto fail;
>>     /* If there are no args, then we're done. */
>>     if (!*argc)
>> @@ -242,38 +259,45 @@ grub_parser_split_cmdline (const char *cmdline,
>>         goto out;
>>       }
>> -  /* Reserve memory for the return values.  */
>> -  args = grub_malloc (bp - buffer);
>> -  if (!args)
>> -    goto fail;
>> -  grub_memcpy (args, buffer, bp - buffer);
>> -
>>     *argv = grub_calloc (*argc + 1, sizeof (char *));
>>     if (!*argv)
>>       goto fail;
>>     /* The arguments are separated with 0's, setup argv so it points to
>>        the right values.  */
>> -  bp = args;
>>     for (i = 0; i < *argc; i++)
>>       {
>> -      (*argv)[i] = bp;
>> -      while (*bp)
>> -    bp++;
>> -      bp++;
>> +      char *arg;
>> +
>> +      if (i > 0)
>> +    {
>> +      if (grub_buffer_advance_read_pos (buffer, 1) != GRUB_ERR_NONE)
>> +        goto fail;
>> +    }
>> +
>> +      arg = (char *) grub_buffer_peek_data (buffer);
>> +      if (arg == NULL ||
>> +      grub_buffer_advance_read_pos (buffer, grub_strlen (arg)) != 
>> GRUB_ERR_NONE)
>> +    goto fail;
>> +
>> +      (*argv)[i] = arg;
>>       }
>> +  /* Keep memory for the return values. */
>> +  grub_buffer_take_data (buffer);
>> +
>>     grub_errno = GRUB_ERR_NONE;
>>    out:
>>     if (rd != cmdline)
>>       grub_free (rd);
>> +  grub_buffer_free (buffer);
>> +  grub_buffer_free (varname);
>>     return grub_errno;
>>    fail:
>>     grub_free (*argv);
>> -  grub_free (args);
>>     goto out;
>>   }
> 
> This commit causes a regresses. Building it as a coreboot payload with 
> `-Os`, it crashes in QEMU. I am using Debian sid/unstable with GCC 10.2.
> 
>      $ gcc --version | head -1
>      gcc (Debian 10.2.1-6) 10.2.1 20210110
> 
> Build the payload `default_payload.elf`.
> 
>      $ rm -rf build && mkdir build && cd build && ../configure 
> CFLAGS=-O2 TARGET_CFLAGS=-Os --with-platform=coreboot 
> --with-platform=coreboot --enable-boot-time --disable-werror && make -j4 
> && make default_payload.elf && cd ..
> 
> Clone coreboot, run `make menuconfig`, increase the ROM size to 2 MB and 
> under *Payload* choose *Add a payload (An ELF executable payload)*, and 
> select `default_payload.elf`. Run `make -j$(nproc)` and run the image in 
> QEMU:
> 
>      $ qemu-system-i386 -enable-kvm -m 2G -bios build/coreboot.rom -serial stdio
> 
> Notice:
> 
> ```
> […]
> BS: BS_PAYLOAD_LOAD run times (exec / console): 44 / 12 ms
> Jumping to boot code at 0x00009000(0x7ffa1000)
> CPU Index 0 - APIC 0 Unexpected Exception:6 @ 10:00009016 - Halting
> Code: 0 eflags: 00010002 cr2: 00000000
> eax: 00000000 ebx: 7ffc39a4 ecx: 0001a9f8 edx: 000000ff
> edi: 0000000b esi: 000001e4 ebp: 7ffc8fd8 esp: 7ffc8f7c
> 
> 0x00008fd0:    00 00 00 00 00 00 00 00
> 0x00008fd8:    00 00 00 00 00 00 00 00
> 0x00008fe0:    00 00 00 00 00 00 00 00
> 0x00008fe8:    00 00 00 00 00 00 00 00
> 0x00008ff0:    00 00 00 00 00 00 00 00
> 0x00008ff8:    00 00 00 00 00 00 00 00
> 0x00009000:    52 52 68 f8 a9 01 00 6a
> 0x00009008:    0b e8 23 cd 00 00 83 c4
> 0x00009010:    10 a0 00 00 00 00 0f 0b
> 0x00009018:    51 51 68 0a aa 01 00 6a
> 0x00009020:    0b e8 0b cd 00 00 83 c4
> 0x00009028:    10 eb e6 90 bc f0 ff 07
> 0x00009030:    00 e9 64 d7 00 00 66 90
> 0x00009038:    02 b0 ad 1b 02 00 00 00
> 0x00009040:    fc 4f 52 e4 55 57 56 53
> 0x00009048:    83 ec 1c 8b 4c 24 30 8b
> 0x7ffc8ff8:    0x7ffc33e0
> 0x7ffc8ff4:    0xdeadbeef
> 0x7ffc8ff0:    0xdeadbeef
> 0x7ffc8fec:    0x7ffaa05f
> 0x7ffc8fe8:    0xdeadbeef
> 0x7ffc8fe4:    0xdeadbeef
> 0x7ffc8fe0:    0xdeadbeef
> 0x7ffc8fdc:    0x7ffaa05f
> 0x7ffc8fd8:    0x7ffdcfe8 <-ebp
> 0x7ffc8fd4:    0x7ffc9000
> 0x7ffc8fd0:    0x00000000
> 0x7ffc8fcc:    0x00000000
> 0x7ffc8fc8:    0x7ffc8ff0
> 0x7ffc8fc4:    0xdeadbeef
> 0x7ffc8fc0:    0xdeadbeef
> 0x7ffc8fbc:    0x7ffae54a
> 0x7ffc8fb8:    0x7ffc8fd8
> 0x7ffc8fb4:    0x0000000b
> 0x7ffc8fb0:    0x00000000
> 0x7ffc8fac:    0x7ffae55e
> 0x7ffc8fa8:    0x7ffc39a4
> 0x7ffc8fa4:    0x0000000b
> 0x7ffc8fa0:    0x000001b8
> 0x7ffc8f9c:    0x7ffae401
> 0x7ffc8f98:    0x7ffc3978
> 0x7ffc8f94:    0x18cd145c
> 0x7ffc8f90:    0x0000007b
> 0x7ffc8f8c:    0x7ffa1000
> 0x7ffc8f88:    0x00009000
> 0x7ffc8f84:    0x00000000
> 0x7ffc8f80:    0x7ffa1000
> 0x7ffc8f7c:    0x7ffb040d <-esp
> ```

Just a gentle ping regarding this regression.


Kind regards,

Paul


^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow
  2021-06-10 11:55   ` Paul Menzel
  2021-06-28 22:12     ` Paul Menzel
@ 2021-07-20 21:02     ` Chris Coulson
  1 sibling, 0 replies; 147+ messages in thread
From: Chris Coulson @ 2021-07-20 21:02 UTC (permalink / raw)
  To: The development of GNU GRUB, Paul Menzel, Daniel Kiper


[-- Attachment #1.1: Type: text/plain, Size: 12502 bytes --]

Hi,

Sorry for taking a while to look at this.

On 10/06/2021 12:55, Paul Menzel wrote:
> Dear Daniel, dear Chris,
> 
> 
> Am 02.03.21 um 19:01 schrieb Daniel Kiper:
>> From: Chris Coulson <chris.coulson@canonical.com>
>>
>> grub_parser_split_cmdline() expands variable names present in the
>> supplied
>> command line in to their corresponding variable contents and uses a 1 kiB
>> stack buffer for temporary storage without sufficient bounds checking. If
>> the function is called with a command line that references a variable
>> with
>> a sufficiently large payload, it is possible to overflow the stack
>> buffer via tab completion, corrupt the stack frame and potentially
>> control execution.
>>
>> Fixes: CVE-2020-27749
>>
>> Reported-by: Chris Coulson <chris.coulson@canonical.com>
>> Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
>> Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
>> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>> ---
>>   grub-core/kern/parser.c | 110
>> +++++++++++++++++++++++++++++-------------------
>>   1 file changed, 67 insertions(+), 43 deletions(-)
>>
>> diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
>> index e010eaa1f..6ab7aa427 100644
>> --- a/grub-core/kern/parser.c
>> +++ b/grub-core/kern/parser.c
>> @@ -18,6 +18,7 @@
>>    */
>>     #include <grub/parser.h>
>> +#include <grub/buffer.h>
>>   #include <grub/env.h>
>>   #include <grub/misc.h>
>>   #include <grub/mm.h>
>> @@ -107,8 +108,8 @@ check_varstate (grub_parser_state_t s)
>>   }
>>     -static void
>> -add_var (char *varname, char **bp, char **vp,
>> +static grub_err_t
>> +add_var (grub_buffer_t varname, grub_buffer_t buf,
>>        grub_parser_state_t state, grub_parser_state_t newstate)
>>   {
>>     const char *val;
>> @@ -116,31 +117,41 @@ add_var (char *varname, char **bp, char **vp,
>>     /* Check if a variable was being read in and the end of the name
>>        was reached.  */
>>     if (!(check_varstate (state) && !check_varstate (newstate)))
>> -    return;
>> +    return GRUB_ERR_NONE;
>>   -  *((*vp)++) = '\0';
>> -  val = grub_env_get (varname);
>> -  *vp = varname;
>> +  if (grub_buffer_append_char (varname, '\0') != GRUB_ERR_NONE)
>> +    return grub_errno;
>> +
>> +  val = grub_env_get ((const char *) grub_buffer_peek_data (varname));
>> +  grub_buffer_reset (varname);
>>     if (!val)
>> -    return;
>> +    return GRUB_ERR_NONE;
>>       /* Insert the contents of the variable in the buffer.  */
>> -  for (; *val; val++)
>> -    *((*bp)++) = *val;
>> +  return grub_buffer_append_data (buf, val, grub_strlen (val));
>>   }
>>   -static void
>> -terminate_arg (char *buffer, char **bp, int *argc)
>> +static grub_err_t
>> +terminate_arg (grub_buffer_t buffer, int *argc)
>>   {
>> -  if (*bp != buffer && *((*bp) - 1) != '\0')
>> -    {
>> -      *((*bp)++) = '\0';
>> -      (*argc)++;
>> -    }
>> +  grub_size_t unread = grub_buffer_get_unread_bytes (buffer);
>> +
>> +  if (unread == 0)
>> +    return GRUB_ERR_NONE;
>> +
>> +  if (*(const char *) grub_buffer_peek_data_at (buffer, unread - 1)
>> == '\0')
>> +    return GRUB_ERR_NONE;
>> +
>> +  if (grub_buffer_append_char (buffer, '\0') != GRUB_ERR_NONE)
>> +    return grub_errno;
>> +
>> +  (*argc)++;
>> +
>> +  return GRUB_ERR_NONE;
>>   }
>>     static grub_err_t
>> -process_char (char c, char *buffer, char **bp, char *varname, char **vp,
>> +process_char (char c, grub_buffer_t buffer, grub_buffer_t varname,
>>             grub_parser_state_t state, int *argc,
>>             grub_parser_state_t *newstate)
>>   {
>> @@ -153,12 +164,13 @@ process_char (char c, char *buffer, char **bp,
>> char *varname, char **vp,
>>      * not describe the variable anymore, write the variable to
>>      * the buffer.
>>      */
>> -  add_var (varname, bp, vp, state, *newstate);
>> +  if (add_var (varname, buffer, state, *newstate) != GRUB_ERR_NONE)
>> +    return grub_errno;
>>       if (check_varstate (*newstate))
>>       {
>>         if (use)
>> -    *((*vp)++) = use;
>> +        return grub_buffer_append_char (varname, use);
>>       }
>>     else if (*newstate == GRUB_PARSER_STATE_TEXT &&
>>          state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
>> @@ -167,10 +179,10 @@ process_char (char c, char *buffer, char **bp,
>> char *varname, char **vp,
>>          * Don't add more than one argument if multiple
>>          * spaces are used.
>>          */
>> -      terminate_arg (buffer, bp, argc);
>> +      return terminate_arg (buffer, argc);
>>       }
>>     else if (use)
>> -    *((*bp)++) = use;
>> +    return grub_buffer_append_char (buffer, use);
>>       return GRUB_ERR_NONE;
>>   }
>> @@ -181,19 +193,22 @@ grub_parser_split_cmdline (const char *cmdline,
>>                  int *argc, char ***argv)
>>   {
>>     grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
>> -  /* XXX: Fixed size buffer, perhaps this buffer should be dynamically
>> -     allocated.  */
>> -  char buffer[1024];
>> -  char *bp = buffer;
>> +  grub_buffer_t buffer, varname;
>>     char *rd = (char *) cmdline;
>>     char *rp = rd;
>> -  char varname[200];
>> -  char *vp = varname;
>> -  char *args;
>>     int i;
>>       *argc = 0;
>>     *argv = NULL;
>> +
>> +  buffer = grub_buffer_new (1024);
>> +  if (buffer == NULL)
>> +    return grub_errno;
>> +
>> +  varname = grub_buffer_new (200);
>> +  if (varname == NULL)
>> +    goto fail;
>> +
>>     do
>>       {
>>         if (rp == NULL || *rp == '\0')
>> @@ -219,7 +234,7 @@ grub_parser_split_cmdline (const char *cmdline,
>>       {
>>         grub_parser_state_t newstate;
>>   -      if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
>> +      if (process_char (*rp, buffer, varname, state, argc,
>>                   &newstate) != GRUB_ERR_NONE)
>>           goto fail;
>>   @@ -230,10 +245,12 @@ grub_parser_split_cmdline (const char *cmdline,
>>       /* A special case for when the last character was part of a
>>        variable.  */
>> -  add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
>> +  if (add_var (varname, buffer, state, GRUB_PARSER_STATE_TEXT) !=
>> GRUB_ERR_NONE)
>> +    goto fail;
>>       /* Ensure that the last argument is terminated. */
>> -  terminate_arg (buffer, &bp, argc);
>> +  if (terminate_arg (buffer, argc) != GRUB_ERR_NONE)
>> +    goto fail;
>>       /* If there are no args, then we're done. */
>>     if (!*argc)
>> @@ -242,38 +259,45 @@ grub_parser_split_cmdline (const char *cmdline,
>>         goto out;
>>       }
>>   -  /* Reserve memory for the return values.  */
>> -  args = grub_malloc (bp - buffer);
>> -  if (!args)
>> -    goto fail;
>> -  grub_memcpy (args, buffer, bp - buffer);
>> -
>>     *argv = grub_calloc (*argc + 1, sizeof (char *));
>>     if (!*argv)
>>       goto fail;
>>       /* The arguments are separated with 0's, setup argv so it points to
>>        the right values.  */
>> -  bp = args;
>>     for (i = 0; i < *argc; i++)
>>       {
>> -      (*argv)[i] = bp;
>> -      while (*bp)
>> -    bp++;
>> -      bp++;
>> +      char *arg;
>> +
>> +      if (i > 0)
>> +    {
>> +      if (grub_buffer_advance_read_pos (buffer, 1) != GRUB_ERR_NONE)
>> +        goto fail;
>> +    }
>> +
>> +      arg = (char *) grub_buffer_peek_data (buffer);
>> +      if (arg == NULL ||
>> +      grub_buffer_advance_read_pos (buffer, grub_strlen (arg)) !=
>> GRUB_ERR_NONE)
>> +    goto fail;
>> +
>> +      (*argv)[i] = arg;
>>       }
>>   +  /* Keep memory for the return values. */
>> +  grub_buffer_take_data (buffer);
>> +
>>     grub_errno = GRUB_ERR_NONE;
>>      out:
>>     if (rd != cmdline)
>>       grub_free (rd);
>> +  grub_buffer_free (buffer);
>> +  grub_buffer_free (varname);
>>       return grub_errno;
>>      fail:
>>     grub_free (*argv);
>> -  grub_free (args);
>>     goto out;
>>   }
>>   
> 
> This commit causes a regresses. Building it as a coreboot payload with
> `-Os`, it crashes in QEMU. I am using Debian sid/unstable with GCC 10.2.
> 
>     $ gcc --version | head -1
>     gcc (Debian 10.2.1-6) 10.2.1 20210110
> 
> Build the payload `default_payload.elf`.
> 
>     $ rm -rf build && mkdir build && cd build && ../configure CFLAGS=-O2
> TARGET_CFLAGS=-Os --with-platform=coreboot --with-platform=coreboot
> --enable-boot-time --disable-werror && make -j4 && make
> default_payload.elf && cd ..
> 
> Clone coreboot, run `make menuconfig`, increase the ROM size to 2 MB and
> under *Payload* choose *Add a payload (An ELF executable payload)*, and
> select `default_payload.elf`. Run `make -j$(nproc)` and run the image in
> QEMU:
> 
>     $ qemu-system-i386 -enable-kvm -m 2G -bios build/coreboot.rom
> -serial stdio
> 
> Notice:
> 
> ```
> […]
> BS: BS_PAYLOAD_LOAD run times (exec / console): 44 / 12 ms
> Jumping to boot code at 0x00009000(0x7ffa1000)
> CPU Index 0 - APIC 0 Unexpected Exception:6 @ 10:00009016 - Halting
> Code: 0 eflags: 00010002 cr2: 00000000
> eax: 00000000 ebx: 7ffc39a4 ecx: 0001a9f8 edx: 000000ff
> edi: 0000000b esi: 000001e4 ebp: 7ffc8fd8 esp: 7ffc8f7c
> 
> 0x00008fd0:    00 00 00 00 00 00 00 00
> 0x00008fd8:    00 00 00 00 00 00 00 00
> 0x00008fe0:    00 00 00 00 00 00 00 00
> 0x00008fe8:    00 00 00 00 00 00 00 00
> 0x00008ff0:    00 00 00 00 00 00 00 00
> 0x00008ff8:    00 00 00 00 00 00 00 00
> 0x00009000:    52 52 68 f8 a9 01 00 6a
> 0x00009008:    0b e8 23 cd 00 00 83 c4
> 0x00009010:    10 a0 00 00 00 00 0f 0b
> 0x00009018:    51 51 68 0a aa 01 00 6a
> 0x00009020:    0b e8 0b cd 00 00 83 c4
> 0x00009028:    10 eb e6 90 bc f0 ff 07
> 0x00009030:    00 e9 64 d7 00 00 66 90
> 0x00009038:    02 b0 ad 1b 02 00 00 00
> 0x00009040:    fc 4f 52 e4 55 57 56 53
> 0x00009048:    83 ec 1c 8b 4c 24 30 8b
> 0x7ffc8ff8:    0x7ffc33e0
> 0x7ffc8ff4:    0xdeadbeef
> 0x7ffc8ff0:    0xdeadbeef
> 0x7ffc8fec:    0x7ffaa05f
> 0x7ffc8fe8:    0xdeadbeef
> 0x7ffc8fe4:    0xdeadbeef
> 0x7ffc8fe0:    0xdeadbeef
> 0x7ffc8fdc:    0x7ffaa05f
> 0x7ffc8fd8:    0x7ffdcfe8 <-ebp
> 0x7ffc8fd4:    0x7ffc9000
> 0x7ffc8fd0:    0x00000000
> 0x7ffc8fcc:    0x00000000
> 0x7ffc8fc8:    0x7ffc8ff0
> 0x7ffc8fc4:    0xdeadbeef
> 0x7ffc8fc0:    0xdeadbeef
> 0x7ffc8fbc:    0x7ffae54a
> 0x7ffc8fb8:    0x7ffc8fd8
> 0x7ffc8fb4:    0x0000000b
> 0x7ffc8fb0:    0x00000000
> 0x7ffc8fac:    0x7ffae55e
> 0x7ffc8fa8:    0x7ffc39a4
> 0x7ffc8fa4:    0x0000000b
> 0x7ffc8fa0:    0x000001b8
> 0x7ffc8f9c:    0x7ffae401
> 0x7ffc8f98:    0x7ffc3978
> 0x7ffc8f94:    0x18cd145c
> 0x7ffc8f90:    0x0000007b
> 0x7ffc8f8c:    0x7ffa1000
> 0x7ffc8f88:    0x00009000
> 0x7ffc8f84:    0x00000000
> 0x7ffc8f80:    0x7ffa1000
> 0x7ffc8f7c:    0x7ffb040d <-esp
> ```
> 
I could reproduce this issue but it's a bit of a pain to debug. I had a
look at some of the coreboot documentation, but I'm not sure if there's
a nice way to debug issues like this.

This is just speculation, but one thing I've noticed that happens with
this patch is that gcc now emits a .text.unlikely section containing
part of terminate_arg when compiling grub-core/kern/parser.c. If I pass
-fno-reorder-functions to gcc, then this code gets emitted to the .text
section instead and the resulting grub binary seems to load fine. This
might suggest that perhaps this code is getting omitted from the final
binary, but I'm not sure yet how that would happen.

Cheers
- Chris

> 
> Kind regards,
> 
> Paul
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 147+ messages in thread

end of thread, other threads:[~2021-07-20 21:03 UTC | newest]

Thread overview: 147+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-02 18:00 [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 001/117] verifiers: Move verifiers API to kernel image Daniel Kiper
2021-03-18  1:22   ` Colin Watson
2021-03-18  7:04     ` Michael Chang
2021-03-02 18:00 ` [SECURITY PATCH 002/117] efi: Move the shim_lock verifier to the GRUB core Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 003/117] kern: Add lockdown support Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 004/117] kern/lockdown: Set a variable if the GRUB is locked down Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 005/117] efi: Lockdown the GRUB when the UEFI Secure Boot is enabled Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 006/117] efi: Use grub_is_lockdown() instead of hardcoding a disabled modules list Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 007/117] acpi: Don't register the acpi command when locked down Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 008/117] mmap: Don't register cutmem and badram commands when lockdown is enforced Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 009/117] commands: Restrict commands that can load BIOS or DT blobs when locked down Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 010/117] commands/setpci: Restrict setpci command " Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 011/117] commands/hdparm: Restrict hdparm " Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 012/117] gdb: Restrict GDB access " Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 013/117] loader/xnu: Don't allow loading extension and packages " Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 014/117] docs: Document the cutmem command Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 015/117] dl: Only allow unloading modules that are not dependencies Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 016/117] usb: Avoid possible out-of-bound accesses caused by malicious devices Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 017/117] mmap: Fix memory leak when iterating over mapped memory Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 018/117] net/net: Fix possible dereference to of a NULL pointer Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 019/117] net/tftp: Fix dangling memory pointer Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 020/117] kern/parser: Fix resource leak if argc == 0 Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 021/117] kern/efi: Fix memory leak on failure Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 022/117] kern/efi/mm: Fix possible NULL pointer dereference Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 023/117] gnulib/regexec: Resolve unused variable Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 024/117] gnulib/regcomp: Fix uninitialized token structure Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 025/117] gnulib/argp-help: Fix dereference of a possibly NULL state Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 026/117] gnulib/regexec: Fix possible null-dereference Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 027/117] gnulib/regcomp: Fix uninitialized re_token Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 028/117] io/lzopio: Resolve unnecessary self-assignment errors Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 029/117] zstd: Initialize seq_t structure fully Daniel Kiper
2021-03-18  8:50   ` Paul Menzel
2021-03-18  9:37     ` Darren Kenny
2021-03-02 18:00 ` [SECURITY PATCH 030/117] kern/partition: Check for NULL before dereferencing input string Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 031/117] disk/ldm: Make sure comp data is freed before exiting from make_vg() Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 032/117] disk/ldm: If failed then free vg variable too Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 033/117] disk/ldm: Fix memory leak on uninserted lv references Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 034/117] disk/cryptodisk: Fix potential integer overflow Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 035/117] hfsplus: Check that the volume name length is valid Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 036/117] zfs: Fix possible negative shift operation Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 037/117] zfs: Fix resource leaks while constructing path Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 038/117] zfs: Fix possible integer overflows Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 039/117] zfsinfo: Correct a check for error allocating memory Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 040/117] affs: Fix memory leaks Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 041/117] libgcrypt/mpi: Fix possible unintended sign extension Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 042/117] libgcrypt/mpi: Fix possible NULL dereference Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 043/117] syslinux: Fix memory leak while parsing Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 044/117] normal/completion: Fix leaking of memory when processing a completion Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 045/117] commands/hashsum: Fix a memory leak Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 046/117] commands/probe: Fix a resource leak when probing disks Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 047/117] video/efi_gop: Remove unnecessary return value of grub_video_gop_fill_mode_info() Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 048/117] video/fb/fbfill: Fix potential integer overflow Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 049/117] video/fb/video_fb: Fix multiple integer overflows Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 050/117] video/fb/video_fb: Fix possible integer overflow Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 051/117] video/readers/jpeg: Test for an invalid next marker reference from a jpeg file Daniel Kiper
2021-03-02 18:00 ` [SECURITY PATCH 052/117] gfxmenu/gui_list: Remove code that coverity is flagging as dead Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 053/117] loader/bsd: Check for NULL arg up-front Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 054/117] loader/xnu: Fix memory leak Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 055/117] loader/xnu: Free driverkey data when an error is detected in grub_xnu_writetree_toheap() Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 056/117] loader/xnu: Check if pointer is NULL before using it Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 057/117] util/grub-install: Fix NULL pointer dereferences Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 058/117] util/grub-editenv: Fix incorrect casting of a signed value Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 059/117] util/glue-efi: Fix incorrect use of a possibly negative value Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 060/117] script/execute: Fix NULL dereference in grub_script_execute_cmdline() Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 061/117] commands/ls: Require device_name is not NULL before printing Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 062/117] script/execute: Avoid crash when using "$#" outside a function scope Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 063/117] lib/arg: Block repeated short options that require an argument Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 064/117] script/execute: Don't crash on a "for" loop with no items Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 065/117] commands/menuentry: Fix quoting in setparams_prefix() Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 066/117] kern/misc: Always set *end in grub_strtoull() Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 067/117] video/readers/jpeg: Catch files with unsupported quantization or Huffman tables Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 068/117] video/readers/jpeg: Catch OOB reads/writes in grub_jpeg_decode_du() Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 069/117] video/readers/jpeg: Don't decode data before start of stream Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 070/117] term/gfxterm: Don't set up a font with glyphs that are too big Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 071/117] fs/fshelp: Catch impermissibly large block sizes in read helper Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 072/117] fs/hfsplus: Don't fetch a key beyond the end of the node Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 073/117] fs/hfsplus: Don't use uninitialized data on corrupt filesystems Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 074/117] fs/hfs: Disable under lockdown Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 075/117] fs/sfs: Fix over-read of root object name Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 076/117] fs/jfs: Do not move to leaf level if name length is negative Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 077/117] fs/jfs: Limit the extents that getblk() can consider Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 078/117] fs/jfs: Catch infinite recursion Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 079/117] fs/nilfs2: Reject too-large keys Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 080/117] fs/nilfs2: Don't search children if provided number is too large Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 081/117] fs/nilfs2: Properly bail on errors in grub_nilfs2_btree_node_lookup() Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 082/117] io/gzio: Bail if gzio->tl/td is NULL Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 083/117] io/gzio: Add init_dynamic_block() clean up if unpacking codes fails Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 084/117] io/gzio: Catch missing values in huft_build() and bail Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 085/117] io/gzio: Zero gzio->tl/td in init_dynamic_block() if huft_build() fails Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 086/117] disk/lvm: Don't go beyond the end of the data we read from disk Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 087/117] disk/lvm: Don't blast past the end of the circular metadata buffer Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 088/117] disk/lvm: Bail on missing PV list Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 089/117] disk/lvm: Do not crash if an expected string is not found Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 090/117] disk/lvm: Do not overread metadata Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 091/117] disk/lvm: Sanitize rlocn->offset to prevent wild read Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 092/117] disk/lvm: Do not allow a LV to be it's own segment's node's LV Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 093/117] fs/btrfs: Validate the number of stripes/parities in RAID5/6 Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 094/117] fs/btrfs: Squash some uninitialized reads Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 095/117] kern/parser: Fix a memory leak Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 096/117] kern/parser: Introduce process_char() helper Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 097/117] kern/parser: Introduce terminate_arg() helper Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 098/117] kern/parser: Refactor grub_parser_split_cmdline() cleanup Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 099/117] kern/buffer: Add variable sized heap buffer Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 100/117] kern/parser: Fix a stack buffer overflow Daniel Kiper
2021-06-10 11:55   ` Paul Menzel
2021-06-28 22:12     ` Paul Menzel
2021-07-20 21:02     ` Chris Coulson
2021-03-02 18:01 ` [SECURITY PATCH 101/117] kern/efi: Add initial stack protector implementation Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 102/117] util/mkimage: Remove unused code to add BSS section Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 103/117] util/mkimage: Use grub_host_to_target32() instead of grub_cpu_to_le32() Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 104/117] util/mkimage: Always use grub_host_to_target32() to initialize PE stack and heap stuff Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 105/117] util/mkimage: Unify more of the PE32 and PE32+ header set-up Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 106/117] util/mkimage: Reorder PE optional header fields set-up Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 107/117] util/mkimage: Improve data_size value calculation Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 108/117] util/mkimage: Refactor section setup to use a helper Daniel Kiper
2021-03-18  8:38   ` John Paul Adrian Glaubitz
2021-03-20 15:05     ` John Paul Adrian Glaubitz
2021-03-20 15:06       ` John Paul Adrian Glaubitz
2021-03-23 19:16     ` John Paul Adrian Glaubitz
2021-03-23 19:35       ` Daniel Kiper
2021-03-23 20:32         ` John Paul Adrian Glaubitz
2021-03-02 18:01 ` [SECURITY PATCH 109/117] util/mkimage: Add an option to import SBAT metadata into a .sbat section Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 110/117] grub-install-common: Add --sbat option Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 111/117] shim_lock: Only skip loading shim_lock verifier with explicit consent Daniel Kiper
2021-03-02 18:01 ` [SECURITY PATCH 112/117] kern/misc: Split parse_printf_args() into format parsing and va_list handling Daniel Kiper
2021-03-02 18:02 ` [SECURITY PATCH 113/117] kern/misc: Add STRING type for internal printf() format handling Daniel Kiper
2021-03-02 18:02 ` [SECURITY PATCH 114/117] kern/misc: Add function to check printf() format against expected format Daniel Kiper
2021-03-18  1:30   ` Colin Watson
2021-03-02 18:02 ` [SECURITY PATCH 115/117] gfxmenu/gui: Check printf() format in the gui_progress_bar and gui_label Daniel Kiper
2021-03-02 18:02 ` [SECURITY PATCH 116/117] templates: Disable the os-prober by default Daniel Kiper
2021-03-02 21:49   ` Didier Spaier
2021-03-03 13:13     ` Daniel Kiper
2021-03-03 17:28       ` Lennart Sorensen
2021-03-03 18:43       ` John Paul Adrian Glaubitz
2021-03-03 19:05         ` Lennart Sorensen
2021-03-03 19:11           ` Didier Spaier
2021-03-03 19:38         ` Daniel Kiper
2021-03-03 20:13           ` John Paul Adrian Glaubitz
2021-03-02 18:02 ` [SECURITY PATCH 117/117] kern/mm: Fix grub_debug_calloc() compilation error Daniel Kiper
2021-03-02 19:37 ` [SECURITY PATCH 000/117] Multiple GRUB2 vulnerabilities - 2021/03/02 round John Paul Adrian Glaubitz
2021-03-02 20:00   ` Bruce Dubbs
2021-03-02 20:49   ` Daniel Kiper
2021-03-09 15:57     ` Neal Gompa
2021-03-09 16:58       ` Daniel Kiper
2021-03-18  8:58 ` Paul Menzel
2021-03-22 15:50   ` Daniel Kiper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.