diff --git a/.grub2.checksum b/.grub2.checksum
index 3a06e672051399458fc0be2952c6a6cba51bb50a..f5c6ecdb0639826138843e89284338ef38ecf588 100644
--- a/.grub2.checksum
+++ b/.grub2.checksum
@@ -1 +1 @@
-2a888a7fcc43f8ac42005d503f46b51eeb654d4025e6c584ae53b56d12bdca6a
+8e0ad9783c648f001168ba5876d58958a0be6c86f62e694babeb9cae5ff19ec6
diff --git a/.grub2.metadata b/.grub2.metadata
index 3f85c530aa3fbb2515ec19cfa452c54b9a65c497..15da87896cf4916bb143fa0360dd5dc98c96d613 100644
--- a/.grub2.metadata
+++ b/.grub2.metadata
@@ -1,4 +1,4 @@
-b79ea44af91b93d17cd3fe80bdae6ed43770678a9a5ae192ccea803ebb657ee1 SOURCES/grub-2.06.tar.xz
 f3bd4a5087865b78217fc68fe2d1abc8be90bd48e3b9cb077c1979441a6f9e8d SOURCES/gnulib-9f48fb992a3d7e96610c4ce8be969cff2d61a01b.tar.gz
+b79ea44af91b93d17cd3fe80bdae6ed43770678a9a5ae192ccea803ebb657ee1 SOURCES/grub-2.06.tar.xz
 1fddd06b4854598a18ff3742c472c6a5c609929ce1ab74ec9901812aaf30be02 SOURCES/theme.tar.bz2
 aea0ea746353c6c2b5b8874e65facd087bb0346ec198993f8aaaa21eea040378 SOURCES/unifont-13.0.06.pcf.gz
diff --git a/SOURCES/0329-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch b/SOURCES/0329-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2a8adf1c82ea09ac6846c0cb172a87a7cb0925d8
--- /dev/null
+++ b/SOURCES/0329-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch
@@ -0,0 +1,226 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Stefan Berger <stefanb@linux.ibm.com>
+Date: Tue, 25 Jul 2023 13:23:10 -0400
+Subject: [PATCH] kern/ieee1275/init: ppc64: Restrict high memory in presence
+ of fadump
+
+When a kernel dump is present then restrict the high memory regions to
+avoid allocating memory where the kernel dump resides. Use the
+ibm,kernel-dump node under /rtas to determine whether a kernel dump exists
+and up to which limit grub can use available memory. Set the
+upper_mem_limit to the size of the kernel dump section of type
+'REAL_MODE_REGION' and therefore only allow grub's memory usage for high
+addresses from RMO_ADDR_MAX to 'upper_mem_limit'. This means that grub can
+use high memory in the range of RMO_ADDR_MAX (768MB) to upper_mem_limit and
+the kernel-dump memory regions above 'upper_mem_limit' remain untouched.
+This change has no effect on memory allocations below 'linux_rmo_save'
+(typically at 640MB).
+
+Also, fall back to allocating below rmo_linux_save in case the chunk of
+memory there would be larger than the chunk of memory above RMO_ADDR_MAX.
+This can for example occur if a free memory area is found starting at 300MB
+extending up to 1GB but a kernel dump is located at 768MB and therefore
+does not allow the allocation of the high memory area but requiring to use
+the chunk starting at 300MB to avoid an unnecessary out-of-memory
+condition.
+
+Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
+Reviewed-by: Hari Bathini <hbathini@linux.ibm.com>
+Cc: Pavithra Prakash <pavrampu@in.ibm.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Carolyn Scherrer <cpscherr@us.ibm.com>
+Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
+Cc: Sourabh Jain <sourabhjain@linux.ibm.com>
+---
+ grub-core/kern/ieee1275/init.c | 144 ++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 142 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
+index 3d4ad9d..8e7f742 100644
+--- a/grub-core/kern/ieee1275/init.c
++++ b/grub-core/kern/ieee1275/init.c
+@@ -17,6 +17,8 @@
+  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+  */
+ 
++#include <stddef.h> /* offsetof() */
++
+ #include <grub/kernel.h>
+ #include <grub/dl.h>
+ #include <grub/disk.h>
+@@ -198,6 +200,96 @@ grub_claim_heap (void)
+ #else
+ /* Helpers for mm on powerpc. */
+ 
++/* ibm,kernel-dump data structures */
++struct kd_section
++{
++  grub_uint32_t flags;
++  grub_uint16_t src_datatype;
++#define KD_SRC_DATATYPE_REAL_MODE_REGION  0x0011
++  grub_uint16_t error_flags;
++  grub_uint64_t src_address;
++  grub_uint64_t num_bytes;
++  grub_uint64_t act_bytes;
++  grub_uint64_t dst_address;
++} GRUB_PACKED;
++
++#define MAX_KD_SECTIONS 10
++
++struct kernel_dump
++{
++  grub_uint32_t format;
++  grub_uint16_t num_sections;
++  grub_uint16_t status_flags;
++  grub_uint32_t offset_1st_section;
++  grub_uint32_t num_blocks;
++  grub_uint64_t start_block;
++  grub_uint64_t num_blocks_avail;
++  grub_uint32_t offet_path_string;
++  grub_uint32_t max_time_allowed;
++  struct kd_section kds[MAX_KD_SECTIONS]; /* offset_1st_section should point to kds[0] */
++} GRUB_PACKED;
++
++/*
++ * Determine if a kernel dump exists and if it does, then determine the highest
++ * address that grub can use for memory allocations.
++ * The caller must have initialized *highest to rmo_top. *highest will not
++ * be modified if no kernel dump is found.
++ */
++static void
++check_kernel_dump (grub_uint64_t *highest)
++{
++  struct kernel_dump kernel_dump;
++  grub_ssize_t kernel_dump_size;
++  grub_ieee1275_phandle_t rtas;
++  struct kd_section *kds;
++  grub_size_t i;
++
++  /* If there's a kernel-dump it must have at least one section */
++  if (grub_ieee1275_finddevice ("/rtas", &rtas) ||
++      grub_ieee1275_get_property (rtas, "ibm,kernel-dump", &kernel_dump,
++                                  sizeof (kernel_dump), &kernel_dump_size) ||
++      kernel_dump_size <= (grub_ssize_t) offsetof (struct kernel_dump, kds[1]))
++    return;
++
++  kernel_dump_size = grub_min (kernel_dump_size, (grub_ssize_t) sizeof (kernel_dump));
++
++  if (grub_be_to_cpu32 (kernel_dump.format) != 1)
++    {
++      grub_printf (_("Error: ibm,kernel-dump has an unexpected format version '%u'\n"),
++                   grub_be_to_cpu32 (kernel_dump.format));
++      return;
++    }
++
++  if (grub_be_to_cpu16 (kernel_dump.num_sections) > MAX_KD_SECTIONS)
++    {
++      grub_printf (_("Error: Too many kernel dump sections: %d\n"),
++                   grub_be_to_cpu32 (kernel_dump.num_sections));
++      return;
++    }
++
++  for (i = 0; i < grub_be_to_cpu16 (kernel_dump.num_sections); i++)
++    {
++      kds = (struct kd_section *) ((grub_addr_t) &kernel_dump +
++                                   grub_be_to_cpu32 (kernel_dump.offset_1st_section) +
++                                   i * sizeof (struct kd_section));
++      /* sanity check the address is within the 'kernel_dump' struct */
++      if ((grub_addr_t) kds > (grub_addr_t) &kernel_dump + kernel_dump_size + sizeof (*kds))
++        {
++          grub_printf (_("Error: 'kds' address beyond last available section\n"));
++          return;
++        }
++
++      if ((grub_be_to_cpu16 (kds->src_datatype) == KD_SRC_DATATYPE_REAL_MODE_REGION) &&
++          (grub_be_to_cpu64 (kds->src_address) == 0))
++        {
++          *highest = grub_min (*highest, grub_be_to_cpu64 (kds->num_bytes));
++          break;
++        }
++    }
++
++  return;
++}
++
+ /*
+  * How much memory does OF believe exists in total?
+  *
+@@ -277,10 +369,31 @@ regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
+    *
+    * Finally, we also want to make sure that when grub loads the kernel,
+    * it isn't going to use up all the memory we're trying to reserve! So
+-   * enforce our entire RUNTIME_MIN_SPACE here:
++   * enforce our entire RUNTIME_MIN_SPACE here (no fadump):
++   *
++   * | Top of memory == upper_mem_limit -|
++   * |                                   |
++   * |             available             |
++   * |                                   |
++   * |----------     768 MB    ----------|
++   * |                                   |
++   * |              reserved             |
++   * |                                   |
++   * |--- 768 MB - runtime min space  ---|
++   * |                                   |
++   * |             available             |
++   * |                                   |
++   * |----------      0 MB     ----------|
++   *
++   * In case fadump is used, we allow the following:
+    *
+    * |---------- Top of memory ----------|
+    * |                                   |
++   * |             unavailable           |
++   * |         (kernel dump area)        |
++   * |                                   |
++   * |--------- upper_mem_limit ---------|
++   * |                                   |
+    * |             available             |
+    * |                                   |
+    * |----------     768 MB    ----------|
+@@ -335,17 +448,44 @@ regions_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
+         }
+       else
+         {
++          grub_uint64_t upper_mem_limit = rmo_top;
++          grub_uint64_t orig_addr = addr;
++
++          check_kernel_dump (&upper_mem_limit);
++
+           /*
+            * we order these cases to prefer higher addresses and avoid some
+            * splitting issues
++           * The following shows the order of variables:
++           *  no   kernel dump: linux_rmo_save < RMO_ADDR_MAX <= upper_mem_limit == rmo_top
++           *  with kernel dump: liuxx_rmo_save < RMO_ADDR_MAX <= upper_mem_limit <= rmo_top
+            */
+-          if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX)
++          if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX && upper_mem_limit >= RMO_ADDR_MAX)
+             {
+               grub_dprintf ("ieee1275",
+                             "adjusting region for RUNTIME_MIN_SPACE: (%llx -> %llx) -> (%llx -> %llx)\n",
+                             addr, addr + len, RMO_ADDR_MAX, addr + len);
+               len = (addr + len) - RMO_ADDR_MAX;
+               addr = RMO_ADDR_MAX;
++
++              /* We must not exceed the upper_mem_limit (assuming it's >= RMO_ADDR_MAX) */
++              if (addr + len > upper_mem_limit)
++                {
++                  /* take the bigger chunk from either below linux_rmo_save or above upper_mem_limit */
++                  len = upper_mem_limit - addr;
++                  if (orig_addr < linux_rmo_save && linux_rmo_save - orig_addr > len)
++                    {
++                      /* lower part is bigger */
++                      addr = orig_addr;
++                      len = linux_rmo_save - addr;
++                    }
++
++                  grub_dprintf ("ieee1275", "re-adjusted region to: (%llx -> %llx)\n",
++                                addr, addr + len);
++
++                  if (len == 0)
++                    return 0;
++                }
+             }
+           else if ((addr < linux_rmo_save) && ((addr + len) > linux_rmo_save))
+             {
diff --git a/SOURCES/0330-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch b/SOURCES/0330-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch
new file mode 100644
index 0000000000000000000000000000000000000000..900c59a0d9908f0aa15fb7eb299aaaefceeb1b15
--- /dev/null
+++ b/SOURCES/0330-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Nicolas Frayer <nfrayer@redhat.com>
+Date: Tue, 19 Dec 2023 16:52:05 +0100
+Subject: [PATCH] normal: Remove grub_env_set prefix in grub_try_normal_prefix
+
+Commit de735a453aa35 added a grub_env_set where the prefix contains
+the arch name in the pathname. This create issues when trying to
+load modules using this prefix as the pathname contains a "doubled"
+arch name in it (ie .../powerpc-ieee1275/powerpc-ieee1275/).
+
+Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
+---
+ grub-core/normal/main.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index d59145f861d5..bac7b8a0e1d8 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -372,7 +372,6 @@ grub_try_normal_prefix (const char *prefix)
+            file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+            if (file)
+              {
+-               grub_env_set ("prefix", prefix);
+                grub_file_close (file);
+                err = GRUB_ERR_NONE;
+              }
diff --git a/SOURCES/0331-search-command-add-flag-to-only-search-root-dev.patch b/SOURCES/0331-search-command-add-flag-to-only-search-root-dev.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5079ee9a22c8d948abdd32aaa81189f13041754d
--- /dev/null
+++ b/SOURCES/0331-search-command-add-flag-to-only-search-root-dev.patch
@@ -0,0 +1,159 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Marta Lewandowska <mlewando@redhat.com>
+Date: Mon, 9 Oct 2023 08:53:18 +0200
+Subject: [PATCH] search command: add flag to only search root dev
+
+bz#2223437
+Signed-off-by: Marta Lewandowska <mlewando@redhat.com>
+---
+ grub-core/commands/search.c      | 36 ++++++++++++++++++++++++++++++++++++
+ grub-core/commands/search_wrap.c |  5 +++++
+ grub-core/kern/misc.c            | 30 ++++++++++++++++++++++++++++++
+ include/grub/misc.h              |  1 +
+ include/grub/search.h            |  3 ++-
+ 5 files changed, 74 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
+index 57d26ced8a8e..94fe8b2872a1 100644
+--- a/grub-core/commands/search.c
++++ b/grub-core/commands/search.c
+@@ -85,6 +85,42 @@ iterate_device (const char *name, void *data)
+       grub_device_close (dev);
+     }
+ 
++  /* Skip it if it's not the root device when requested. */
++  if (ctx->flags & SEARCH_FLAGS_ROOTDEV_ONLY)
++    {
++      const char *root_dev;
++      root_dev = grub_env_get ("root");
++      if (root_dev != NULL && *root_dev != '\0')
++      {
++        char *root_disk = grub_malloc (grub_strlen(root_dev) + 1);
++        char *name_disk = grub_malloc (grub_strlen(name) + 1);
++        char *rem_1 = grub_malloc(grub_strlen(root_dev) + 1);
++        char *rem_2 = grub_malloc(grub_strlen(name) + 1);
++
++	if (root_disk != NULL && name_disk != NULL &&
++	    rem_1 != NULL && rem_2 != NULL)
++     {
++            /* get just the disk name; partitions will be different. */
++            grub_str_sep (root_dev, root_disk, ',', rem_1);
++            grub_str_sep (name, name_disk, ',', rem_2);
++            if (root_disk != NULL && *root_disk != '\0' &&
++             name_disk != NULL && *name_disk != '\0')
++              if (grub_strcmp(root_disk, name_disk) != 0)
++                {
++                  grub_free (root_disk);
++                  grub_free (name_disk);
++                  grub_free (rem_1);
++                  grub_free (rem_2);
++                  return 0;
++                }
++	  }
++        grub_free (root_disk);
++        grub_free (name_disk);
++        grub_free (rem_1);
++        grub_free (rem_2);
++      }
++    }
++
+ #ifdef DO_SEARCH_FS_UUID
+ #define compare_fn grub_strcasecmp
+ #else
+diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
+index 0b62acf85359..06b5f51eefb5 100644
+--- a/grub-core/commands/search_wrap.c
++++ b/grub-core/commands/search_wrap.c
+@@ -41,6 +41,7 @@ static const struct grub_arg_option options[] =
+      ARG_TYPE_STRING},
+     {"no-floppy",	'n', 0, N_("Do not probe any floppy drive."), 0, 0},
+     {"efidisk-only",	0, 0, N_("Only probe EFI disks."), 0, 0},
++    {"root-dev-only",  'r', 0, N_("Only probe root device."), 0, 0},
+     {"hint",	        'h', GRUB_ARG_OPTION_REPEATABLE,
+      N_("First try the device HINT. If HINT ends in comma, "
+ 	"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
+@@ -75,6 +76,7 @@ enum options
+     SEARCH_SET,
+     SEARCH_NO_FLOPPY,
+     SEARCH_EFIDISK_ONLY,
++    SEARCH_ROOTDEV_ONLY,
+     SEARCH_HINT,
+     SEARCH_HINT_IEEE1275,
+     SEARCH_HINT_BIOS,
+@@ -189,6 +191,9 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
+   if (state[SEARCH_EFIDISK_ONLY].set)
+     flags |= SEARCH_FLAGS_EFIDISK_ONLY;
+ 
++  if (state[SEARCH_ROOTDEV_ONLY].set)
++    flags |= SEARCH_FLAGS_ROOTDEV_ONLY;
++
+   if (state[SEARCH_LABEL].set)
+     grub_search_label (id, var, flags, hints, nhints);
+   else if (state[SEARCH_FS_UUID].set)
+diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
+index cb454614022f..50af9ee1bdd9 100644
+--- a/grub-core/kern/misc.c
++++ b/grub-core/kern/misc.c
+@@ -619,6 +619,36 @@ grub_reverse (char *str)
+     }
+ }
+ 
++/* Separate string into two parts, broken up by delimiter delim. */
++void
++grub_str_sep (const char *s, char *p, char delim, char *r)
++{
++  char* t = grub_strndup(s, grub_strlen(s));
++
++  if (t != NULL && *t != '\0')
++  {
++    char* tmp = t;
++
++    while (((*p = *t) != '\0') && ((*p = *t) != delim))
++    {
++      p++;
++      t++;
++    }
++    *p = '\0';
++
++    if (*t != '\0')
++    {
++      t++;
++      while ((*r++ = *t++) != '\0')
++        ;
++      *r = '\0';
++    }
++    grub_free (tmp);
++  }
++  else
++    grub_free (t);
++}
++
+ /* Divide N by D, return the quotient, and store the remainder in *R.  */
+ grub_uint64_t
+ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
+diff --git a/include/grub/misc.h b/include/grub/misc.h
+index faae0ae8606c..981526644d29 100644
+--- a/include/grub/misc.h
++++ b/include/grub/misc.h
+@@ -314,6 +314,7 @@ void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n);
+ grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) WARN_UNUSED_RESULT;
+ int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2)));
+ int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 1, 2)));
++void EXPORT_FUNC(grub_str_sep) (const char *s, char *p, char delim, char *r);
+ 
+ /* Replace all `ch' characters of `input' with `with' and copy the
+    result into `output'; return EOS address of `output'. */
+diff --git a/include/grub/search.h b/include/grub/search.h
+index 4190aeb2cbf5..321d1400e451 100644
+--- a/include/grub/search.h
++++ b/include/grub/search.h
+@@ -22,7 +22,8 @@
+ enum search_flags
+   {
+     SEARCH_FLAGS_NO_FLOPPY	= 1,
+-    SEARCH_FLAGS_EFIDISK_ONLY	= 2
++    SEARCH_FLAGS_EFIDISK_ONLY	= 2,
++    SEARCH_FLAGS_ROOTDEV_ONLY	= 4
+   };
+ 
+ void grub_search_fs_file (const char *key, const char *var,
diff --git a/SOURCES/0332-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch b/SOURCES/0332-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d20f909b905af019cb8ffe0a98f7b2679cf7c1b0
--- /dev/null
+++ b/SOURCES/0332-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch
@@ -0,0 +1,146 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Solar Designer <solar@openwall.com>
+Date: Tue, 6 Feb 2024 21:39:41 +0100
+Subject: [PATCH] grub-set-bootflag: Conservative partial fix for CVE-2024-1048
+
+Following up on CVE-2019-14865 and taking a fresh look at
+grub2-set-bootflag now (through my work at CIQ on Rocky Linux), I saw some
+other ways in which users could still abuse this little program:
+
+1. After CVE-2019-14865 fix, grub2-set-bootflag no longer rewrites the
+grubenv file in-place, but writes into a temporary file and renames it
+over the original, checking for error returns from each call first.
+This prevents the original file truncation vulnerability, but it can
+leave the temporary file around if the program is killed before it can
+rename or remove the file.  There are still many ways to get the program
+killed, such as through RLIMIT_FSIZE triggering SIGXFSZ (tested,
+reliable) or by careful timing (tricky) of signals sent by process group
+leader, pty, pre-scheduled timers, SIGXCPU (probably not an exhaustive
+list).  Invoking the program multiple times fills up /boot (or if /boot
+is not separate, then it can fill up the root filesystem).  Since the
+files are tiny, the filesystem is likely to run out of free inodes
+before it'd run out of blocks, but the effect is similar - can't create
+new files after this point (but still can add data to existing files,
+such as logs).
+
+2. After CVE-2019-14865 fix, grub2-set-bootflag naively tries to protect
+itself from signals by becoming full root.  (This does protect it from
+signals sent by the user directly to the PID, but e.g. "kill -9 -1" by
+the user still works.)  A side effect of such "protection" is that it's
+possible to invoke more concurrent instances of grub2-set-bootflag than
+the user's RLIMIT_NPROC would normally permit (as specified e.g. in
+/etc/security/limits.conf, or say in Apache httpd's RLimitNPROC if
+grub2-set-bootflag would be abused by a website script), thereby
+exhausting system resources (e.g., bypassing RAM usage limit if
+RLIMIT_AS was also set).
+
+3. umask is inherited.  Again, due to how the CVE-2019-14865 fix creates
+a new file, and due to how mkstemp() works, this affects grubenv's new
+file permissions.  Luckily, mkstemp() forces them to be no more relaxed
+than 0600, but the user ends up being able to set them e.g. to 0.
+Luckily, at least in my testing GRUB still works fine even when the file
+has such (lack of) permissions.
+
+This commit deals with the abuses above as follows:
+
+1. RLIMIT_FSIZE is pre-checked, so this specific way to get the process
+killed should no longer work.  However, this isn't a complete fix
+because there are other ways to get the process killed after it has
+created the temporary file.
+
+The commit also fixes bug 1975892 ("RFE: grub2-set-bootflag should not
+write the grubenv when the flag being written is already set") and
+similar for "menu_show_once", which further reduces the abuse potential.
+
+2. RLIMIT_NPROC bypass should be avoided by not becoming full root (aka
+dropping the partial "kill protection").
+
+3. A safe umask is set.
+
+This is a partial fix (temporary files can still accumulate, but this is
+harder to trigger).
+
+While at it, this commit also fixes potential 1- or 2-byte over-read of
+env[] if its content is malformed - this was not a security issue since the
+grubenv file is trusted input, and the fix is just for robustness.
+
+Signed-off-by: Solar Designer <solar@openwall.com>
+---
+ util/grub-set-bootflag.c | 29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c
+index 3b4c25ca2ac6..5bbbef804391 100644
+--- a/util/grub-set-bootflag.c
++++ b/util/grub-set-bootflag.c
+@@ -33,6 +33,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <sys/stat.h>
++#include <sys/resource.h>
+ 
+ #include "progname.h"
+ 
+@@ -57,12 +59,17 @@ static void usage(FILE *out)
+ int main(int argc, char *argv[])
+ {
+   /* NOTE buf must be at least the longest bootflag length + 4 bytes */
+-  char env[GRUBENV_SIZE + 1], buf[64], *s;
++  char env[GRUBENV_SIZE + 1 + 2], buf[64], *s;
+   /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */
+   char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1];
+   const char *bootflag;
+   int i, fd, len, ret;
+   FILE *f;
++  struct rlimit rlim;
++
++  if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE)
++    return 1;
++  umask(077);
+ 
+   if (argc != 2)
+     {
+@@ -94,20 +101,11 @@ int main(int argc, char *argv[])
+   len = strlen (bootflag);
+ 
+   /*
+-   * Really become root. setuid avoids an user killing us, possibly leaking
+-   * the tmpfile. setgid avoids the new grubenv's gid being that of the user.
++   * setegid avoids the new grubenv's gid being that of the user.
+    */
+-  ret = setuid(0);
+-  if (ret)
++  if (setegid(0))
+     {
+-      perror ("Error setuid(0) failed");
+-      return 1;
+-    }
+-
+-  ret = setgid(0);
+-  if (ret)
+-    {
+-      perror ("Error setgid(0) failed");
++      perror ("Error setegid(0) failed");
+       return 1;
+     }
+ 
+@@ -136,6 +134,9 @@ int main(int argc, char *argv[])
+ 
+   /* 0 terminate env */
+   env[GRUBENV_SIZE] = 0;
++  /* not a valid flag value */
++  env[GRUBENV_SIZE + 1] = 0;
++  env[GRUBENV_SIZE + 2] = 0;
+ 
+   if (strncmp (env, GRUB_ENVBLK_SIGNATURE, strlen (GRUB_ENVBLK_SIGNATURE)))
+     {
+@@ -171,6 +172,8 @@ int main(int argc, char *argv[])
+ 
+   /* The grubenv is not 0 terminated, so memcpy the name + '=' , '1', '\n' */
+   snprintf(buf, sizeof(buf), "%s=1\n", bootflag);
++  if (!memcmp(s, buf, len + 3))
++    return 0; /* nothing to do */
+   memcpy(s, buf, len + 3);
+ 
+ 
diff --git a/SOURCES/0333-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch b/SOURCES/0333-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b47b3110380eb85b40aded0a77047fc22e03e637
--- /dev/null
+++ b/SOURCES/0333-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch
@@ -0,0 +1,187 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Solar Designer <solar@openwall.com>
+Date: Tue, 6 Feb 2024 21:56:21 +0100
+Subject: [PATCH] grub-set-bootflag: More complete fix for CVE-2024-1048
+
+Switch to per-user fixed temporary filenames along with a weird locking
+mechanism, which is explained in source code comments.  This is a more
+complete fix than the previous commit (temporary files can't accumulate).
+Unfortunately, it introduces new risks (by working on a temporary file
+shared between the user's invocations), which are _hopefully_ avoided by
+the patch's elaborate logic.  I actually got it wrong at first, which
+suggests that this logic is hard to reason about, and more errors or
+omissions are possible.  It also relies on the kernel's primitives' exact
+semantics to a greater extent (nothing out of the ordinary, though).
+
+Remaining issues that I think cannot reasonably be fixed without a
+redesign (e.g., having per-flag files with nothing else in them) and
+without introducing new issues:
+
+A. A user can still revert a concurrent user's attempt of setting the
+other flag - or of making other changes to grubenv by means other than
+this program.
+
+B. One leftover temporary file per user is still possible.
+
+Signed-off-by: Solar Designer <solar@openwall.com>
+---
+ util/grub-set-bootflag.c | 95 ++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 79 insertions(+), 16 deletions(-)
+
+diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c
+index 5bbbef804391..514c4f9091ac 100644
+--- a/util/grub-set-bootflag.c
++++ b/util/grub-set-bootflag.c
+@@ -33,6 +33,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <sys/file.h>
+ #include <sys/stat.h>
+ #include <sys/resource.h>
+ 
+@@ -60,15 +61,12 @@ int main(int argc, char *argv[])
+ {
+   /* NOTE buf must be at least the longest bootflag length + 4 bytes */
+   char env[GRUBENV_SIZE + 1 + 2], buf[64], *s;
+-  /* +1 for 0 termination, +6 for "XXXXXX" in tmp filename */
+-  char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 6 + 1];
++  /* +1 for 0 termination, +11 for ".%u" in tmp filename */
++  char env_filename[PATH_MAX + 1], tmp_filename[PATH_MAX + 11 + 1];
+   const char *bootflag;
+   int i, fd, len, ret;
+   FILE *f;
+-  struct rlimit rlim;
+ 
+-  if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE)
+-    return 1;
+   umask(077);
+ 
+   if (argc != 2)
+@@ -105,7 +103,7 @@ int main(int argc, char *argv[])
+    */
+   if (setegid(0))
+     {
+-      perror ("Error setegid(0) failed");
++      perror ("setegid(0) failed");
+       return 1;
+     }
+ 
+@@ -176,19 +174,82 @@ int main(int argc, char *argv[])
+     return 0; /* nothing to do */
+   memcpy(s, buf, len + 3);
+ 
++  struct rlimit rlim;
++  if (getrlimit(RLIMIT_FSIZE, &rlim) || rlim.rlim_cur < GRUBENV_SIZE || rlim.rlim_max < GRUBENV_SIZE)
++    {
++      fprintf (stderr, "Resource limits undetermined or too low\n");
++      return 1;
++    }
++
++  /*
++   * Here we work under the premise that we shouldn't write into the target
++   * file directly because we might not be able to have all of our changes
++   * written completely and atomically.  That was CVE-2019-14865, known to
++   * have been triggerable via RLIMIT_FSIZE.  While we've dealt with that
++   * specific attack via the check above, there may be other possibilities.
++   */
+ 
+   /*
+    * Create a tempfile for writing the new env.  Use the canonicalized filename
+    * for the template so that the tmpfile is in the same dir / on same fs.
++   *
++   * We now use per-user fixed temporary filenames, so that a user cannot cause
++   * multiple files to accumulate.
++   *
++   * We don't use O_EXCL so that a stale temporary file doesn't prevent further
++   * usage of the program by the user.
+    */
+-  snprintf(tmp_filename, sizeof(tmp_filename), "%sXXXXXX", env_filename);
+-  fd = mkstemp(tmp_filename);
++  snprintf(tmp_filename, sizeof(tmp_filename), "%s.%u", env_filename, getuid());
++  fd = open(tmp_filename, O_CREAT | O_WRONLY, 0600);
+   if (fd == -1)
+     {
+       perror ("Creating tmpfile failed");
+       return 1;
+     }
+ 
++  /*
++   * The lock prevents the same user from reaching further steps ending in
++   * rename() concurrently, in which case the temporary file only partially
++   * written by one invocation could be renamed to the target file by another.
++   *
++   * The lock also guards the slow fsync() from concurrent calls.  After the
++   * first time that and the rename() complete, further invocations for the
++   * same flag become no-ops.
++   *
++   * We lock the temporary file rather than the target file because locking the
++   * latter would allow any user having SIGSTOP'ed their process to make all
++   * other users' invocations fail (or lock up if we'd use blocking mode).
++   *
++   * We use non-blocking mode (LOCK_NB) because the lock having been taken by
++   * another process implies that the other process would normally have already
++   * renamed the file to target by the time it releases the lock (and we could
++   * acquire it), so we'd be working directly on the target if we proceeded,
++   * which is undesirable, and we'd kind of fail on the already-done rename.
++   */
++  if (flock(fd, LOCK_EX | LOCK_NB))
++    {
++      perror ("Locking tmpfile failed");
++      return 1;
++    }
++
++  /*
++   * Deal with the potential that another invocation proceeded all the way to
++   * rename() and process exit while we were between open() and flock().
++   */
++  {
++    struct stat st1, st2;
++    if (fstat(fd, &st1) || stat(tmp_filename, &st2))
++      {
++        perror ("stat of tmpfile failed");
++        return 1;
++      }
++    if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
++      {
++        fprintf (stderr, "Another invocation won race\n");
++        return 1;
++      }
++  }
++
+   f = fdopen (fd, "w");
+   if (!f)
+     {
+@@ -213,6 +274,14 @@ int main(int argc, char *argv[])
+       return 1;     
+     }
+ 
++  ret = ftruncate (fileno (f), GRUBENV_SIZE);
++  if (ret)
++    {
++      perror ("Error truncating tmpfile");
++      unlink(tmp_filename);
++      return 1;
++    }
++
+   ret = fsync (fileno (f));
+   if (ret)
+     {
+@@ -221,15 +290,9 @@ int main(int argc, char *argv[])
+       return 1;
+     }
+ 
+-  ret = fclose (f);
+-  if (ret)
+-    {
+-      perror ("Error closing tmpfile");
+-      unlink(tmp_filename);
+-      return 1;
+-    }
+-
+   /*
++   * We must not close the file before rename() as that would remove the lock.
++   *
+    * And finally rename the tmpfile with the new env over the old env, the
+    * linux kernel guarantees that this is atomic (from a syscall pov).
+    */
diff --git a/SOURCES/0334-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch b/SOURCES/0334-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch
new file mode 100644
index 0000000000000000000000000000000000000000..dba46d4abea58b3a195e3ed3a5b591495f9260d6
--- /dev/null
+++ b/SOURCES/0334-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Solar Designer <solar@openwall.com>
+Date: Tue, 6 Feb 2024 22:05:45 +0100
+Subject: [PATCH] grub-set-bootflag: Exit calmly when not running as root
+
+Exit calmly when not installed SUID root and invoked by non-root.  This
+allows installing user/grub-boot-success.service unconditionally while
+supporting non-SUID installation of the program for some limited usage.
+
+Signed-off-by: Solar Designer <solar@openwall.com>
+---
+ util/grub-set-bootflag.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/util/grub-set-bootflag.c b/util/grub-set-bootflag.c
+index 514c4f9091ac..31a868aeca8a 100644
+--- a/util/grub-set-bootflag.c
++++ b/util/grub-set-bootflag.c
+@@ -98,6 +98,17 @@ int main(int argc, char *argv[])
+   bootflag = bootflags[i];
+   len = strlen (bootflag);
+ 
++  /*
++   * Exit calmly when not installed SUID root and invoked by non-root.  This
++   * allows installing user/grub-boot-success.service unconditionally while
++   * supporting non-SUID installation of the program for some limited usage.
++   */
++  if (geteuid())
++    {
++      printf ("grub-set-bootflag not running as root, no action taken\n");
++      return 0;
++    }
++
+   /*
+    * setegid avoids the new grubenv's gid being that of the user.
+    */
diff --git a/SOURCES/0335-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch b/SOURCES/0335-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8234f678acd863538d6bc57de1aee40a92d1776f
--- /dev/null
+++ b/SOURCES/0335-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch
@@ -0,0 +1,93 @@
+From 43651027d24e62a7a463254165e1e46e42aecdea Mon Sep 17 00:00:00 2001
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:31:57 +0300
+Subject: [PATCH 1/6] fs/ntfs: Fix an OOB write when parsing the
+ $ATTRIBUTE_LIST attribute for the $MFT file
+
+When parsing an extremely fragmented $MFT file, i.e., the file described
+using the $ATTRIBUTE_LIST attribute, current NTFS code will reuse a buffer
+containing bytes read from the underlying drive to store sector numbers,
+which are consumed later to read data from these sectors into another buffer.
+
+These sectors numbers, two 32-bit integers, are always stored at predefined
+offsets, 0x10 and 0x14, relative to first byte of the selected entry within
+the $ATTRIBUTE_LIST attribute. Usually, this won't cause any problem.
+
+However, when parsing a specially-crafted file system image, this may cause
+the NTFS code to write these integers beyond the buffer boundary, likely
+causing the GRUB memory allocator to misbehave or fail. These integers contain
+values which are controlled by on-disk structures of the NTFS file system.
+
+Such modification and resulting misbehavior may touch a memory range not
+assigned to the GRUB and owned by firmware or another EFI application/driver.
+
+This fix introduces checks to ensure that these sector numbers are never
+written beyond the boundary.
+
+Fixes: CVE-2023-4692
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index bbdbe24ada83..c3c4db117bba 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -184,7 +184,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+     }
+   if (at->attr_end)
+     {
+-      grub_uint8_t *pa;
++      grub_uint8_t *pa, *pa_end;
+ 
+       at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+       if (at->emft_buf == NULL)
+@@ -209,11 +209,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ 	    }
+ 	  at->attr_nxt = at->edat_buf;
+ 	  at->attr_end = at->edat_buf + u32at (pa, 0x30);
++	  pa_end = at->edat_buf + n;
+ 	}
+       else
+ 	{
+ 	  at->attr_nxt = at->attr_end + u16at (pa, 0x14);
+ 	  at->attr_end = at->attr_end + u32at (pa, 4);
++	  pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+ 	}
+       at->flags |= GRUB_NTFS_AF_ALST;
+       while (at->attr_nxt < at->attr_end)
+@@ -230,6 +232,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ 	  at->flags |= GRUB_NTFS_AF_GPOS;
+ 	  at->attr_cur = at->attr_nxt;
+ 	  pa = at->attr_cur;
++
++	  if ((pa >= pa_end) || (pa_end - pa < 0x18))
++	    {
++	      grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
++	      return NULL;
++	    }
++
+ 	  grub_set_unaligned32 ((char *) pa + 0x10,
+ 				grub_cpu_to_le32 (at->mft->data->mft_start));
+ 	  grub_set_unaligned32 ((char *) pa + 0x14,
+@@ -240,6 +249,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ 	    {
+ 	      if (*pa != attr)
+ 		break;
++
++              if ((pa >= pa_end) || (pa_end - pa < 0x18))
++                {
++	          grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
++	          return NULL;
++	        }
++
+ 	      if (read_attr
+ 		  (at, pa + 0x10,
+ 		   u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
+-- 
+2.43.0
+
diff --git a/SOURCES/0336-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch b/SOURCES/0336-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a90e077ee3f87e110f733ecf33622e69e0c4f00f
--- /dev/null
+++ b/SOURCES/0336-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch
@@ -0,0 +1,58 @@
+From 0ed2458cc4eff6d9a9199527e2a0b6d445802f94 Mon Sep 17 00:00:00 2001
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:32:33 +0300
+Subject: [PATCH 2/6] fs/ntfs: Fix an OOB read when reading data from the
+ resident $DATA attribute
+
+When reading a file containing resident data, i.e., the file data is stored in
+the $DATA attribute within the NTFS file record, not in external clusters,
+there are no checks that this resident data actually fits the corresponding
+file record segment.
+
+When parsing a specially-crafted file system image, the current NTFS code will
+read the file data from an arbitrary, attacker-chosen memory offset and of
+arbitrary, attacker-chosen length.
+
+This allows an attacker to display arbitrary chunks of memory, which could
+contain sensitive information like password hashes or even plain-text,
+obfuscated passwords from BS EFI variables.
+
+This fix implements a check to ensure that resident data is read from the
+corresponding file record segment only.
+
+Fixes: CVE-2023-4693
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index c3c4db117bba..a68e173d8285 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -401,7 +401,18 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
+     {
+       if (ofs + len > u32at (pa, 0x10))
+ 	return grub_error (GRUB_ERR_BAD_FS, "read out of range");
+-      grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len);
++
++      if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++	return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
++
++      if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++	return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
++
++      if (u16at (pa, 0x14) + u32at (pa, 0x10) >
++	  (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
++	return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
++
++      grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len);
+       return 0;
+     }
+ 
+-- 
+2.43.0
+
diff --git a/SOURCES/0337-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch b/SOURCES/0337-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fb3eb315347898c3a8c973e9294ad8b3bf11f05c
--- /dev/null
+++ b/SOURCES/0337-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch
@@ -0,0 +1,73 @@
+From 7e5f031a6a6a3decc2360a7b0c71abbe598e7354 Mon Sep 17 00:00:00 2001
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:33:17 +0300
+Subject: [PATCH 3/6] fs/ntfs: Fix an OOB read when parsing directory entries
+ from resident and non-resident index attributes
+
+This fix introduces checks to ensure that index entries are never read
+beyond the corresponding directory index.
+
+The lack of this check is a minor issue, likely not exploitable in any way.
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index a68e173d8285..2d78b96e19fb 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -599,7 +599,7 @@ get_utf8 (grub_uint8_t *in, grub_size_t len)
+ }
+ 
+ static int
+-list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
++list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos,
+ 	   grub_fshelp_iterate_dir_hook_t hook, void *hook_data)
+ {
+   grub_uint8_t *np;
+@@ -610,6 +610,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
+       grub_uint8_t namespace;
+       char *ustr;
+ 
++      if ((pos >= end_pos) || (end_pos - pos < 0x52))
++        break;
++
+       if (pos[0xC] & 2)		/* end signature */
+ 	break;
+ 
+@@ -617,6 +620,9 @@ list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos,
+       ns = *(np++);
+       namespace = *(np++);
+ 
++      if (2 * ns > end_pos - pos - 0x52)
++        break;
++
+       /*
+        *  Ignore files in DOS namespace, as they will reappear as Win32
+        *  names.
+@@ -806,7 +812,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+     }
+ 
+   cur_pos += 0x10;		/* Skip index root */
+-  ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook, hook_data);
++  ret = list_file (mft, cur_pos + u16at (cur_pos, 0),
++                   at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
++                   hook, hook_data);
+   if (ret)
+     goto done;
+ 
+@@ -893,6 +901,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ 			     (const grub_uint8_t *) "INDX")))
+ 		goto done;
+ 	      ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)],
++			       indx + (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
+ 			       hook, hook_data);
+ 	      if (ret)
+ 		goto done;
+-- 
+2.43.0
+
diff --git a/SOURCES/0338-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch b/SOURCES/0338-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c121cf3dec93f7632d3d63ba238f342687202330
--- /dev/null
+++ b/SOURCES/0338-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch
@@ -0,0 +1,51 @@
+From 7a5a116739fa6d8a625da7d6b9272c9a2462f967 Mon Sep 17 00:00:00 2001
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:33:44 +0300
+Subject: [PATCH 4/6] fs/ntfs: Fix an OOB read when parsing bitmaps for index
+ attributes
+
+This fix introduces checks to ensure that bitmaps for directory indices
+are never read beyond their actual sizes.
+
+The lack of this check is a minor issue, likely not exploitable in any way.
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index 2d78b96e19fb..bb70c89fb803 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -843,6 +843,25 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ 
+ 	  if (is_resident)
+ 	    {
++              if (bitmap_len > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++		{
++		  grub_error (GRUB_ERR_BAD_FS, "resident bitmap too large");
++		  goto done;
++		}
++
++              if (cur_pos >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++		{
++		  grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
++		  goto done;
++		}
++
++              if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) >
++		  (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos)
++		{
++		  grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
++		  goto done;
++		}
++
+               grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14),
+                            bitmap_len);
+ 	    }
+-- 
+2.43.0
+
diff --git a/SOURCES/0339-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch b/SOURCES/0339-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch
new file mode 100644
index 0000000000000000000000000000000000000000..efeb21d4319296e47f0bba0f6e3fc4213a8eca9a
--- /dev/null
+++ b/SOURCES/0339-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch
@@ -0,0 +1,61 @@
+From 1fe82c41e070385e273d7bb1cfb482627a3c28e8 Mon Sep 17 00:00:00 2001
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:38:19 +0300
+Subject: [PATCH 5/6] fs/ntfs: Fix an OOB read when parsing a volume label
+
+This fix introduces checks to ensure that an NTFS volume label is always
+read from the corresponding file record segment.
+
+The current NTFS code allows the volume label string to be read from an
+arbitrary, attacker-chosen memory location. However, the bytes read are
+always treated as UTF-16LE. So, the final string displayed is mostly
+unreadable and it can't be easily converted back to raw bytes.
+
+The lack of this check is a minor issue, likely not causing a significant
+data leak.
+
+Reported-by: Maxim Suhanov <dfirblog@gmail.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index bb70c89fb803..ff5e3740f0dd 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -1213,13 +1213,29 @@ grub_ntfs_label (grub_device_t device, char **label)
+ 
+   init_attr (&mft->attr, mft);
+   pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
++
++  if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++    {
++      grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
++      goto fail;
++    }
++
++  if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa < 0x16)
++    {
++      grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
++      goto fail;
++    }
++
+   if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
+     {
+       int len;
+ 
+       len = u32at (pa, 0x10) / 2;
+       pa += u16at (pa, 0x14);
+-      *label = get_utf8 (pa, len);
++      if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
++        *label = get_utf8 (pa, len);
++      else
++        grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label");
+     }
+ 
+ fail:
+-- 
+2.43.0
+
diff --git a/SOURCES/0340-fs-ntfs-Make-code-more-readable.patch b/SOURCES/0340-fs-ntfs-Make-code-more-readable.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2f00384e9a5db4382161b4b73534159ccf0835fa
--- /dev/null
+++ b/SOURCES/0340-fs-ntfs-Make-code-more-readable.patch
@@ -0,0 +1,159 @@
+From e58b870ff926415e23fc386af41ff81b2f588763 Mon Sep 17 00:00:00 2001
+From: Maxim Suhanov <dfirblog@gmail.com>
+Date: Mon, 28 Aug 2023 16:40:07 +0300
+Subject: [PATCH 6/6] fs/ntfs: Make code more readable
+
+Move some calls used to access NTFS attribute header fields into
+functions with human-readable names.
+
+Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
+Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
+Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
+---
+ grub-core/fs/ntfs.c | 48 +++++++++++++++++++++++++++++++--------------
+ 1 file changed, 33 insertions(+), 15 deletions(-)
+
+diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
+index ff5e3740f0dd..de435aa14d85 100644
+--- a/grub-core/fs/ntfs.c
++++ b/grub-core/fs/ntfs.c
+@@ -52,6 +52,24 @@ u64at (void *ptr, grub_size_t ofs)
+   return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs));
+ }
+ 
++static grub_uint16_t
++first_attr_off (void *mft_buf_ptr)
++{
++  return u16at (mft_buf_ptr, 0x14);
++}
++
++static grub_uint16_t
++res_attr_data_off (void *res_attr_ptr)
++{
++  return u16at (res_attr_ptr, 0x14);
++}
++
++static grub_uint32_t
++res_attr_data_len (void *res_attr_ptr)
++{
++  return u32at (res_attr_ptr, 0x10);
++}
++
+ grub_ntfscomp_func_t grub_ntfscomp_func;
+ 
+ static grub_err_t
+@@ -106,7 +124,7 @@ init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
+ {
+   at->mft = mft;
+   at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
+-  at->attr_nxt = mft->buf + u16at (mft->buf, 0x14);
++  at->attr_nxt = mft->buf + first_attr_off (mft->buf);
+   at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
+ }
+ 
+@@ -154,7 +172,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ 		    return NULL;
+ 		}
+ 
+-	      new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)];
++	      new_pos = &at->emft_buf[first_attr_off (at->emft_buf)];
+ 	      while (*new_pos != 0xFF)
+ 		{
+ 		  if ((*new_pos == *at->attr_cur)
+@@ -213,7 +231,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
+ 	}
+       else
+ 	{
+-	  at->attr_nxt = at->attr_end + u16at (pa, 0x14);
++	  at->attr_nxt = at->attr_end + res_attr_data_off (pa);
+ 	  at->attr_end = at->attr_end + u32at (pa, 4);
+ 	  pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
+ 	}
+@@ -399,20 +417,20 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
+ 
+   if (pa[8] == 0)
+     {
+-      if (ofs + len > u32at (pa, 0x10))
++      if (ofs + len > res_attr_data_len (pa))
+ 	return grub_error (GRUB_ERR_BAD_FS, "read out of range");
+ 
+-      if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
++      if (res_attr_data_len (pa) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ 	return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
+ 
+       if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
+ 	return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
+ 
+-      if (u16at (pa, 0x14) + u32at (pa, 0x10) >
++      if (res_attr_data_off (pa) + res_attr_data_len (pa) >
+ 	  (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
+ 	return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
+ 
+-      grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len);
++      grub_memcpy (dest, pa + res_attr_data_off (pa) + ofs, len);
+       return 0;
+     }
+ 
+@@ -556,7 +574,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno)
+ 			   (unsigned long long) mftno);
+ 
+       if (!pa[8])
+-	mft->size = u32at (pa, 0x10);
++	mft->size = res_attr_data_len (pa);
+       else
+ 	mft->size = u64at (pa, 0x30);
+ 
+@@ -805,7 +823,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ 	  (u32at (cur_pos, 0x18) != 0x490024) ||
+ 	  (u32at (cur_pos, 0x1C) != 0x300033))
+ 	continue;
+-      cur_pos += u16at (cur_pos, 0x14);
++      cur_pos += res_attr_data_off (cur_pos);
+       if (*cur_pos != 0x30)	/* Not filename index */
+ 	continue;
+       break;
+@@ -834,7 +852,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ 	{
+           int is_resident = (cur_pos[8] == 0);
+ 
+-          bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) :
++          bitmap_len = ((is_resident) ? res_attr_data_len (cur_pos) :
+                         u32at (cur_pos, 0x28));
+ 
+           bmp = grub_malloc (bitmap_len);
+@@ -855,14 +873,14 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
+ 		  goto done;
+ 		}
+ 
+-              if (u16at (cur_pos, 0x14) + u32at (cur_pos, 0x10) >
++              if (res_attr_data_off (cur_pos) + res_attr_data_len (cur_pos) >
+ 		  (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos)
+ 		{
+ 		  grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range");
+ 		  goto done;
+ 		}
+ 
+-              grub_memcpy (bmp, cur_pos + u16at (cur_pos, 0x14),
++              grub_memcpy (bmp, cur_pos + res_attr_data_off (cur_pos),
+                            bitmap_len);
+ 	    }
+           else
+@@ -1226,12 +1244,12 @@ grub_ntfs_label (grub_device_t device, char **label)
+       goto fail;
+     }
+ 
+-  if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
++  if ((pa) && (pa[8] == 0) && (res_attr_data_len (pa)))
+     {
+       int len;
+ 
+-      len = u32at (pa, 0x10) / 2;
+-      pa += u16at (pa, 0x14);
++      len = res_attr_data_len (pa) / 2;
++      pa += res_attr_data_off (pa);
+       if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len)
+         *label = get_utf8 (pa, len);
+       else
+-- 
+2.43.0
+
diff --git a/SOURCES/0341-grub_dl_set_mem_attrs-fix-format-string.patch b/SOURCES/0341-grub_dl_set_mem_attrs-fix-format-string.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a9315220a8b574df67c9b414be7750297ddc359d
--- /dev/null
+++ b/SOURCES/0341-grub_dl_set_mem_attrs-fix-format-string.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Fri, 7 Apr 2023 14:54:35 +0200
+Subject: [PATCH] grub_dl_set_mem_attrs(): fix format string
+
+The grub_dprintf() call for printing the message
+
+  updating attributes for GOT and trampolines
+
+passes the argument "mod->name", but the format string doesn't accept that
+argument.
+
+Print the module name too.
+
+Example output:
+
+> kern/dl.c:736: updating attributes for GOT and trampolines ("video_fb")
+
+Fixes: ad1b904d325b (nx: set page permissions for loaded modules.)
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ grub-core/kern/dl.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index ab9101a5ad1a..a97f4a8b1355 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -733,7 +733,8 @@ grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr)
+     {
+       tgsz = ALIGN_UP(tgsz, arch_addralign);
+ 
+-      grub_dprintf ("modules", "updating attributes for GOT and trampolines\n",
++      grub_dprintf ("modules",
++		    "updating attributes for GOT and trampolines (\"%s\")\n",
+ 		    mod->name);
+       grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X,
+ 			     GRUB_MEM_ATTR_W);
diff --git a/SOURCES/0342-grub_dl_set_mem_attrs-add-self-check-for-the-tramp-G.patch b/SOURCES/0342-grub_dl_set_mem_attrs-add-self-check-for-the-tramp-G.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1f70fef2dea073c62affacd461611e5cd7334b2e
--- /dev/null
+++ b/SOURCES/0342-grub_dl_set_mem_attrs-add-self-check-for-the-tramp-G.patch
@@ -0,0 +1,140 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Fri, 7 Apr 2023 16:21:54 +0200
+Subject: [PATCH] grub_dl_set_mem_attrs(): add self-check for the tramp/GOT
+ sizes
+
+On aarch64 UEFI, we currently have a crasher:
+
+  grub_dl_load_core()
+    grub_dl_load_core_noinit()
+
+      /* independent allocation: must remain writable */
+      mod = grub_zalloc();
+
+      /* allocates module image with incorrect tail alignment */
+      grub_dl_load_segments()
+
+      /* write-protecting the module image makes "mod" read-only! */
+      grub_dl_set_mem_attrs()
+        grub_update_mem_attrs()
+
+    grub_dl_init()
+      /* page fault, crash */
+      mod->next = ...;
+
+- Commit 887f1d8fa976 ("modules: load module sections at page-aligned
+  addresses", 2023-02-08) forgot to page-align the allocation of the
+  trampolines and GOT areas of grub2 modules, in grub_dl_load_segments().
+
+- Commit ad1b904d325b ("nx: set page permissions for loaded modules.",
+  2023-02-08) calculated a common bounding box for the trampolines and GOT
+  areas in grub_dl_set_mem_attrs(), rounded the box size up to a whole
+  multiple of EFI page size ("arch_addralign"), and write-protected the
+  resultant page range.
+
+Consequently, grub_dl_load_segments() places the module image in memory
+such that its tail -- the end of the trampolines and GOT areas -- lands at
+the head of a page whose tail in turn contains independent memory
+allocations, such as "mod". grub_dl_set_mem_attrs() will then unwittingly
+write-protect these other allocations too.
+
+But "mod" must remain writable: we assign "mod->next" in grub_dl_init()
+subsequently. Currently we crash there with a page fault / permission
+fault.
+
+(The crash is not trivial to hit: the tramp/GOT areas are irrelevant on
+x86_64, plus the page protection depends on the UEFI platform firmware
+providing EFI_MEMORY_ATTRIBUTE_PROTOCOL. In practice, the crash is
+restricted to aarch64 edk2 (ArmVirtQemu) builds containing commit
+1c4dfadb4611, "ArmPkg/CpuDxe: Implement EFI memory attributes protocol",
+2023-03-16.)
+
+Example log before the patch:
+
+> kern/dl.c:736: updating attributes for GOT and trampolines ("video_fb")
+> kern/efi/mm.c:927: set +rx -w on 0x13b88b000-0x13b88bfff before:rwx after:r-x
+> kern/dl.c:744: done updating module memory attributes for "video_fb"
+> kern/dl.c:639: flushing 0xe4f0 bytes at 0x13b87d000
+> kern/arm64/cache.c:42: D$ line size: 64
+> kern/arm64/cache.c:43: I$ line size: 64
+> kern/dl.c:839: module name: video_fb
+> kern/dl.c:840: init function: 0x0
+> kern/dl.c:865: Initing module video_fb
+>
+> Synchronous Exception at 0x000000013B8A76EC
+> PC 0x00013B8A76EC
+>
+>   X0 0x000000013B88B960   X1 0x0000000000000000   X2 0x000000013F93587C   X3 0x0000000000000075
+>
+>   SP 0x00000000470745C0  ELR 0x000000013B8A76EC  SPSR 0x60000205  FPSR 0x00000000
+>  ESR 0x9600004F          FAR 0x000000013B88B9D0
+>
+>  ESR : EC 0x25  IL 0x1  ISS 0x0000004F
+>
+> Data abort: Permission fault, third level
+
+Note the following:
+
+- The whole 4K page at 0x1_3B88_B000 is write-protected.
+
+- The "video_fb" module actually lives at [0x1_3B87_D000, 0x1_3B88_B4F0)
+  -- left-inclusive, right-exclusive --; that is, in the last page (at
+  0x1_3B88_B000), it only occupies the first 0x4F0 bytes.
+
+- The instruction at 0x1_3B8A_76EC faults. Not shown here, but it is a
+  store instruction, which writes to the field at offset 0x70 of the
+  structure pointed-to by the X0 register. This is the "mod->next"
+  assignment from grub_dl_init().
+
+- The faulting address is therefore (X0 + 0x70), i.e., 0x1_3B88_B9D0. This
+  is indeed the value held in the FAR register.
+
+- The faulting address 0x1_3B88_B9D0 falls in the above-noted page (at
+  0x1_3B88_B000), namely at offset 0x9D0. This is *beyond* the first 0x4F0
+  bytes that the very tail of the "video_fb" module occupies at the front
+  of that page.
+
+For now, add a self-check that reports this bug (and prevents the crash by
+skipping the write protection).
+
+Example log after the patch:
+
+> kern/dl.c:742:BUG: trying to protect pages outside of module allocation
+> ("video_fb"): module base 0x13b87d000, size 0xe4f0; tramp/GOT base
+> 0x13b88b000, size 0x1000
+
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ grub-core/kern/dl.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index a97f4a8b1355..3b66fa410e80 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -682,7 +682,7 @@ grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr)
+ #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv)
+   grub_size_t arch_addralign = grub_arch_dl_min_alignment ();
+   grub_addr_t tgaddr;
+-  grub_uint64_t tgsz;
++  grub_size_t tgsz;
+ #endif
+ 
+   grub_dprintf ("modules", "updating memory attributes for \"%s\"\n",
+@@ -736,6 +736,15 @@ grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr)
+       grub_dprintf ("modules",
+ 		    "updating attributes for GOT and trampolines (\"%s\")\n",
+ 		    mod->name);
++      if (tgaddr < (grub_addr_t)mod->base ||
++          tgsz > (grub_addr_t)-1 - tgaddr ||
++	  tgaddr + tgsz > (grub_addr_t)mod->base + mod->sz)
++	return grub_error (GRUB_ERR_BUG,
++			   "BUG: trying to protect pages outside of module "
++			   "allocation (\"%s\"): module base %p, size 0x%"
++			   PRIxGRUB_SIZE "; tramp/GOT base 0x%" PRIxGRUB_ADDR
++			   ", size 0x%" PRIxGRUB_SIZE,
++			   mod->name, mod->base, mod->sz, tgaddr, tgsz);
+       grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X,
+ 			     GRUB_MEM_ATTR_W);
+     }
diff --git a/SOURCES/0343-grub_dl_load_segments-page-align-the-tramp-GOT-areas.patch b/SOURCES/0343-grub_dl_load_segments-page-align-the-tramp-GOT-areas.patch
new file mode 100644
index 0000000000000000000000000000000000000000..45ab25366c662a3ed36a1bd184635ee5b84f8b56
--- /dev/null
+++ b/SOURCES/0343-grub_dl_load_segments-page-align-the-tramp-GOT-areas.patch
@@ -0,0 +1,70 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Fri, 7 Apr 2023 16:56:09 +0200
+Subject: [PATCH] grub_dl_load_segments(): page-align the tramp/GOT areas too
+
+The tramp/GOT write-protection in grub_dl_set_mem_attrs() requires that
+the tramp/GOT areas of the module image *not* share a page with any other
+memory allocations. Page-align the tramp/GOT areas, while satisfying their
+intrinsic alignment requirements too.
+
+Fixes: 887f1d8fa976 (modules: load module sections at page-aligned addresses)
+Fixes: ad1b904d325b (nx: set page permissions for loaded modules.)
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+---
+ grub-core/kern/dl.c | 24 ++++++++++++++++--------
+ 1 file changed, 16 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
+index 3b66fa410e80..f3cdb9e0bacf 100644
+--- a/grub-core/kern/dl.c
++++ b/grub-core/kern/dl.c
+@@ -280,7 +280,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
+   grub_size_t tsize = 0, talign = 1, arch_addralign = 1;
+ #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv)
+   grub_size_t tramp;
++  grub_size_t tramp_align;
+   grub_size_t got;
++  grub_size_t got_align;
+   grub_err_t err;
+ #endif
+   char *ptr;
+@@ -311,12 +313,18 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
+   err = grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
+   if (err)
+     return err;
+-  tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN);
+-  if (talign < GRUB_ARCH_DL_TRAMP_ALIGN)
+-    talign = GRUB_ARCH_DL_TRAMP_ALIGN;
+-  tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN);
+-  if (talign < GRUB_ARCH_DL_GOT_ALIGN)
+-    talign = GRUB_ARCH_DL_GOT_ALIGN;
++  tramp_align = GRUB_ARCH_DL_TRAMP_ALIGN;
++  if (tramp_align < arch_addralign)
++    tramp_align = arch_addralign;
++  tsize += ALIGN_UP (tramp, tramp_align);
++  if (talign < tramp_align)
++    talign = tramp_align;
++  got_align = GRUB_ARCH_DL_GOT_ALIGN;
++  if (got_align < arch_addralign)
++    got_align = arch_addralign;
++  tsize += ALIGN_UP (got, got_align);
++  if (talign < got_align)
++    talign = got_align;
+ #endif
+ 
+ #ifdef GRUB_MACHINE_EMU
+@@ -376,11 +384,11 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
+ 	}
+     }
+ #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv)
+-  ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
++  ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, tramp_align);
+   mod->tramp = ptr;
+   mod->trampptr = ptr;
+   ptr += tramp;
+-  ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN);
++  ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, got_align);
+   mod->got = ptr;
+   mod->gotptr = ptr;
+   ptr += got;
diff --git a/SOURCES/20-grub.install b/SOURCES/20-grub.install
index fe7ad8a5f5650e317224361b6e0e9a72c41bb43e..a3f1b18b9fedda68d657bede7924339cc3561bd6 100755
--- a/SOURCES/20-grub.install
+++ b/SOURCES/20-grub.install
@@ -19,6 +19,9 @@ MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID
 # If ${BOOT_DIR_ABS} exists, some other boot loader is active.
 [[ -d "${BOOT_DIR_ABS}" ]] && exit 0
 
+# UKIs are BLS type 2 entries, 90-uki-copy.install takes care of them
+[ "x$KERNEL_INSTALL_LAYOUT" != "xuki" ] || exit 0
+
 BLS_DIR="/boot/loader/entries"
 
 mkbls() {
diff --git a/SOURCES/grub.patches b/SOURCES/grub.patches
index b41fa9999f5730a6bcb9cfed9439b8b7b2b5d81f..7782ccdbccdd434cb2551c46245d1a8387187b65 100644
--- a/SOURCES/grub.patches
+++ b/SOURCES/grub.patches
@@ -326,4 +326,18 @@ Patch0325: 0325-kern-ieee1275-init-Extended-support-in-Vec5.patch
 Patch0326: 0326-efi-http-change-uint32_t-to-uintn_t.patch
 Patch0327: 0327-grub-mkconfig-dont-overwrite-BLS-cmdline-if-BLSCFG.patch
 Patch0328: 0328-grub2-mkconfig-Pass-all-boot-params-when-used-by-ana.patch
-Patch0329: 0329-search-command-add-flag-to-only-search-root-dev.patch
+Patch0329: 0329-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch
+Patch0330: 0330-normal-Remove-grub_env_set-prefix-in-grub_try_normal.patch
+Patch0331: 0331-search-command-add-flag-to-only-search-root-dev.patch
+Patch0332: 0332-grub-set-bootflag-Conservative-partial-fix-for-CVE-2.patch
+Patch0333: 0333-grub-set-bootflag-More-complete-fix-for-CVE-2024-104.patch
+Patch0334: 0334-grub-set-bootflag-Exit-calmly-when-not-running-as-ro.patch
+Patch0335: 0335-fs-ntfs-Fix-an-OOB-write-when-parsing-the-ATTRIBUTE_.patch
+Patch0336: 0336-fs-ntfs-Fix-an-OOB-read-when-reading-data-from-the-r.patch
+Patch0337: 0337-fs-ntfs-Fix-an-OOB-read-when-parsing-directory-entri.patch
+Patch0338: 0338-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch
+Patch0339: 0339-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch
+Patch0340: 0340-fs-ntfs-Make-code-more-readable.patch
+Patch0341: 0341-grub_dl_set_mem_attrs-fix-format-string.patch
+Patch0342: 0342-grub_dl_set_mem_attrs-add-self-check-for-the-tramp-G.patch
+Patch0343: 0343-grub_dl_load_segments-page-align-the-tramp-GOT-areas.patch
diff --git a/SPECS/grub2.spec b/SPECS/grub2.spec
index eb0c497108d6dd834677f4cb073b369b448457c8..822a8461abb3e288dd26d5ef244642944d7d90da 100644
--- a/SPECS/grub2.spec
+++ b/SPECS/grub2.spec
@@ -16,7 +16,7 @@
 Name: grub2
 Epoch: 1
 Version: 2.06
-Release: 70%{?dist}.2.rocky.0.5
+Release: 77%{?dist}
 Summary: Bootloader with support for Linux, Multiboot and more
 License: GPLv3+
 URL: http://www.gnu.org/software/grub/
@@ -534,32 +534,50 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
 %endif
 
 %changelog
-* Thu Apr 04 2024 Release Engineering <releng@rockylinux.org> - 2.06-70.rocky.0.5
+* Wed May 01 2024 Release Engineering <releng@rockylinux.org> - 2.06-77
 - Removing redhat old cert sources entries (Sherif Nagy)
-- Preserving rhel8 sbat entry based on shim-review feedback ticket no. 194
+- Preserving rhel9 sbat entry based on shim-review feedback ticket no. 194
 - Adding prod cert
-- Porting to 9.3
-- Cleaning up grup.macro extra signing certs and updating rocky test CA and CERT
+- Porting to 9.4
 - Cleaning up grup.macro extra signing certs
 - Adding Rocky testing CA, CERT and sbat files
 - Use DER for ppc64le builds from rocky-sb-certs (Louis Abel)
 
-* Thu Jan 4 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-70.el9_3.2
+* Thu Feb 22 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-77
+- kern/dl: grub_dl_set_mem_attrs()/grub_dl_load_segments() fixes
+- Resolves: #RHEL-26322
+
+* Tue Feb 20 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-76
+- fs/ntfs: OOB write fix
+- (CVE-2023-4692)
+- Resolves: #RHEL-11567
+
+* Wed Feb 7 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-75
+- grub-set-bootflag: Fix for CVE-2024-1048
+- (CVE-2024-1048)
+- Resolves: #RHEL-20747
+
+* Mon Feb 5 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-74
+- Don't run 20-grub.install for UKIs
+- Resolves: #RHEL-21368
+
+* Thu Jan 4 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-73
 - search command: add flag to only search root dev
-  (CVE-2023-4001)
-- Resolves: #RHEL-20525
+- Resolves: #RHEL-20526
+- Resolves: #CVE-2023-4001
 
-* Thu Sep 7 2023 Nicolas Frayer <nfrayer@redhat.com> - 2.06-70.el9_3.1
-- Bump spec release version
-- Related: #2203203
-- Related: #2212320
-- Related: #2221543
+* Thu Jan 4 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-72
+- normal: Remove grub_env_set prefix in grub_try_normal_prefix
+- Resolves: #RHEL-1601
+
+* Thu Oct 19 2023 Nicolas Frayer <nfrayer@redhat.com> - 2.06-71
+- kern/ieee1275/init: ppc64: Restrict high memory in presence
+  of fadump
+- Resolves: #RHEL-14282
 
 * Tue Aug 29 2023 Nicolas Frayer <nfrayer@redhat.com> - 2.06-70
 - grub2-mkconfig: Pass all boot params when used by anaconda
-- Resolves: #2203203
-- Resolves: #2212320
-- Resolves: #2221543
+- Resolves: #RHEL-2185
 
 * Thu Aug 24 2023 Nicolas Frayer <nfrayer@redhat.com> - 2.06-69
 - grub2-mkconfig: dont overwrite BLS cmdline if BLSCFG is true