Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package grub2 for openSUSE:Factory checked 
in at 2022-06-09 14:09:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/grub2 (Old)
 and      /work/SRC/openSUSE:Factory/.grub2.new.1548 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "grub2"

Thu Jun  9 14:09:19 2022 rev:268 rq:981229 version:2.06

Changes:
--------
--- /work/SRC/openSUSE:Factory/grub2/grub2.changes      2022-06-03 
14:15:15.085206168 +0200
+++ /work/SRC/openSUSE:Factory/.grub2.new.1548/grub2.changes    2022-06-09 
14:09:24.364336047 +0200
@@ -1,0 +2,46 @@
+Tue May 31 04:44:18 UTC 2022 - Michael Chang <mch...@suse.com>
+
+- Security fixes and hardenings for boothole 3 / boothole 2022 (bsc#1198581)
+  * 0001-video-Remove-trailing-whitespaces.patch
+  * 0002-loader-efi-chainloader-Simplify-the-loader-state.patch
+  * 0003-commands-boot-Add-API-to-pass-context-to-loader.patch
+- Fix CVE-2022-28736 (bsc#1198496)
+  * 0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch
+- Fix CVE-2022-28735 (bsc#1198495)
+  * 0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
+  * 0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
+  * 0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
+  * 0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch
+- Fix CVE-2021-3695 (bsc#1191184)
+  * 0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
+- Fix CVE-2021-3696 (bsc#1191185)
+  * 0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
+  * 0011-video-readers-png-Sanity-check-some-huffman-codes.patch
+  * 0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
+  * 0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
+  * 0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
+- Fix CVE-2021-3697 (bsc#1191186)
+  * 0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
+  * 0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
+- Fix CVE-2022-28733 (bsc#1198460)
+  * 0017-net-ip-Do-IP-fragment-maths-safely.patch
+  * 0018-net-netbuff-Block-overly-large-netbuff-allocs.patch
+  * 0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
+  * 0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
+  * 0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
+  * 0022-net-tftp-Avoid-a-trivial-UAF.patch
+  * 0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
+- Fix CVE-2022-28734 (bsc#1198493)
+  * 0024-net-http-Fix-OOB-write-for-split-http-headers.patch
+- Fix CVE-2022-28734 (bsc#1198493)
+  * 0025-net-http-Error-out-on-headers-with-LF-without-CR.patch
+  * 0026-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
+  * 0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
+  * 0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
+  * 0029-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
+  * 0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
+  * 0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
+  * 0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch
+- Bump grub's SBAT generation to 2
+
+-------------------------------------------------------------------

New:
----
  0001-video-Remove-trailing-whitespaces.patch
  0002-loader-efi-chainloader-Simplify-the-loader-state.patch
  0003-commands-boot-Add-API-to-pass-context-to-loader.patch
  0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch
  0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
  0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
  0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
  0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch
  0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
  0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
  0011-video-readers-png-Sanity-check-some-huffman-codes.patch
  0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
  0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
  0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
  0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
  0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
  0017-net-ip-Do-IP-fragment-maths-safely.patch
  0018-net-netbuff-Block-overly-large-netbuff-allocs.patch
  0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
  0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
  0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
  0022-net-tftp-Avoid-a-trivial-UAF.patch
  0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
  0024-net-http-Fix-OOB-write-for-split-http-headers.patch
  0025-net-http-Error-out-on-headers-with-LF-without-CR.patch
  0026-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
  0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
  0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
  0029-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
  0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
  0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
  0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ grub2.spec ++++++
--- /var/tmp/diff_new_pack.k08Enp/_old  2022-06-09 14:09:27.224339881 +0200
+++ /var/tmp/diff_new_pack.k08Enp/_new  2022-06-09 14:09:27.228339887 +0200
@@ -22,7 +22,7 @@
 %if %{defined sbat_distro}
 # SBAT metadata
 %define sbat_generation 1
-%define sbat_generation_grub 1
+%define sbat_generation_grub 2
 %else
 %{error please define sbat_distro, sbat_distro_summary and sbat_distro_url}
 %endif
@@ -375,6 +375,38 @@
 Patch850:       0001-Fix-infinite-boot-loop-on-headless-system-in-qemu.patch
 Patch851:       0001-libc-config-merge-from-glibc.patch
 Patch852:       0001-ofdisk-improve-boot-time-by-lookup-boot-disk-first.patch
+Patch853:       0001-video-Remove-trailing-whitespaces.patch
+Patch854:       0002-loader-efi-chainloader-Simplify-the-loader-state.patch
+Patch855:       0003-commands-boot-Add-API-to-pass-context-to-loader.patch
+Patch856:       0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch
+Patch857:       0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
+Patch858:       0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
+Patch859:       0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
+Patch860:       0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch
+Patch861:       0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
+Patch862:       0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
+Patch863:       0011-video-readers-png-Sanity-check-some-huffman-codes.patch
+Patch864:       0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
+Patch865:       0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
+Patch866:       0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
+Patch867:       0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
+Patch868:       0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
+Patch869:       0017-net-ip-Do-IP-fragment-maths-safely.patch
+Patch870:       0018-net-netbuff-Block-overly-large-netbuff-allocs.patch
+Patch871:       0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
+Patch872:       0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
+Patch873:       0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
+Patch874:       0022-net-tftp-Avoid-a-trivial-UAF.patch
+Patch875:       0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
+Patch876:       0024-net-http-Fix-OOB-write-for-split-http-headers.patch
+Patch877:       0025-net-http-Error-out-on-headers-with-LF-without-CR.patch
+Patch878:       0026-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
+Patch879:       0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
+Patch880:       0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
+Patch881:       0029-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
+Patch882:       0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
+Patch883:       0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
+Patch884:       0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch
 
 Requires:       gettext-runtime
 %if 0%{?suse_version} >= 1140

++++++ 0001-video-Remove-trailing-whitespaces.patch ++++++
++++ 687 lines (skipped)

++++++ 0002-loader-efi-chainloader-Simplify-the-loader-state.patch ++++++
>From c111176648717645284865e15d7c6713cf29e982 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coul...@canonical.com>
Date: Tue, 5 Apr 2022 10:02:04 +0100
Subject: [PATCH 02/32] loader/efi/chainloader: Simplify the loader state

The chainloader command retains the source buffer and device path passed
to LoadImage(), requiring the unload hook passed to grub_loader_set() to
free them. It isn't required to retain this state though - they aren't
required by StartImage() or anything else in the boot hook, so clean them
up before grub_cmd_chainloader() finishes.

Signed-off-by: Chris Coulson <chris.coul...@canonical.com>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/loader/efi/chainloader.c | 37 ++++++++++++++++--------------
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/grub-core/loader/efi/chainloader.c 
b/grub-core/loader/efi/chainloader.c
index 625f1d26da..1ec09a166c 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -53,12 +53,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 static grub_dl_t my_mod;
 
-static grub_efi_physical_address_t address;
-static grub_efi_uintn_t pages;
 static grub_ssize_t fsize;
-static grub_efi_device_path_t *file_path;
 static grub_efi_handle_t image_handle;
-static grub_efi_char16_t *cmdline;
 static grub_ssize_t cmdline_len;
 static grub_efi_handle_t dev_handle;
 
@@ -70,16 +66,16 @@ static grub_efi_status_t (*entry_point) (grub_efi_handle_t 
image_handle,  grub_e
 static grub_err_t
 grub_chainloader_unload (void)
 {
+  grub_efi_loaded_image_t *loaded_image;
   grub_efi_boot_services_t *b;
 
+  loaded_image = grub_efi_get_loaded_image (image_handle);
+  if (loaded_image != NULL)
+    grub_free (loaded_image->load_options);
+
   b = grub_efi_system_table->boot_services;
   efi_call_1 (b->unload_image, image_handle);
-  efi_call_2 (b->free_pages, address, pages);
 
-  grub_free (file_path);
-  grub_free (cmdline);
-  cmdline = 0;
-  file_path = 0;
   dev_handle = 0;
 
   grub_dl_unref (my_mod);
@@ -158,7 +154,7 @@ make_file_path (grub_efi_device_path_t *dp, const char 
*filename)
   char *dir_start;
   char *dir_end;
   grub_size_t size;
-  grub_efi_device_path_t *d;
+  grub_efi_device_path_t *d, *file_path;
 
   dir_start = grub_strchr (filename, ')');
   if (! dir_start)
@@ -641,10 +637,13 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
   grub_efi_status_t status;
   grub_efi_boot_services_t *b;
   grub_device_t dev = 0;
-  grub_efi_device_path_t *dp = 0;
+  grub_efi_device_path_t *dp = NULL, *file_path = NULL;
   grub_efi_loaded_image_t *loaded_image;
   char *filename;
   void *boot_image = 0;
+  grub_efi_physical_address_t address = 0;
+  grub_efi_uintn_t pages = 0;
+  grub_efi_char16_t *cmdline = NULL;
 
   if (argc == 0)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -652,10 +651,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
 
   grub_dl_ref (my_mod);
 
-  /* Initialize some global variables.  */
-  address = 0;
-  image_handle = 0;
-  file_path = 0;
   dev_handle = 0;
 
   b = grub_efi_system_table->boot_services;
@@ -857,6 +852,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
   grub_file_close (file);
   grub_device_close (dev);
 
+  /* We're finished with the source image buffer and file path now. */
+  efi_call_2 (b->free_pages, address, pages);
+  grub_free (file_path);
+
   grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
   return 0;
 
@@ -868,13 +867,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
   if (file)
     grub_file_close (file);
 
+  grub_free (cmdline);
   grub_free (file_path);
 
   if (address)
     efi_call_2 (b->free_pages, address, pages);
 
-  if (cmdline)
-    grub_free (cmdline);
+  if (image_handle != NULL)
+    {
+      efi_call_1 (b->unload_image, image_handle);
+      image_handle = NULL;
+    }
 
   grub_dl_unref (my_mod);
 
-- 
2.34.1


++++++ 0003-commands-boot-Add-API-to-pass-context-to-loader.patch ++++++
>From 8bb57923d39f00b6f850cf6138ff5973cfd0d25f Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coul...@canonical.com>
Date: Tue, 5 Apr 2022 10:58:28 +0100
Subject: [PATCH 03/32] commands/boot: Add API to pass context to loader

Loaders rely on global variables for saving context which is consumed
in the boot hook and freed in the unload hook. In the case where a loader
command is executed twice, calling grub_loader_set() a second time executes
the unload hook, but in some cases this runs when the loader's global
context has already been updated, resulting in the updated context being
freed and potential use-after-free bugs when the boot hook is subsequently
called.

This adds a new API, grub_loader_set_ex(), which allows a loader to specify
context that is passed to its boot and unload hooks. This is an alternative
to requiring that loaders call grub_loader_unset() before mutating their
global context.

Signed-off-by: Chris Coulson <chris.coul...@canonical.com>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/commands/boot.c | 66 ++++++++++++++++++++++++++++++++++-----
 include/grub/loader.h     |  5 +++
 2 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c
index bbca81e947..61514788e2 100644
--- a/grub-core/commands/boot.c
+++ b/grub-core/commands/boot.c
@@ -27,10 +27,20 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-static grub_err_t (*grub_loader_boot_func) (void);
-static grub_err_t (*grub_loader_unload_func) (void);
+static grub_err_t (*grub_loader_boot_func) (void *context);
+static grub_err_t (*grub_loader_unload_func) (void *context);
+static void *grub_loader_context;
 static int grub_loader_flags;
 
+struct grub_simple_loader_hooks
+{
+  grub_err_t (*boot) (void);
+  grub_err_t (*unload) (void);
+};
+
+/* Don't heap allocate this to avoid making grub_loader_set() fallible. */
+static struct grub_simple_loader_hooks simple_loader_hooks;
+
 struct grub_preboot
 {
   grub_err_t (*preboot_func) (int);
@@ -44,6 +54,29 @@ static int grub_loader_loaded;
 static struct grub_preboot *preboots_head = 0,
   *preboots_tail = 0;
 
+static grub_err_t
+grub_simple_boot_hook (void *context)
+{
+  struct grub_simple_loader_hooks *hooks;
+
+  hooks = (struct grub_simple_loader_hooks *) context;
+  return hooks->boot ();
+}
+
+static grub_err_t
+grub_simple_unload_hook (void *context)
+{
+  struct grub_simple_loader_hooks *hooks;
+  grub_err_t ret;
+
+  hooks = (struct grub_simple_loader_hooks *) context;
+
+  ret = hooks->unload ();
+  grub_memset (hooks, 0, sizeof (*hooks));
+
+  return ret;
+}
+
 int
 grub_loader_is_loaded (void)
 {
@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot 
*hnd)
 }
 
 void
-grub_loader_set (grub_err_t (*boot) (void),
-                grub_err_t (*unload) (void),
-                int flags)
+grub_loader_set_ex (grub_err_t (*boot) (void *context),
+                   grub_err_t (*unload) (void *context),
+                   void *context,
+                   int flags)
 {
   if (grub_loader_loaded && grub_loader_unload_func)
-    grub_loader_unload_func ();
+    grub_loader_unload_func (grub_loader_context);
 
   grub_loader_boot_func = boot;
   grub_loader_unload_func = unload;
+  grub_loader_context = context;
   grub_loader_flags = flags;
 
   grub_loader_loaded = 1;
 }
 
+void
+grub_loader_set (grub_err_t (*boot) (void),
+                grub_err_t (*unload) (void),
+                int flags)
+{
+  grub_loader_set_ex (grub_simple_boot_hook,
+                     grub_simple_unload_hook,
+                     &simple_loader_hooks,
+                     flags);
+
+  simple_loader_hooks.boot = boot;
+  simple_loader_hooks.unload = unload;
+}
+
 void
 grub_loader_unset(void)
 {
   if (grub_loader_loaded && grub_loader_unload_func)
-    grub_loader_unload_func ();
+    grub_loader_unload_func (grub_loader_context);
 
   grub_loader_boot_func = 0;
   grub_loader_unload_func = 0;
+  grub_loader_context = 0;
 
   grub_loader_loaded = 0;
 }
@@ -158,7 +208,7 @@ grub_loader_boot (void)
          return err;
        }
     }
-  err = (grub_loader_boot_func) ();
+  err = (grub_loader_boot_func) (grub_loader_context);
 
   for (cur = preboots_tail; cur; cur = cur->prev)
     if (! err)
diff --git a/include/grub/loader.h b/include/grub/loader.h
index b208642821..97f2310545 100644
--- a/include/grub/loader.h
+++ b/include/grub/loader.h
@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) 
(void),
                                    grub_err_t (*unload) (void),
                                    int flags);
 
+void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *context),
+                                      grub_err_t (*unload) (void *context),
+                                      void *context,
+                                      int flags);
+
 /* Unset current loader, if any.  */
 void EXPORT_FUNC (grub_loader_unset) (void);
 
-- 
2.34.1


++++++ 0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch ++++++
>From e0cc6a601865a72cfe316f2cbbaaefcdd2ad8c69 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coul...@canonical.com>
Date: Tue, 5 Apr 2022 11:48:58 +0100
Subject: [PATCH 04/32] loader/efi/chainloader: Use grub_loader_set_ex()

This ports the EFI chainloader to use grub_loader_set_ex() in order to fix
a use-after-free bug that occurs when grub_cmd_chainloader() is executed
more than once before a boot attempt is performed.

Fixes: CVE-2022-28736

Signed-off-by: Chris Coulson <chris.coul...@canonical.com>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/loader/efi/chainloader.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/grub-core/loader/efi/chainloader.c 
b/grub-core/loader/efi/chainloader.c
index 1ec09a166c..b3e1e89302 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -54,7 +54,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
 static grub_dl_t my_mod;
 
 static grub_ssize_t fsize;
-static grub_efi_handle_t image_handle;
 static grub_ssize_t cmdline_len;
 static grub_efi_handle_t dev_handle;
 
@@ -64,8 +63,9 @@ static grub_efi_status_t (*entry_point) (grub_efi_handle_t 
image_handle,  grub_e
 #endif
 
 static grub_err_t
-grub_chainloader_unload (void)
+grub_chainloader_unload (void *context)
 {
+  grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
   grub_efi_loaded_image_t *loaded_image;
   grub_efi_boot_services_t *b;
 
@@ -83,8 +83,9 @@ grub_chainloader_unload (void)
 }
 
 static grub_err_t
-grub_chainloader_boot (void)
+grub_chainloader_boot (void *context)
 {
+  grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
   grub_efi_boot_services_t *b;
   grub_efi_status_t status;
   grub_efi_uintn_t exit_data_size;
@@ -644,6 +645,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
   grub_efi_physical_address_t address = 0;
   grub_efi_uintn_t pages = 0;
   grub_efi_char16_t *cmdline = NULL;
+  grub_efi_handle_t image_handle = NULL;
 
   if (argc == 0)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -856,7 +858,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
   efi_call_2 (b->free_pages, address, pages);
   grub_free (file_path);
 
-  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
+  grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, 
image_handle, 0);
   return 0;
 
  fail:
@@ -874,10 +876,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
     efi_call_2 (b->free_pages, address, pages);
 
   if (image_handle != NULL)
-    {
-      efi_call_1 (b->unload_image, image_handle);
-      image_handle = NULL;
-    }
+    efi_call_1 (b->unload_image, image_handle);
 
   grub_dl_unref (my_mod);
 
-- 
2.34.1


++++++ 0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch ++++++
>From ee99e452b9c1aafd3eb80592830ae2c6f69eb395 Mon Sep 17 00:00:00 2001
From: Julian Andres Klode <julian.kl...@canonical.com>
Date: Thu, 2 Dec 2021 15:03:53 +0100
Subject: [PATCH 05/32] kern/efi/sb: Reject non-kernel files in the shim_lock
 verifier

We must not allow other verifiers to pass things like the GRUB modules.
Instead of maintaining a blocklist, maintain an allowlist of things
that we do not care about.

This allowlist really should be made reusable, and shared by the
lockdown verifier, but this is the minimal patch addressing
security concerns where the TPM verifier was able to mark modules
as verified (or the OpenPGP verifier for that matter), when it
should not do so on shim-powered secure boot systems.

Fixes: CVE-2022-28735

Signed-off-by: Julian Andres Klode <julian.kl...@canonical.com>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++---
 include/grub/verify.h   |  1 +
 2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index c52ec6226a..89c4bb3fd1 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ 
((unused)),
                         void **context __attribute__ ((unused)),
                         enum grub_verify_flags *flags)
 {
-  *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+  *flags = GRUB_VERIFY_FLAGS_NONE;
 
   switch (type & GRUB_FILE_TYPE_MASK)
     {
+    /* Files we check. */
     case GRUB_FILE_TYPE_LINUX_KERNEL:
     case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
     case GRUB_FILE_TYPE_BSD_KERNEL:
@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ 
((unused)),
     case GRUB_FILE_TYPE_PLAN9_KERNEL:
     case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
       *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
+      return GRUB_ERR_NONE;
 
-      /* Fall through. */
+    /* Files that do not affect secureboot state. */
+    case GRUB_FILE_TYPE_NONE:
+    case GRUB_FILE_TYPE_LOOPBACK:
+    case GRUB_FILE_TYPE_LINUX_INITRD:
+    case GRUB_FILE_TYPE_OPENBSD_RAMDISK:
+    case GRUB_FILE_TYPE_XNU_RAMDISK:
+    case GRUB_FILE_TYPE_SIGNATURE:
+    case GRUB_FILE_TYPE_PUBLIC_KEY:
+    case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST:
+    case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
+    case GRUB_FILE_TYPE_TESTLOAD:
+    case GRUB_FILE_TYPE_GET_SIZE:
+    case GRUB_FILE_TYPE_FONT:
+    case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
+    case GRUB_FILE_TYPE_CAT:
+    case GRUB_FILE_TYPE_HEXCAT:
+    case GRUB_FILE_TYPE_CMP:
+    case GRUB_FILE_TYPE_HASHLIST:
+    case GRUB_FILE_TYPE_TO_HASH:
+    case GRUB_FILE_TYPE_KEYBOARD_LAYOUT:
+    case GRUB_FILE_TYPE_PIXMAP:
+    case GRUB_FILE_TYPE_GRUB_MODULE_LIST:
+    case GRUB_FILE_TYPE_CONFIG:
+    case GRUB_FILE_TYPE_THEME:
+    case GRUB_FILE_TYPE_GETTEXT_CATALOG:
+    case GRUB_FILE_TYPE_FS_SEARCH:
+    case GRUB_FILE_TYPE_LOADENV:
+    case GRUB_FILE_TYPE_SAVEENV:
+    case GRUB_FILE_TYPE_VERIFY_SIGNATURE:
+      *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+      return GRUB_ERR_NONE;
 
+    /* Other files. */
     default:
-      return GRUB_ERR_NONE;
+      return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot 
policy"));
     }
 }
 
diff --git a/include/grub/verify.h b/include/grub/verify.h
index 6fde244fc6..67448165f4 100644
--- a/include/grub/verify.h
+++ b/include/grub/verify.h
@@ -24,6 +24,7 @@
 
 enum grub_verify_flags
   {
+    GRUB_VERIFY_FLAGS_NONE             = 0,
     GRUB_VERIFY_FLAGS_SKIP_VERIFICATION        = 1,
     GRUB_VERIFY_FLAGS_SINGLE_CHUNK     = 2,
     /* Defer verification to another authority. */
-- 
2.34.1


++++++ 0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch ++++++
>From 77a70351615e0b6e66d663e063e9b4ba8ae129a0 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Fri, 25 Jun 2021 02:19:05 +1000
Subject: [PATCH 06/32] kern/file: Do not leak device_name on error in
 grub_file_open()

If we have an error in grub_file_open() before we free device_name, we
will leak it.

Free device_name in the error path and null out the pointer in the good
path once we free it there.

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

diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
index 58454458c4..ffdcaba05f 100644
--- a/grub-core/kern/file.c
+++ b/grub-core/kern/file.c
@@ -79,6 +79,7 @@ grub_file_open (const char *name, enum grub_file_type type)
 
   device = grub_device_open (device_name);
   grub_free (device_name);
+  device_name = NULL;
   if (! device)
     goto fail;
 
@@ -131,6 +132,7 @@ grub_file_open (const char *name, enum grub_file_type type)
   return file;
 
  fail:
+  grub_free (device_name);
   if (device)
     grub_device_close (device);
 
-- 
2.34.1


++++++ 0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch ++++++
>From 9db9558e1c75d47beca7ba378a99471c57729be5 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 6 Jul 2021 14:02:55 +1000
Subject: [PATCH 07/32] video/readers/png: Abort sooner if a read operation
 fails

Fuzzing revealed some inputs that were taking a long time, potentially
forever, because they did not bail quickly upon encountering an I/O error.

Try to catch I/O errors sooner and bail out.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index 54dfedf435..d715c4629f 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -142,6 +142,7 @@ static grub_uint8_t
 grub_png_get_byte (struct grub_png_data *data)
 {
   grub_uint8_t r;
+  grub_ssize_t bytes_read = 0;
 
   if ((data->inside_idat) && (data->idat_remain == 0))
     {
@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data)
     }
 
   r = 0;
-  grub_file_read (data->file, &r, 1);
+  bytes_read = grub_file_read (data->file, &r, 1);
+
+  if (bytes_read != 1)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                 "png: unexpected end of data");
+      return 0;
+    }
 
   if (data->inside_idat)
     data->idat_remain--;
@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data,
   if (len == 0)
     return GRUB_ERR_NONE;
 
-  for (i = 0; 3 * i < len && i < 256; i++)
+  grub_errno = GRUB_ERR_NONE;
+  for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++)
     for (j = 0; j < 3; j++)
       data->palette[i][j] = grub_png_get_byte (data);
-  for (i *= 3; i < len; i++)
+  for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++)
     grub_png_get_byte (data);
 
   grub_png_get_dword (data);
 
-  return GRUB_ERR_NONE;
+  return grub_errno;
 }
 
 static grub_err_t
@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
 
   color_bits = grub_png_get_byte (data);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
   data->is_16bit = (color_bits == 16);
 
   color_type = grub_png_get_byte (data);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
 
   /* According to PNG spec, no other types are valid.  */
   if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data)
   if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                       "png: compression method not supported");
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
 
   if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                       "png: filter method not supported");
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
 
   if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                       "png: interlace method not supported");
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
 
   /* Skip crc checksum.  */
   grub_png_get_dword (data);
@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct 
huff_table *ht)
   int code, i;
 
   code = 0;
-  for (i = 0; i < ht->max_length; i++)
+  for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++)
     {
       code = (code << 1) + grub_png_get_bits (data, 1);
       if (code < ht->maxval[i])
@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
   grub_uint8_t lens[DEFLATE_HCLEN_MAX];
 
   nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
   nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
   nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
 
   if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
       (nb > DEFLATE_HCLEN_MAX))
@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
                            data->dist_offset);
 
   prev = 0;
-  for (i = 0; i < nl + nd; i++)
+  for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++)
     {
       int n, code;
       struct huff_table *ht;
@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
          len = cplens[n];
          if (cplext[n])
            len += grub_png_get_bits (data, cplext[n]);
+         if (grub_errno != GRUB_ERR_NONE)
+           return grub_errno;
 
          n = grub_png_get_huff_code (data, &data->dist_table);
          dist = cpdist[n];
          if (cpdext[n])
            dist += grub_png_get_bits (data, cpdext[n]);
+         if (grub_errno != GRUB_ERR_NONE)
+           return grub_errno;
 
          pos = data->wp - dist;
          if (pos < 0)
            pos += WSIZE;
 
-         while (len > 0)
+         while (len > 0 && grub_errno == GRUB_ERR_NONE)
            {
              data->slide[data->wp] = data->slide[pos];
              grub_png_output_byte (data, data->slide[data->wp]);
@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
   int final;
 
   cmf = grub_png_get_byte (data);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
   flg = grub_png_get_byte (data);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
 
   if ((cmf & 0xF) != Z_DEFLATED)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
       int block_type;
 
       final = grub_png_get_bits (data, 1);
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_errno;
       block_type = grub_png_get_bits (data, 2);
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_errno;
 
       switch (block_type)
        {
@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data)
            grub_png_get_byte (data);
            grub_png_get_byte (data);
 
-           for (i = 0; i < len; i++)
+           for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++)
              grub_png_output_byte (data, grub_png_get_byte (data));
 
            break;
@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data)
 
       len = grub_png_get_dword (data);
       type = grub_png_get_dword (data);
+      if (grub_errno != GRUB_ERR_NONE)
+       break;
       data->next_offset = data->file->offset + len + 4;
 
       switch (type)
-- 
2.34.1


++++++ 0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch ++++++
>From 2ca24e4cc44effd08fe6dfa05ad8417a9b186f42 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 6 Jul 2021 14:13:40 +1000
Subject: [PATCH 08/32] video/readers/png: Refuse to handle multiple image
 headers

This causes the bitmap to be leaked. Do not permit multiple image headers.

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

diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index d715c4629f..35ae553c8e 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data)
   int color_bits;
   enum grub_video_blit_format blt;
 
+  if (data->image_width || data->image_height)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found");
+
   data->image_width = grub_png_get_dword (data);
   data->image_height = grub_png_get_dword (data);
 
-- 
2.34.1


++++++ 0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch ++++++
>From 7be3f3b1b7be0602056721526878c91d3333f8fd Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 6 Jul 2021 18:51:35 +1000
Subject: [PATCH 09/32] video/readers/png: Drop greyscale support to fix heap
 out-of-bounds write

A 16-bit greyscale PNG without alpha is processed in the following loop:

      for (i = 0; i < (data->image_width * data->image_height);
           i++, d1 += 4, d2 += 2)
        {
          d1[R3] = d2[1];
          d1[G3] = d2[1];
          d1[B3] = d2[1];
        }

The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration,
but there are only 3 bytes allocated for storage. This means that image
data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes
out of every 4 following the end of the image.

This has existed since greyscale support was added in 2013 in commit
3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale).

Saving starfield.png as a 16-bit greyscale image without alpha in the gimp
and attempting to load it causes grub-emu to crash - I don't think this code
has ever worked.

Delete all PNG greyscale support.

Fixes: CVE-2021-3695

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/video/readers/png.c | 87 +++--------------------------------
 1 file changed, 7 insertions(+), 80 deletions(-)

diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index 35ae553c8e..a3161e25b6 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -100,7 +100,7 @@ struct grub_png_data
 
   unsigned image_width, image_height;
   int bpp, is_16bit;
-  int raw_bytes, is_gray, is_alpha, is_palette;
+  int raw_bytes, is_alpha, is_palette;
   int row_bytes, color_bits;
   grub_uint8_t *image_data;
 
@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
     data->bpp = 3;
   else
     {
-      data->is_gray = 1;
-      data->bpp = 1;
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                        "png: color type not supported");
     }
 
   if ((color_bits != 8) && (color_bits != 16)
       && (color_bits != 4
-         || !(data->is_gray || data->is_palette)))
+         || !data->is_palette))
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                        "png: bit depth must be 8 or 16");
 
@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
     }
 
 #ifndef GRUB_CPU_WORDS_BIGENDIAN
-  if (data->is_16bit || data->is_gray || data->is_palette)
+  if (data->is_16bit || data->is_palette)
 #endif
     {
       data->image_data = grub_calloc (data->image_height, data->row_bytes);
@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data)
       int shift;
       int mask = (1 << data->color_bits) - 1;
       unsigned j;
-      if (data->is_gray)
-       {
-         /* Generic formula is
-            (0xff * i) / ((1U << data->color_bits) - 1)
-            but for allowed bit depth of 1, 2 and for it's
-            equivalent to
-            (0xff / ((1U << data->color_bits) - 1)) * i
-            Precompute the multipliers to avoid division.
-         */
-
-         const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 };
-         for (i = 0; i < (1U << data->color_bits); i++)
-           {
-             grub_uint8_t col = multipliers[data->color_bits] * i;
-             palette[i][0] = col;
-             palette[i][1] = col;
-             palette[i][2] = col;
-           }
-       }
-      else
-       grub_memcpy (palette, data->palette, 3 << data->color_bits);
+
+      grub_memcpy (palette, data->palette, 3 << data->color_bits);
       d1c = d1;
       d2c = d2;
       for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3,
@@ -957,60 +938,6 @@ grub_png_convert_image (struct grub_png_data *data)
       return;
     }
 
-  if (data->is_gray)
-    {
-      switch (data->bpp)
-       {
-       case 4:
-         /* 16-bit gray with alpha.  */
-         for (i = 0; i < (data->image_width * data->image_height);
-              i++, d1 += 4, d2 += 4)
-           {
-             d1[R4] = d2[3];
-             d1[G4] = d2[3];
-             d1[B4] = d2[3];
-             d1[A4] = d2[1];
-           }
-         break;
-       case 2:
-         if (data->is_16bit)
-           /* 16-bit gray without alpha.  */
-           {
-             for (i = 0; i < (data->image_width * data->image_height);
-                  i++, d1 += 4, d2 += 2)
-               {
-                 d1[R3] = d2[1];
-                 d1[G3] = d2[1];
-                 d1[B3] = d2[1];
-               }
-           }
-         else
-           /* 8-bit gray with alpha.  */
-           {
-             for (i = 0; i < (data->image_width * data->image_height);
-                  i++, d1 += 4, d2 += 2)
-               {
-                 d1[R4] = d2[1];
-                 d1[G4] = d2[1];
-                 d1[B4] = d2[1];
-                 d1[A4] = d2[0];
-               }
-           }
-         break;
-         /* 8-bit gray without alpha.  */
-       case 1:
-         for (i = 0; i < (data->image_width * data->image_height);
-              i++, d1 += 3, d2++)
-           {
-             d1[R3] = d2[0];
-             d1[G3] = d2[0];
-             d1[B3] = d2[0];
-           }
-         break;
-       }
-      return;
-    }
-
     {
   /* Only copy the upper 8 bit.  */
 #ifndef GRUB_CPU_WORDS_BIGENDIAN
-- 
2.34.1


++++++ 0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch ++++++
>From 8ebb6943eae81d3c31963bbae42d5d1f168c8dd5 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 6 Jul 2021 23:25:07 +1000
Subject: [PATCH 10/32] video/readers/png: Avoid heap OOB R/W inserting huff
 table items

In fuzzing we observed crashes where a code would attempt to be inserted
into a huffman table before the start, leading to a set of heap OOB reads
and writes as table entries with negative indices were shifted around and
the new code written in.

Catch the case where we would underflow the array and bail.

Fixes: CVE-2021-3696

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

diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index a3161e25b6..d7ed5aa6cf 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int 
code, int len)
   for (i = len; i < ht->max_length; i++)
     n += ht->maxval[i];
 
+  if (n > ht->num_values)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                 "png: out of range inserting huffman table item");
+      return;
+    }
+
   for (i = 0; i < n; i++)
     ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
 
-- 
2.34.1


++++++ 0011-video-readers-png-Sanity-check-some-huffman-codes.patch ++++++
>From bbbb410d5d7d29d935e7108c77a0368e4e007a43 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 6 Jul 2021 19:19:11 +1000
Subject: [PATCH 11/32] video/readers/png: Sanity check some huffman codes

ASAN picked up two OOB global reads: we weren't checking if some code
values fit within the cplens or cpdext arrays. Check and throw an error
if not.

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

diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index d7ed5aa6cf..7f2ba7849b 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
          int len, dist, pos;
 
          n -= 257;
+         if (((unsigned int) n) >= ARRAY_SIZE (cplens))
+           return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                              "png: invalid huff code");
          len = cplens[n];
          if (cplext[n])
            len += grub_png_get_bits (data, cplext[n]);
@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
            return grub_errno;
 
          n = grub_png_get_huff_code (data, &data->dist_table);
+         if (((unsigned int) n) >= ARRAY_SIZE (cpdist))
+           return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                              "png: invalid huff code");
          dist = cpdist[n];
          if (cpdext[n])
            dist += grub_png_get_bits (data, cpdext[n]);
-- 
2.34.1


++++++ 0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch ++++++
>From 27134e18072a9dffb2bda6b74cd312be5360baa0 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Mon, 28 Jun 2021 14:16:14 +1000
Subject: [PATCH 12/32] video/readers/jpeg: Abort sooner if a read operation
 fails

Fuzzing revealed some inputs that were taking a long time, potentially
forever, because they did not bail quickly upon encountering an I/O error.

Try to catch I/O errors sooner and bail out.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/video/readers/jpeg.c | 86 +++++++++++++++++++++++++++-------
 1 file changed, 70 insertions(+), 16 deletions(-)

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index e31602f766..10225abd53 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -109,9 +109,17 @@ static grub_uint8_t
 grub_jpeg_get_byte (struct grub_jpeg_data *data)
 {
   grub_uint8_t r;
+  grub_ssize_t bytes_read;
 
   r = 0;
-  grub_file_read (data->file, &r, 1);
+  bytes_read = grub_file_read (data->file, &r, 1);
+
+  if (bytes_read != 1)
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                 "jpeg: unexpected end of data");
+      return 0;
+    }
 
   return r;
 }
@@ -120,9 +128,17 @@ static grub_uint16_t
 grub_jpeg_get_word (struct grub_jpeg_data *data)
 {
   grub_uint16_t r;
+  grub_ssize_t bytes_read;
 
   r = 0;
-  grub_file_read (data->file, &r, sizeof (grub_uint16_t));
+  bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t));
+
+  if (bytes_read != sizeof (grub_uint16_t))
+    {
+      grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                 "jpeg: unexpected end of data");
+      return 0;
+    }
 
   return grub_be_to_cpu16 (r);
 }
@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
   if (data->bit_mask == 0)
     {
       data->bit_save = grub_jpeg_get_byte (data);
+      if (grub_errno != GRUB_ERR_NONE) {
+       grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                   "jpeg: file read error");
+       return 0;
+      }
       if (data->bit_save == JPEG_ESC_CHAR)
        {
          if (grub_jpeg_get_byte (data) != 0)
@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
                          "jpeg: invalid 0xFF in data stream");
              return 0;
            }
+         if (grub_errno != GRUB_ERR_NONE)
+           {
+             grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error");
+             return 0;
+           }
        }
       data->bit_mask = 0x80;
     }
@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
     return 0;
 
   msb = value = grub_jpeg_get_bit (data);
-  for (i = 1; i < num; i++)
+  for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++)
     value = (value << 1) + (grub_jpeg_get_bit (data) != 0);
   if (!msb)
     value += 1 - (1 << num);
@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
   while (data->file->offset + sizeof (count) + 1 <= next_marker)
     {
       id = grub_jpeg_get_byte (data);
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_errno;
       ac = (id >> 4) & 1;
       id &= 0xF;
       if (id > 1)
@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
 
   next_marker = data->file->offset;
   next_marker += grub_jpeg_get_word (data);
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
 
   if (next_marker > data->file->size)
     {
@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
         <= next_marker)
     {
       id = grub_jpeg_get_byte (data);
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
       if (id >= 0x10)          /* Upper 4-bit is precision.  */
        return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                           "jpeg: only 8-bit precision is supported");
@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
   next_marker = data->file->offset;
   next_marker += grub_jpeg_get_word (data);
 
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
   if (grub_jpeg_get_byte (data) != 8)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                       "jpeg: only 8-bit precision is supported");
@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
        return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
 
       ss = grub_jpeg_get_byte (data);  /* Sampling factor.  */
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_errno;
       if (!id)
        {
          grub_uint8_t vs, hs;
@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du)
     }
 }
 
-static void
+static grub_err_t
 grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
 {
   int h1, h2, qt;
@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, 
jpeg_data_unit_t du)
   data->dc_value[id] +=
     grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1));
 
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
+
   du[0] = data->dc_value[id] * (int) data->quan_table[qt][0];
   pos = 1;
   while (pos < ARRAY_SIZE (data->quan_table[qt]))
@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, 
jpeg_data_unit_t du)
       num >>= 4;
       pos += num;
 
+      if (grub_errno != GRUB_ERR_NONE)
+        return grub_errno;
+
       if (pos >= ARRAY_SIZE (jpeg_zigzag_order))
        {
-         grub_error (GRUB_ERR_BAD_FILE_TYPE,
-                     "jpeg: invalid position in zigzag order!?");
-         return;
+         return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                            "jpeg: invalid position in zigzag order!?");
        }
 
       du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, 
jpeg_data_unit_t du)
     }
 
   grub_jpeg_idct_transform (du);
+  return GRUB_ERR_NONE;
 }
 
 static void
@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
   data_offset += grub_jpeg_get_word (data);
 
   cc = grub_jpeg_get_byte (data);
-
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
   if (cc != 3 && cc != 1)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                       "jpeg: component count must be 1 or 3");
@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
       id = grub_jpeg_get_byte (data) - 1;
       if ((id < 0) || (id >= 3))
        return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
-
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_errno;
       ht = grub_jpeg_get_byte (data);
       data->comp_index[id][1] = (ht >> 4);
       data->comp_index[id][2] = (ht & 0xF) + 2;
@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
       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");
+      if (grub_errno != GRUB_ERR_NONE)
+       return grub_errno;
     }
 
   grub_jpeg_get_byte (data);   /* Skip 3 unused bytes.  */
   grub_jpeg_get_word (data);
-
+  if (grub_errno != GRUB_ERR_NONE)
+    return grub_errno;
   if (data->file->offset != data_offset)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
 
@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
 {
   unsigned c1, vb, hb, nr1, nc1;
   int rst = data->dri;
+  grub_err_t err = GRUB_ERR_NONE;
 
   vb = 8 << data->log_vs;
   hb = 8 << data->log_hs;
@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
 
        for (r2 = 0; r2 < (1U << data->log_vs); r2++)
          for (c2 = 0; c2 < (1U << data->log_hs); c2++)
-           grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
+            {
+              err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
+              if (err != GRUB_ERR_NONE)
+                return err;
+            }
 
        if (data->color_components >= 3)
          {
-           grub_jpeg_decode_du (data, 1, data->cbdu);
-           grub_jpeg_decode_du (data, 2, data->crdu);
+           err = grub_jpeg_decode_du (data, 1, data->cbdu);
+           if (err != GRUB_ERR_NONE)
+             return err;
+           err = grub_jpeg_decode_du (data, 2, data->crdu);
+           if (err != GRUB_ERR_NONE)
+             return err;
          }
 
-       if (grub_errno)
-         return grub_errno;
-
        nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb;
        nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
 
-- 
2.34.1


++++++ 0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch ++++++
>From 8f8282090a1d1469bffd0db6a07275882628caeb Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Mon, 28 Jun 2021 14:16:58 +1000
Subject: [PATCH 13/32] video/readers/jpeg: Do not reallocate a given huff
 table

Fix a memory leak where an invalid file could cause us to reallocate
memory for a huffman table we had already allocated memory for.

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

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index 10225abd53..caa211f06d 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
        n += count[i];
 
       id += ac * 2;
+      if (data->huff_value[id] != NULL)
+       return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                          "jpeg: attempt to reallocate huffman table");
       data->huff_value[id] = grub_malloc (n);
       if (grub_errno)
        return grub_errno;
-- 
2.34.1


++++++ 0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch ++++++
>From 9b6026ba4eb26eadc7ddb8df1c49f648efe257c5 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Mon, 28 Jun 2021 14:25:17 +1000
Subject: [PATCH 14/32] video/readers/jpeg: Refuse to handle multiple start of
 streams

An invalid file could contain multiple start of stream blocks, which
would cause us to reallocate and leak our bitmap. Refuse to handle
multiple start of streams.

Additionally, fix a grub_error() call formatting.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/video/readers/jpeg.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index caa211f06d..1df1171d78 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
   if (data->file->offset != data_offset)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
 
+  if (*data->bitmap)
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan 
blocks");
+
   if (grub_video_bitmap_create (data->bitmap, data->image_width,
                                data->image_height,
                                GRUB_VIDEO_BLIT_FORMAT_RGB_888))
@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
   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");
+    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)
-- 
2.34.1


++++++ 0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch ++++++
>From 9a6e9ad21eb2f414dce6eaedd41e146a28142101 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Wed, 7 Jul 2021 15:38:19 +1000
Subject: [PATCH 15/32] video/readers/jpeg: Block int underflow -> wild pointer
 write

Certain 1 px wide images caused a wild pointer write in
grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(),
we have the following loop:

for (; data->r1 < nr1 && (!data->dri || rst);
     data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)

We did not check if vb * width >= hb * nc1.

On a 64-bit platform, if that turns out to be negative, it will underflow,
be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so
we see data->bitmap_ptr jump, e.g.:

0x6180_0000_0480 to
0x6181_0000_0498
     ^
     ~--- carry has occurred and this pointer is now far away from
          any object.

On a 32-bit platform, it will decrement the pointer, creating a pointer
that won't crash but will overwrite random data.

Catch the underflow and error out.

Fixes: CVE-2021-3697

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

diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
index 1df1171d78..97a533b24f 100644
--- a/grub-core/video/readers/jpeg.c
+++ b/grub-core/video/readers/jpeg.c
@@ -23,6 +23,7 @@
 #include <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/bufio.h>
+#include <grub/safemath.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -693,6 +694,7 @@ static grub_err_t
 grub_jpeg_decode_data (struct grub_jpeg_data *data)
 {
   unsigned c1, vb, hb, nr1, nc1;
+  unsigned stride_a, stride_b, stride;
   int rst = data->dri;
   grub_err_t err = GRUB_ERR_NONE;
 
@@ -705,8 +707,14 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                       "jpeg: attempted to decode data before start of stream");
 
+  if (grub_mul(vb, data->image_width, &stride_a) ||
+      grub_mul(hb, nc1, &stride_b) ||
+      grub_sub(stride_a, stride_b, &stride))
+    return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                      "jpeg: cannot decode image with these dimensions");
+
   for (; data->r1 < nr1 && (!data->dri || rst);
-       data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
+       data->r1++, data->bitmap_ptr += stride * 3)
     for (c1 = 0;  c1 < nc1 && (!data->dri || rst);
        c1++, rst--, data->bitmap_ptr += hb * 3)
       {
-- 
2.34.1


++++++ 0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch ++++++
>From cfe96e5c432b58726047f4d94f106f58855db1e2 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 13 Jul 2021 13:24:38 +1000
Subject: [PATCH 16/32] normal/charset: Fix array out-of-bounds formatting
 unicode for display

In some cases attempting to display arbitrary binary strings leads
to ASAN splats reading the widthspec array out of bounds.

Check the index. If it would be out of bounds, return a width of 1.
I don't know if that's strictly correct, but we're not really expecting
great display of arbitrary binary data, and it's certainly not worse than
an OOB read.

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

diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
index 4dfcc31078..7a5a7c153c 100644
--- a/grub-core/normal/charset.c
+++ b/grub-core/normal/charset.c
@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct 
grub_unicode_glyph *c)
 {
   if (grub_unicode_get_comb_type (c->base))
     return 0;
+  if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec))
+    return 1;
   if (widthspec[c->base >> 3] & (1 << (c->base & 7)))
     return 2;
   else
-- 
2.34.1


++++++ 0017-net-ip-Do-IP-fragment-maths-safely.patch ++++++
>From 5c79af15504c599b58a2f3e591850876dfdb5fa2 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Mon, 20 Dec 2021 19:41:21 +1100
Subject: [PATCH 17/32] net/ip: Do IP fragment maths safely

We can receive packets with invalid IP fragmentation information. This
can lead to rsm->total_len underflowing and becoming very large.

Then, in grub_netbuff_alloc(), we add to this very large number, which can
cause it to overflow and wrap back around to a small positive number.
The allocation then succeeds, but the resulting buffer is too small and
subsequent operations can write past the end of the buffer.

Catch the underflow here.

Fixes: CVE-2022-28733

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

diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
index 01410798b3..937be87678 100644
--- a/grub-core/net/ip.c
+++ b/grub-core/net/ip.c
@@ -25,6 +25,7 @@
 #include <grub/net/netbuff.h>
 #include <grub/mm.h>
 #include <grub/priority_queue.h>
+#include <grub/safemath.h>
 #include <grub/time.h>
 
 struct iphdr {
@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
     {
       rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK)
                        + (nb->tail - nb->data));
-      rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t));
+
+      if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof 
(grub_uint32_t),
+                   &rsm->total_len))
+       {
+         grub_dprintf ("net", "IP reassembly size underflow\n");
+         return GRUB_ERR_NONE;
+       }
+
       rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len);
       if (!rsm->asm_netbuff)
        {
-- 
2.34.1


++++++ 0018-net-netbuff-Block-overly-large-netbuff-allocs.patch ++++++
>From bf949ed28a526b7ab137b8804e2ef6239c3061f2 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 8 Mar 2022 23:47:46 +1100
Subject: [PATCH 18/32] net/netbuff: Block overly large netbuff allocs

A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment
reassembly. If we are asked to create one that is unreasonably big, refuse.

This is a hardening measure: if we hit this code, there's a bug somewhere
else that we should catch and fix.

This commit:
  - stops the bug propagating any further.
  - provides a spot to instrument in e.g. fuzzing to try to catch these bugs.

I have put instrumentation (e.g. __builtin_trap() to force a crash) here and
have not been able to find any more crashes.

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

diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c
index dbeeefe478..d5e9e9a0d7 100644
--- a/grub-core/net/netbuff.c
+++ b/grub-core/net/netbuff.c
@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len)
 
   COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0);
 
+  /*
+   * The largest size of a TCP packet is 64 KiB, and everything else
+   * should be a lot smaller - most MTUs are 1500 or less. Cap data
+   * size at 64 KiB + a buffer.
+   */
+  if (len > 0xffffUL + 0x1000UL)
+    {
+      grub_error (GRUB_ERR_BUG,
+                  "attempted to allocate a packet that is too big");
+      return NULL;
+    }
+
   if (len < NETBUFFMINLEN)
     len = NETBUFFMINLEN;
 
   len = ALIGN_UP (len, NETBUFF_ALIGN);
+
 #ifdef GRUB_MACHINE_EMU
   data = grub_malloc (len + sizeof (*nb));
 #else
-- 
2.34.1


++++++ 0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch ++++++
>From cc43d9a3d77069850f993fbc4ae47c941bf284b9 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Thu, 16 Sep 2021 01:29:54 +1000
Subject: [PATCH 19/32] net/dns: Fix double-free addresses on corrupt DNS
 response

grub_net_dns_lookup() takes as inputs a pointer to an array of addresses
("addresses") for the given name, and pointer to a number of addresses
("naddresses"). grub_net_dns_lookup() is responsible for allocating
"addresses", and the caller is responsible for freeing it if
"naddresses" > 0.

The DNS recv_hook will sometimes set and free the addresses array,
for example if the packet is too short:

      if (ptr + 10 >= nb->tail)
        {
          if (!*data->naddresses)
            grub_free (*data->addresses);
          grub_netbuff_free (nb);
          return GRUB_ERR_NONE;
        }

Later on the nslookup command code unconditionally frees the "addresses"
array. Normally this is fine: the array is either populated with valid
data or is NULL. But in these sorts of error cases it is neither NULL
nor valid and we get a double-free.

Only free "addresses" if "naddresses" > 0.

It looks like the other use of grub_net_dns_lookup() is not affected.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/net/dns.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
index 906ec7d678..135faac035 100644
--- a/grub-core/net/dns.c
+++ b/grub-core/net/dns.c
@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ 
((unused)),
       grub_net_addr_to_str (&addresses[i], buf);
       grub_printf ("%s\n", buf);
     }
-  grub_free (addresses);
   if (naddresses)
-    return GRUB_ERR_NONE;
+    {
+      grub_free (addresses);
+      return GRUB_ERR_NONE;
+    }
   return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
 }
 
-- 
2.34.1


++++++ 0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch ++++++
>From e33af61c202972c81aaccdd395d61855e1584f66 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Mon, 20 Dec 2021 21:55:43 +1100
Subject: [PATCH 20/32] net/dns: Don't read past the end of the string we're
 checking against

I don't really understand what's going on here but fuzzing found
a bug where we read past the end of check_with. That's a C string,
so use grub_strlen() to make sure we don't overread it.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/net/dns.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
index 135faac035..17961a9f18 100644
--- a/grub-core/net/dns.c
+++ b/grub-core/net/dns.c
@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const 
grub_uint8_t *head,
                 int *length, char *set)
 {
   const char *readable_ptr = check_with;
+  int readable_len;
   const grub_uint8_t *ptr;
   char *optr = set;
   int bytes_processed = 0;
   if (length)
     *length = 0;
+
+  if (readable_ptr != NULL)
+    readable_len = grub_strlen (readable_ptr);
+  else
+    readable_len = 0;
+
   for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; )
     {
       /* End marker.  */
@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const 
grub_uint8_t *head,
          ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]);
          continue;
        }
-      if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)
+      if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 
1, readable_ptr, *ptr) != 0))
        return 0;
       if (grub_memchr (ptr + 1, 0, *ptr) 
          || grub_memchr (ptr + 1, '.', *ptr))
        return 0;
       if (readable_ptr)
-       readable_ptr += *ptr;
+       {
+         readable_ptr += *ptr;
+         readable_len -= *ptr;
+       }
       if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0)
        return 0;
       bytes_processed += *ptr + 1;
@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const 
grub_uint8_t *head,
       if (optr)
        *optr++ = '.';
       if (readable_ptr && *readable_ptr)
-       readable_ptr++;
+       {
+         readable_ptr++;
+         readable_len--;
+       }
       ptr += *ptr + 1;
     }
   return 0;
-- 
2.34.1


++++++ 0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch ++++++
>From 4adbb12d15af04f8f279a6290cd0195e57cc9e69 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Mon, 20 Sep 2021 01:12:24 +1000
Subject: [PATCH 21/32] net/tftp: Prevent a UAF and double-free from a failed
 seek

A malicious tftp server can cause UAFs and a double free.

An attempt to read from a network file is handled by grub_net_fs_read(). If
the read is at an offset other than the current offset, grub_net_seek_real()
is invoked.

In grub_net_seek_real(), if a backwards seek cannot be satisfied from the
currently received packets, and the underlying transport does not provide
a seek method, then grub_net_seek_real() will close and reopen the network
protocol layer.

For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t
file->data. The file->data pointer is not nulled out after the free.

If the ->open() call fails, the file->data will not be reallocated and will
continue point to a freed memory block. This could happen from a server
refusing to send the requisite ack to the new tftp request, for example.

The seek and the read will then fail, but the grub_file continues to exist:
the failed seek does not necessarily cause the entire file to be thrown
away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc.,
a read failure is interpreted as a decompressor passing on the file, not as
an invalidation of the entire grub_file_t structure).

This means subsequent attempts to read or seek the file will use the old
file->data after free. Eventually, the file will be close()d again and
file->data will be freed again.

Mark a net_fs file that doesn't reopen as broken. Do not permit read() or
close() on a broken file (seek is not exposed directly to the file API -
it is only called as part of read, so this blocks seeks as well).

As an additional defence, null out the ->data pointer if tftp_open() fails.
That would have lead to a simple null pointer dereference rather than
a mess of UAFs.

This may affect other protocols, I haven't checked.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/net/net.c  | 11 +++++++++--
 grub-core/net/tftp.c |  1 +
 include/grub/net.h   |  1 +
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index d11672fbee..b8238b7df1 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1546,7 +1546,8 @@ grub_net_fs_close (grub_file_t file)
       grub_netbuff_free (file->device->net->packs.first->nb);
       grub_net_remove_packet (file->device->net->packs.first);
     }
-  file->device->net->protocol->close (file);
+  if (!file->device->net->broken)
+    file->device->net->protocol->close (file);
   grub_free (file->device->net->name);
   return GRUB_ERR_NONE;
 }
@@ -1768,7 +1769,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t 
offset)
     file->device->net->stall = 0;
     err = file->device->net->protocol->open (file, file->device->net->name);
     if (err)
-      return err;
+      {
+       file->device->net->broken = 1;
+       return err;
+      }
     grub_net_fs_read_real (file, NULL, offset);
     return grub_errno;
   }
@@ -1777,6 +1781,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t 
offset)
 static grub_ssize_t
 grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
 {
+  if (file->device->net->broken)
+    return -1;
+
   if (file->offset != file->device->net->offset)
     {
       grub_err_t err;
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index f3e7879388..d1afa25352 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -404,6 +404,7 @@ tftp_open (struct grub_file *file, const char *filename)
     {
       grub_net_udp_close (data->sock);
       grub_free (data);
+      file->data = NULL;
       return grub_errno;
     }
 
diff --git a/include/grub/net.h b/include/grub/net.h
index cbcae79b1f..8d71ca6cc5 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -277,6 +277,7 @@ typedef struct grub_net
   grub_fs_t fs;
   int eof;
   int stall;
+  int broken;
 } *grub_net_t;
 
 extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
-- 
2.34.1


++++++ 0022-net-tftp-Avoid-a-trivial-UAF.patch ++++++
>From 1824df76e0e712917edce83b5be57d485b81a5a7 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 18 Jan 2022 14:29:20 +1100
Subject: [PATCH 22/32] net/tftp: Avoid a trivial UAF

Under tftp errors, we print a tftp error message from the tftp header.
However, the tftph pointer is a pointer inside nb, the netbuff. Previously,
we were freeing the nb and then dereferencing it. Don't do that, use it
and then free it later.

This isn't really _bad_ per se, especially as we're single-threaded, but
it trips up fuzzers.

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

diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
index d1afa25352..4222d93b6d 100644
--- a/grub-core/net/tftp.c
+++ b/grub-core/net/tftp.c
@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ 
((unused)),
       return GRUB_ERR_NONE;
     case TFTP_ERROR:
       data->have_oack = 1;
-      grub_netbuff_free (nb);
       grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg);
       grub_error_save (&data->save_err);
+      grub_netbuff_free (nb);
       return GRUB_ERR_NONE;
     default:
       grub_netbuff_free (nb);
-- 
2.34.1


++++++ 0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch ++++++
>From 7ec48289eeae517e14e2c957a90fd95a49741894 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 1 Mar 2022 23:14:15 +1100
Subject: [PATCH 23/32] net/http: Do not tear down socket if it's already been
 torn down

It's possible for data->sock to get torn down in tcp error handling.
If we unconditionally tear it down again we will end up doing writes
to an offset of the NULL pointer when we go to tear it down again.

Detect if it has been torn down and don't do it again.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/net/http.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index bf838660d9..a77bc4e4b8 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -425,7 +425,7 @@ http_establish (struct grub_file *file, grub_off_t offset, 
int initial)
       return err;
     }
 
-  for (i = 0; !data->headers_recv && i < 100; i++)
+  for (i = 0; data->sock && !data->headers_recv && i < 100; i++)
     {
       grub_net_tcp_retransmit ();
       grub_net_poll_cards (300, &data->headers_recv);
@@ -433,7 +433,8 @@ http_establish (struct grub_file *file, grub_off_t offset, 
int initial)
 
   if (!data->headers_recv)
     {
-      grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
+      if (data->sock)
+        grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
       if (data->err)
        {
          char *str = data->errmsg;
-- 
2.34.1


++++++ 0024-net-http-Fix-OOB-write-for-split-http-headers.patch ++++++
>From d7374ab1a110a7ddcfa5a0eda9574ebef2220ee1 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 8 Mar 2022 18:17:03 +1100
Subject: [PATCH 24/32] net/http: Fix OOB write for split http headers

GRUB has special code for handling an http header that is split
across two packets.

The code tracks the end of line by looking for a "\n" byte. The
code for split headers has always advanced the pointer just past the
end of the line, whereas the code that handles unsplit headers does
not advance the pointer. This extra advance causes the length to be
one greater, which breaks an assumption in parse_line(), leading to
it writing a NUL byte one byte past the end of the buffer where we
reconstruct the line from the two packets.

It's conceivable that an attacker controlled set of packets could
cause this to zero out the first byte of the "next" pointer of the
grub_mm_region structure following the current_line buffer.

Do not advance the pointer in the split header case.

Fixes: CVE-2022-28734

Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/net/http.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index a77bc4e4b8..d9d2ade98e 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -193,9 +193,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ 
((unused)),
          int have_line = 1;
          char *t;
          ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
-         if (ptr)
-           ptr++;
-         else
+         if (ptr == NULL)
            {
              have_line = 0;
              ptr = (char *) nb->tail;
-- 
2.34.1


++++++ 0025-net-http-Error-out-on-headers-with-LF-without-CR.patch ++++++
>From 5a6ca6483123f2290696e7268f875ff72dd841b6 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 8 Mar 2022 19:04:40 +1100
Subject: [PATCH 25/32] net/http: Error out on headers with LF without CR

In a similar vein to the previous patch, parse_line() would write
a NUL byte past the end of the buffer if there was an HTTP header
with a LF rather than a CRLF.

RFC-2616 says:

  Many HTTP/1.1 header field values consist of words separated by LWS
  or special characters. These special characters MUST be in a quoted
  string to be used within a parameter value (as defined in section 3.6).

We don't support quoted sections or continuation lines, etc.

If we see an LF that's not part of a CRLF, bail out.

Fixes: CVE-2022-28734

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

diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index d9d2ade98e..0472645d12 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -69,7 +69,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, 
grub_size_t len)
   char *end = ptr + len;
   while (end > ptr && *(end - 1) == '\r')
     end--;
+
+  /* LF without CR. */
+  if (end == ptr + len)
+    {
+      data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR"));
+      return GRUB_ERR_NONE;
+    }
   *end = 0;
+
   /* Trailing CRLF.  */
   if (data->in_chunk_len == 1)
     {
-- 
2.34.1


++++++ 0026-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch ++++++
>From c1013c295f1e32620db302470f126df0c6a0d5a5 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudha...@linux.ibm.com>
Date: Wed, 6 Apr 2022 18:03:37 +0530
Subject: [PATCH 26/32] fs/f2fs: Do not read past the end of nat journal
 entries

A corrupt f2fs file system could specify a nat journal entry count
that is beyond the maximum NAT_JOURNAL_ENTRIES.

Check if the specified nat journal entry count before accessing the
array, and throw an error if it is too large.

Signed-off-by: Sudhakar Kuppusamy <sudha...@linux.ibm.com>
Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/fs/f2fs.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
index 8a9992ca9e..63702214b0 100644
--- a/grub-core/fs/f2fs.c
+++ b/grub-core/fs/f2fs.c
@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data)
   return err;
 }
 
-static grub_uint32_t
-get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid)
+static grub_err_t
+get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid,
+                              grub_uint32_t *blkaddr)
 {
   grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats);
-  grub_uint32_t blkaddr = 0;
   grub_uint16_t i;
 
+  if (n >= NAT_JOURNAL_ENTRIES)
+    return grub_error (GRUB_ERR_BAD_FS,
+                       "invalid number of nat journal entries");
+
   for (i = 0; i < n; i++)
     {
       if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid)
         {
-          blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
+          *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
           break;
         }
     }
 
-  return blkaddr;
+  return GRUB_ERR_NONE;
 }
 
 static grub_uint32_t
@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, 
grub_uint32_t nid)
 {
   struct grub_f2fs_nat_block *nat_block;
   grub_uint32_t seg_off, block_off, entry_off, block_addr;
-  grub_uint32_t blkaddr;
+  grub_uint32_t blkaddr = 0;
   grub_err_t err;
 
-  blkaddr = get_blkaddr_from_nat_journal (data, nid);
+  err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
+  if (err != GRUB_ERR_NONE)
+    return 0;
+
   if (blkaddr)
     return blkaddr;
 
-- 
2.34.1


++++++ 0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch ++++++
>From 5ac885d02a9e91a5d6760090f90fa2bb4e7a5dd6 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudha...@linux.ibm.com>
Date: Wed, 6 Apr 2022 18:49:09 +0530
Subject: [PATCH 27/32] fs/f2fs: Do not read past the end of nat bitmap

A corrupt f2fs filesystem could have a block offset or a bitmap
offset that would cause us to read beyond the bounds of the nat
bitmap.

Introduce the nat_bitmap_size member in grub_f2fs_data which holds
the size of nat bitmap.

Set the size when loading the nat bitmap in nat_bitmap_ptr(), and
catch when an invalid offset would create a pointer past the end of
the allocated space.

Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid
reading past the end of the nat bitmap.

Signed-off-by: Sudhakar Kuppusamy <sudha...@linux.ibm.com>
Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
index 63702214b0..8898b235e0 100644
--- a/grub-core/fs/f2fs.c
+++ b/grub-core/fs/f2fs.c
@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
 #define F2FS_INLINE_DOTS          0x10  /* File having implicit dot dentries. 
*/
 
 #define MAX_VOLUME_NAME           512
+#define MAX_NAT_BITMAP_SIZE       3900
 
 enum FILE_TYPE
 {
@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint
   grub_uint32_t                   checksum_offset;
   grub_uint64_t                   elapsed_time;
   grub_uint8_t                    alloc_type[MAX_ACTIVE_LOGS];
-  grub_uint8_t                    sit_nat_version_bitmap[3900];
+  grub_uint8_t                    sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE];
   grub_uint32_t                   checksum;
 } GRUB_PACKED;
 
@@ -302,6 +303,7 @@ struct grub_f2fs_data
 
   struct grub_f2fs_nat_journal    nat_j;
   char                            *nat_bitmap;
+  grub_uint32_t                   nat_bitmap_size;
 
   grub_disk_t                     disk;
   struct grub_f2fs_node           *inode;
@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int 
type)
 }
 
 static void *
-nat_bitmap_ptr (struct grub_f2fs_data *data)
+nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size)
 {
   struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
   grub_uint32_t offset;
+  *nat_bitmap_size = MAX_NAT_BITMAP_SIZE;
 
   if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0)
     return ckpt->sit_nat_version_bitmap;
 
   offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize);
+  if (offset >= MAX_NAT_BITMAP_SIZE)
+     return NULL;
+
+  *nat_bitmap_size = *nat_bitmap_size - offset;
 
   return ckpt->sit_nat_version_bitmap + offset;
 }
@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, 
const grub_uint32_t len)
 }
 
 static int
-grub_f2fs_test_bit (grub_uint32_t nr, const char *p)
+grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len)
 {
   int mask;
+  grub_uint32_t shifted_nr = (nr >> 3);
+
+  if (shifted_nr >= len)
+    return -1;
 
-  p += (nr >> 3);
+  p += shifted_nr;
   mask = 1 << (7 - (nr & 0x07));
 
   return mask & *p;
@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, 
grub_uint32_t nid)
   grub_uint32_t seg_off, block_off, entry_off, block_addr;
   grub_uint32_t blkaddr = 0;
   grub_err_t err;
+  int result_bit;
 
   err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
   if (err != GRUB_ERR_NONE)
@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, 
grub_uint32_t nid)
         ((seg_off * data->blocks_per_seg) << 1) +
         (block_off & (data->blocks_per_seg - 1));
 
-  if (grub_f2fs_test_bit (block_off, data->nat_bitmap))
+  result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap,
+                                   data->nat_bitmap_size);
+  if (result_bit > 0)
     block_addr += data->blocks_per_seg;
+  else if (result_bit == -1)
+    {
+      grub_free (nat_block);
+      return 0;
+    }
 
   err = grub_f2fs_block_read (data, block_addr, nat_block);
   if (err)
@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk)
   if (err)
     goto fail;
 
-  data->nat_bitmap = nat_bitmap_ptr (data);
+  data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size);
+  if (data->nat_bitmap == NULL)
+    goto fail;
 
   err = get_nat_journal (data);
   if (err)
-- 
2.34.1


++++++ 0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch ++++++
>From 315e2773ed5cae92548d4508301ac0fe7515e5bb Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudha...@linux.ibm.com>
Date: Wed, 6 Apr 2022 18:17:43 +0530
Subject: [PATCH 28/32] fs/f2fs: Do not copy file names that are too long

A corrupt f2fs file system might specify a name length which is greater
than the maximum name length supported by the GRUB f2fs driver.

We will allocate enough memory to store the overly long name, but there
are only F2FS_NAME_LEN bytes in the source, so we would read past the end
of the source.

While checking directory entries, do not copy a file name with an invalid
length.

Signed-off-by: Sudhakar Kuppusamy <sudha...@linux.ibm.com>
Signed-off-by: Daniel Axtens <d...@axtens.net>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/fs/f2fs.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
index 8898b235e0..df6beb544c 100644
--- a/grub-core/fs/f2fs.c
+++ b/grub-core/fs/f2fs.c
@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx 
*ctx)
 
       ftype = ctx->dentry[i].file_type;
       name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len);
+
+      if (name_len >= F2FS_NAME_LEN)
+        return 0;
+
       filename = grub_malloc (name_len + 1);
       if (!filename)
         return 0;
-- 
2.34.1


++++++ 0029-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch ++++++
>From c64e0158654a1098caf652f6ffd192cbe26583f3 Mon Sep 17 00:00:00 2001
From: Darren Kenny <darren.ke...@oracle.com>
Date: Tue, 29 Mar 2022 10:49:56 +0000
Subject: [PATCH 29/32] fs/btrfs: Fix several fuzz issues with invalid dir item
 sizing

According to the btrfs code in Linux, the structure of a directory item
leaf should be of the form:

  |struct btrfs_dir_item|name|data|

in GRUB the name len and data len are in the grub_btrfs_dir_item
structure's n and m fields respectively.

The combined size of the structure, name and data should be less than
the allocated memory, a difference to the Linux kernel's struct
btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for
where the name is stored, so we adjust for that too.

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

diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 42fdbaf616..626fd2daa0 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -2210,6 +2210,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
   grub_uint64_t tree;
   grub_uint8_t type;
   char *new_path = NULL;
+  grub_size_t est_size = 0;
 
   if (!data)
     return grub_errno;
@@ -2276,6 +2277,18 @@ grub_btrfs_dir (grub_device_t device, const char *path,
          break;
        }
 
+      if (direl == NULL ||
+         grub_add (grub_le_to_cpu16 (direl->n),
+                   grub_le_to_cpu16 (direl->m), &est_size) ||
+         grub_add (est_size, sizeof (*direl), &est_size) ||
+         grub_sub (est_size, sizeof (direl->name), &est_size) ||
+         est_size > allocated)
+       {
+         grub_errno = GRUB_ERR_OUT_OF_RANGE;
+         r = -grub_errno;
+         goto out;
+       }
+
       for (cdirel = direl;
           (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
           < (grub_ssize_t) elemsize;
@@ -2286,6 +2299,19 @@ grub_btrfs_dir (grub_device_t device, const char *path,
          char c;
          struct grub_btrfs_inode inode;
          struct grub_dirhook_info info;
+
+         if (cdirel == NULL ||
+             grub_add (grub_le_to_cpu16 (cdirel->n),
+                       grub_le_to_cpu16 (cdirel->m), &est_size) ||
+             grub_add (est_size, sizeof (*cdirel), &est_size) ||
+             grub_sub (est_size, sizeof (cdirel->name), &est_size) ||
+             est_size > allocated)
+          {
+            grub_errno = GRUB_ERR_OUT_OF_RANGE;
+            r = -grub_errno;
+            goto out;
+          }
+
          err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id,
                                       tree);
          grub_memset (&info, 0, sizeof (info));
-- 
2.34.1


++++++ 0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch ++++++
>From 2576115cc77c45d2a77d7629b8c2f26a3a58822b Mon Sep 17 00:00:00 2001
From: Darren Kenny <darren.ke...@oracle.com>
Date: Tue, 29 Mar 2022 15:52:46 +0000
Subject: [PATCH 30/32] fs/btrfs: Fix more ASAN and SEGV issues found with
 fuzzing

The fuzzer is generating btrfs file systems that have chunks with
invalid combinations of stripes and substripes for the given RAID
configurations.

After examining the Linux kernel fs/btrfs/tree-checker.c code, it
appears that sub-stripes should only be applied to RAID10, and in that
case there should only ever be 2 of them.

Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4
should have 2. 3 or 4 stripes respectively, which is what redundancy
corresponds.

Some of the chunks ended up with a size of 0, which grub_malloc() still
returned memory for and in turn generated ASAN errors later when
accessed.

While it would be possible to specifically limit the number of stripes,
a more correct test was on the combination of the chunk item, and the
number of stripes by the size of the chunk stripe structure in
comparison to the size of the chunk itself.

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

diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 626fd2daa0..62fe5e6a69 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -938,6 +938,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
        return grub_error (GRUB_ERR_BAD_FS,
                           "couldn't find the chunk descriptor");
 
+      if (!chsize)
+       {
+         grub_dprintf ("btrfs", "zero-size chunk\n");
+         return grub_error (GRUB_ERR_BAD_FS,
+                            "got an invalid zero-size chunk");
+       }
       chunk = grub_malloc (chsize);
       if (!chunk)
        return grub_errno;
@@ -996,6 +1002,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
              stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
                                             nstripes,
                                             NULL);
+
+             /* For single, there should be exactly 1 stripe. */
+             if (grub_le_to_cpu16 (chunk->nstripes) != 1)
+               {
+                 grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 
(%u)\n",
+                               grub_le_to_cpu16 (chunk->nstripes));
+                 return grub_error (GRUB_ERR_BAD_FS,
+                                    "invalid RAID_SINGLE: nstripes != 1 (%u)",
+                                     grub_le_to_cpu16 (chunk->nstripes));
+               }
              if (stripe_length == 0)
                stripe_length = 512;
              stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
@@ -1015,6 +1031,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
              stripen = 0;
              stripe_offset = off;
              csize = grub_le_to_cpu64 (chunk->size) - off;
+
+             /*
+             * Redundancy, and substripes only apply to RAID10, and there
+             * should be exactly 2 sub-stripes.
+             */
+            if (grub_le_to_cpu16 (chunk->nstripes) != redundancy)
+               {
+                 grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n",
+                               redundancy, grub_le_to_cpu16 (chunk->nstripes));
+                 return grub_error (GRUB_ERR_BAD_FS,
+                                    "invalid RAID1: nstripes != %u (%u)",
+                                    redundancy, grub_le_to_cpu16 
(chunk->nstripes));
+               }
              break;
            }
          case GRUB_BTRFS_CHUNK_TYPE_RAID0:
@@ -1051,6 +1080,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
              stripe_offset = low + chunk_stripe_length
                * high;
              csize = chunk_stripe_length - low;
+
+             /*
+              * Substripes only apply to RAID10, and there
+              * should be exactly 2 sub-stripes.
+              */
+             if (grub_le_to_cpu16 (chunk->nsubstripes) != 2)
+               {
+                 grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 
(%u)",
+                               grub_le_to_cpu16 (chunk->nsubstripes));
+                 return grub_error (GRUB_ERR_BAD_FS,
+                                    "invalid RAID10: nsubstripes != 2 (%u)",
+                                    grub_le_to_cpu16 (chunk->nsubstripes));
+               }
+
              break;
            }
          case GRUB_BTRFS_CHUNK_TYPE_RAID5:
@@ -1150,6 +1193,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
 
        for (j = 0; j < 2; j++)
          {
+           grub_size_t est_chunk_alloc = 0;
+
            grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
                          "+0x%" PRIxGRUB_UINT64_T
                          " (%d stripes (%d substripes) of %"
@@ -1162,6 +1207,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
            grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n",
                          addr);
 
+           if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe),
+                         grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) 
||
+               grub_add (est_chunk_alloc,
+                         sizeof (struct grub_btrfs_chunk_item), 
&est_chunk_alloc) ||
+               est_chunk_alloc > chunk->size)
+             {
+               err = GRUB_ERR_BAD_FS;
+               break;
+             }
+
            if (is_raid56)
              {
                err = btrfs_read_from_chunk (data, chunk, stripen,
-- 
2.34.1


++++++ 0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch ++++++
>From 480019e546386b8e25a26d03408897a7752b98b6 Mon Sep 17 00:00:00 2001
From: Darren Kenny <darren.ke...@oracle.com>
Date: Thu, 7 Apr 2022 15:18:12 +0000
Subject: [PATCH 31/32] fs/btrfs: Fix more fuzz issues related to chunks

The corpus was generating issues in grub_btrfs_read_logical() when
attempting to iterate over stripe entries in the superblock's
bootmapping.

In most cases the reason for the failure was that the number of stripes
in chunk->nstripes exceeded the possible space statically allocated in
superblock bootmapping space. Each stripe entry in the bootmapping block
consists of a grub_btrfs_key followed by a grub_btrfs_chunk_stripe.

Another issue that came up was that while calculating the chunk size,
in an earlier piece of code in that function, depending on the data
provided in the btrfs file system, it would end up calculating a size
that was too small to contain even 1 grub_btrfs_chunk_item, which is
obviously invalid too.

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

diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
index 62fe5e6a69..7007463c6e 100644
--- a/grub-core/fs/btrfs.c
+++ b/grub-core/fs/btrfs.c
@@ -944,6 +944,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
          return grub_error (GRUB_ERR_BAD_FS,
                             "got an invalid zero-size chunk");
        }
+
+      /*
+       * The space being allocated for a chunk should at least be able to
+       * contain one chunk item.
+       */
+      if (chsize < sizeof (struct grub_btrfs_chunk_item))
+       {
+         grub_dprintf ("btrfs", "chunk-size too small\n");
+         return grub_error (GRUB_ERR_BAD_FS,
+                            "got an invalid chunk size");
+       }
       chunk = grub_malloc (chsize);
       if (!chunk)
        return grub_errno;
@@ -1191,6 +1202,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
        if (csize > (grub_uint64_t) size)
          csize = size;
 
+       /*
+        * The space for a chunk stripe is limited to the space provide in the 
super-block's
+        * bootstrap mapping with an initial btrfs key at the start of each 
chunk.
+        */
+       grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) /
+         (sizeof (struct grub_btrfs_key) + sizeof (struct 
grub_btrfs_chunk_stripe));
+
        for (j = 0; j < 2; j++)
          {
            grub_size_t est_chunk_alloc = 0;
@@ -1217,6 +1235,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, 
grub_disk_addr_t addr,
                break;
              }
 
+          if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes)
+             {
+               err = GRUB_ERR_BAD_FS;
+               break;
+             }
+
            if (is_raid56)
              {
                err = btrfs_read_from_chunk (data, chunk, stripen,
-- 
2.34.1


++++++ 0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch ++++++
>From 836337d9b895da32bcbc451c84bc3a7865a15963 Mon Sep 17 00:00:00 2001
From: Michael Chang <mch...@suse.com>
Date: Mon, 18 Apr 2022 22:16:49 +0800
Subject: [PATCH 32/32] Use grub_loader_set_ex() for secureboot chainloader

This is required as many distributions, including SUSE, has been
shipping a variation to load and start image using native functions than
calling out efi protocols when secure boot is enabled and shim lock is
used to verify image.

Signed-off-by: Michael Chang <mch...@suse.com>
---
 grub-core/loader/efi/chainloader.c | 100 +++++++++++++++++++----------
 1 file changed, 66 insertions(+), 34 deletions(-)

diff --git a/grub-core/loader/efi/chainloader.c 
b/grub-core/loader/efi/chainloader.c
index b3e1e89302..48d69c7795 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -53,10 +53,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
 
 static grub_dl_t my_mod;
 
-static grub_ssize_t fsize;
-static grub_ssize_t cmdline_len;
-static grub_efi_handle_t dev_handle;
-
 #ifdef SUPPORT_SECURE_BOOT
 static grub_efi_boolean_t debug_secureboot = 0;
 static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle,  
grub_efi_system_table_t *system_table);
@@ -76,8 +72,6 @@ grub_chainloader_unload (void *context)
   b = grub_efi_system_table->boot_services;
   efi_call_1 (b->unload_image, image_handle);
 
-  dev_handle = 0;
-
   grub_dl_unref (my_mod);
   return GRUB_ERR_NONE;
 }
@@ -254,6 +248,17 @@ struct pe_coff_loader_image_context
   struct grub_pe32_header_no_msdos_stub *pe_hdr;
 };
 
+struct grub_secureboot_chainloader_context
+{
+  grub_efi_physical_address_t address;
+  grub_efi_uintn_t pages;
+  grub_ssize_t fsize;
+  grub_efi_device_path_t *file_path;
+  grub_efi_char16_t *cmdline;
+  grub_ssize_t cmdline_len;
+  grub_efi_handle_t dev_handle;
+};
+
 typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t;
 
 struct grub_efi_shim_lock
@@ -477,11 +482,13 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
 }
 
 static grub_efi_boolean_t
-handle_image (void *data, grub_efi_uint32_t datasize)
+handle_image (struct grub_secureboot_chainloader_context *load_context)
 {
   grub_efi_boot_services_t *b;
   grub_efi_loaded_image_t *li, li_bak;
   grub_efi_status_t efi_status;
+  void *data = (void *)(unsigned long)load_context->address;
+  grub_efi_uint32_t datasize = load_context->fsize;
   char *buffer = NULL;
   char *buffer_aligned = NULL;
   grub_efi_uint32_t i, size;
@@ -571,10 +578,10 @@ handle_image (void *data, grub_efi_uint32_t datasize)
   grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t));
   li->image_base = buffer_aligned;
   li->image_size = context.image_size;
-  li->load_options = cmdline;
-  li->load_options_size = cmdline_len;
-  li->file_path = grub_efi_get_media_file_path (file_path);
-  li->device_handle = dev_handle;
+  li->load_options = load_context->cmdline;
+  li->load_options_size = load_context->cmdline_len;
+  li->file_path = grub_efi_get_media_file_path (load_context->file_path);
+  li->device_handle = load_context->dev_handle;
   if (li->file_path)
     {
       grub_printf ("file path: ");
@@ -605,26 +612,27 @@ error_exit:
 }
 
 static grub_err_t
-grub_secureboot_chainloader_unload (void)
+grub_secureboot_chainloader_unload (void* context)
 {
   grub_efi_boot_services_t *b;
+  struct grub_secureboot_chainloader_context *sb_context = (struct 
grub_secureboot_chainloader_context *)context;
 
   b = grub_efi_system_table->boot_services;
-  efi_call_2 (b->free_pages, address, pages);
-  grub_free (file_path);
-  grub_free (cmdline);
-  cmdline = 0;
-  file_path = 0;
-  dev_handle = 0;
+  efi_call_2 (b->free_pages, sb_context->address, sb_context->pages);
+  grub_free (sb_context->file_path);
+  grub_free (sb_context->cmdline);
+  grub_free (sb_context);
 
   grub_dl_unref (my_mod);
   return GRUB_ERR_NONE;
 }
 
 static grub_err_t
-grub_secureboot_chainloader_boot (void)
+grub_secureboot_chainloader_boot (void *context)
 {
-  handle_image ((void *)address, fsize);
+  struct grub_secureboot_chainloader_context *sb_context = (struct 
grub_secureboot_chainloader_context *)context;
+
+  handle_image (sb_context);
   grub_loader_unset ();
   return grub_errno;
 }
@@ -635,6 +643,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
                      int argc, char *argv[])
 {
   grub_file_t file = 0;
+  grub_ssize_t size;
   grub_efi_status_t status;
   grub_efi_boot_services_t *b;
   grub_device_t dev = 0;
@@ -646,6 +655,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
   grub_efi_uintn_t pages = 0;
   grub_efi_char16_t *cmdline = NULL;
   grub_efi_handle_t image_handle = NULL;
+  grub_ssize_t cmdline_len = 0;
+  grub_efi_handle_t dev_handle = 0;
 
   if (argc == 0)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -653,8 +664,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
 
   grub_dl_ref (my_mod);
 
-  dev_handle = 0;
-
   b = grub_efi_system_table->boot_services;
 
   if (argc > 1)
@@ -732,14 +741,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
   grub_printf ("file path: ");
   grub_efi_print_device_path (file_path);
 
-  fsize = grub_file_size (file);
-  if (!fsize)
+  size = grub_file_size (file);
+  if (!size)
     {
       grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
                  filename);
       goto fail;
     }
-  pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12);
+  pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
 
   status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
                              GRUB_EFI_LOADER_CODE,
@@ -753,7 +762,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
     }
 
   boot_image = (void *) ((grub_addr_t) address);
-  if (grub_file_read (file, boot_image, fsize) != fsize)
+  if (grub_file_read (file, boot_image, size) != size)
     {
       if (grub_errno == GRUB_ERR_NONE)
        grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -763,7 +772,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
     }
 
 #if defined (__i386__) || defined (__x86_64__)
-  if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
+  if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
     {
       struct grub_macho_fat_header *head = boot_image;
       if (head->magic
@@ -786,30 +795,42 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
              > ~grub_cpu_to_le32 (archs[i].size)
              || grub_cpu_to_le32 (archs[i].offset)
              + grub_cpu_to_le32 (archs[i].size)
-             > (grub_size_t) fsize)
+             > (grub_size_t) size)
            {
              grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
                          filename);
              goto fail;
            }
          boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset);
-         fsize = grub_cpu_to_le32 (archs[i].size);
+         size = grub_cpu_to_le32 (archs[i].size);
        }
     }
 #endif
 
 #ifdef SUPPORT_SECURE_BOOT
   /* FIXME is secure boot possible also with universal binaries? */
-  if (debug_secureboot || (grub_efi_get_secureboot () == 
GRUB_EFI_SECUREBOOT_MODE_ENABLED && grub_secure_validate ((void *)address, 
fsize)))
+  if (debug_secureboot || (grub_efi_get_secureboot () == 
GRUB_EFI_SECUREBOOT_MODE_ENABLED && grub_secure_validate ((void *)address, 
size)))
     {
+      struct grub_secureboot_chainloader_context *sb_context;
+
+      sb_context = grub_malloc (sizeof (*sb_context));
+      if (!sb_context)
+       goto fail;
+      sb_context->cmdline = cmdline;
+      sb_context->cmdline_len = cmdline_len;
+      sb_context->fsize = size;
+      sb_context->dev_handle = dev_handle;
+      sb_context->address = address;
+      sb_context->pages = pages;
+      sb_context->file_path = file_path;
       grub_file_close (file);
-      grub_loader_set (grub_secureboot_chainloader_boot, 
grub_secureboot_chainloader_unload, 0);
+      grub_loader_set_ex (grub_secureboot_chainloader_boot, 
grub_secureboot_chainloader_unload, sb_context, 0);
       return 0;
     }
 #endif
 
   status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
-                      boot_image, fsize,
+                      boot_image, size,
                       &image_handle);
 #ifdef SUPPORT_SECURE_BOOT
   if (status == GRUB_EFI_SECURITY_VIOLATION && grub_efi_get_secureboot () != 
GRUB_EFI_SECUREBOOT_MODE_ENABLED)
@@ -817,10 +838,21 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
       /* If it failed with security violation while not in secure boot mode,
          the firmware might be broken. We try to workaround on that by forcing
          the SB method! (bsc#887793) */
+      struct grub_secureboot_chainloader_context *sb_context;
+
       grub_dprintf ("chain", "Possible firmware flaw! Security violation while 
not in secure boot mode.\n");
+      sb_context = grub_malloc (sizeof (*sb_context));
+      if (!sb_context)
+       goto fail;
+      sb_context->cmdline = cmdline;
+      sb_context->cmdline_len = cmdline_len;
+      sb_context->fsize = size;
+      sb_context->dev_handle = dev_handle;
+      sb_context->address = address;
+      sb_context->pages = pages;
       grub_file_close (file);
-      grub_loader_set (grub_secureboot_chainloader_boot,
-             grub_secureboot_chainloader_unload, 0);
+      grub_loader_set_ex (grub_secureboot_chainloader_boot,
+             grub_secureboot_chainloader_unload, sb_context, 0);
       return 0;
     }
 #endif
-- 
2.34.1

Reply via email to