CVE fixes for 2022-05-24
Resolves: CVE-2022-28736 CVE-2022-28735 CVE-2022-28734 CVE-2022-28733 Resolves: CVE-2021-3697 CVE-2021-3696 CVE-2021-3695 Signed-off-by: Robbie Harwood <rharwood@redhat.com>
This commit is contained in:
		
							parent
							
								
									a44a6377ed
								
							
						
					
					
						commit
						f0ad2aaa26
					
				@ -0,0 +1,69 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
Date: Thu, 28 Apr 2022 21:53:36 +0100
 | 
			
		||||
Subject: [PATCH] loader/efi/chainloader: grub_load_and_start_image doesn't
 | 
			
		||||
 load and start
 | 
			
		||||
 | 
			
		||||
grub_load_and_start_image only loads an image - it still requires the
 | 
			
		||||
caller to start it. This renames it to grub_load_image.
 | 
			
		||||
 | 
			
		||||
It's called from 2 places:
 | 
			
		||||
- grub_cmd_chainloader when not using the shim protocol.
 | 
			
		||||
- grub_secureboot_chainloader_boot if handle_image returns an error.
 | 
			
		||||
In this case, the image is loaded and then nothing else happens which
 | 
			
		||||
seems strange. I assume the intention is that it falls back to LoadImage
 | 
			
		||||
and StartImage if handle_image fails, so I've made it do that.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
(cherry picked from commit b4d70820a65c00561045856b7b8355461a9545f6)
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/efi/chainloader.c | 16 +++++++++++++---
 | 
			
		||||
 1 file changed, 13 insertions(+), 3 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
index 644cd2e56f..d3bf02ed8a 100644
 | 
			
		||||
--- a/grub-core/loader/efi/chainloader.c
 | 
			
		||||
+++ b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
@@ -841,7 +841,7 @@ grub_secureboot_chainloader_unload (void)
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_load_and_start_image(void *boot_image)
 | 
			
		||||
+grub_load_image(void *boot_image)
 | 
			
		||||
 {
 | 
			
		||||
   grub_efi_boot_services_t *b;
 | 
			
		||||
   grub_efi_status_t status;
 | 
			
		||||
@@ -883,13 +883,23 @@ grub_load_and_start_image(void *boot_image)
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
 grub_secureboot_chainloader_boot (void)
 | 
			
		||||
 {
 | 
			
		||||
+  grub_efi_boot_services_t *b;
 | 
			
		||||
   int rc;
 | 
			
		||||
+
 | 
			
		||||
   rc = handle_image ((void *)(unsigned long)address, fsize);
 | 
			
		||||
   if (rc == 0)
 | 
			
		||||
     {
 | 
			
		||||
-      grub_load_and_start_image((void *)(unsigned long)address);
 | 
			
		||||
+      /* We weren't able to attempt to execute the image, so fall back
 | 
			
		||||
+       * to LoadImage / StartImage.
 | 
			
		||||
+       */
 | 
			
		||||
+      rc = grub_load_image((void *)(unsigned long)address);
 | 
			
		||||
+      if (rc == 0)
 | 
			
		||||
+        grub_chainloader_boot ();
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+  b = grub_efi_system_table->boot_services;
 | 
			
		||||
+  efi_call_1 (b->unload_image, image_handle);
 | 
			
		||||
+
 | 
			
		||||
   grub_loader_unset ();
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
 }
 | 
			
		||||
@@ -1091,7 +1101,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
     }
 | 
			
		||||
   else
 | 
			
		||||
     {
 | 
			
		||||
-      grub_load_and_start_image(boot_image);
 | 
			
		||||
+      grub_load_image(boot_image);
 | 
			
		||||
       grub_file_close (file);
 | 
			
		||||
       grub_device_close (dev);
 | 
			
		||||
       grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
 | 
			
		||||
							
								
								
									
										330
									
								
								0221-loader-efi-chainloader-simplify-the-loader-state.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								0221-loader-efi-chainloader-simplify-the-loader-state.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,330 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
Date: Fri, 29 Apr 2022 21:13:08 +0100
 | 
			
		||||
Subject: [PATCH] loader/efi/chainloader: simplify the loader state
 | 
			
		||||
 | 
			
		||||
When not using the shim lock protocol, 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.
 | 
			
		||||
 | 
			
		||||
This also wraps the loader state when using the shim lock protocol
 | 
			
		||||
inside a struct.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
(cherry picked from commit fa39862933b3be1553a580a3a5c28073257d8046)
 | 
			
		||||
[rharwood: fix unitialized handle and double-frees of file/dev]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/efi/chainloader.c | 160 +++++++++++++++++++++++--------------
 | 
			
		||||
 1 file changed, 102 insertions(+), 58 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
index d3bf02ed8a..3342492ff1 100644
 | 
			
		||||
--- a/grub-core/loader/efi/chainloader.c
 | 
			
		||||
+++ b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
@@ -48,38 +48,21 @@ 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;
 | 
			
		||||
 
 | 
			
		||||
-static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
 | 
			
		||||
+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;
 | 
			
		||||
+};
 | 
			
		||||
+static struct grub_secureboot_chainloader_context *sb_context;
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_chainloader_unload (void)
 | 
			
		||||
-{
 | 
			
		||||
-  grub_efi_boot_services_t *b;
 | 
			
		||||
-
 | 
			
		||||
-  b = grub_efi_system_table->boot_services;
 | 
			
		||||
-  efi_call_1 (b->unload_image, image_handle);
 | 
			
		||||
-  grub_efi_free_pages (address, pages);
 | 
			
		||||
-
 | 
			
		||||
-  grub_free (file_path);
 | 
			
		||||
-  grub_free (cmdline);
 | 
			
		||||
-  cmdline = 0;
 | 
			
		||||
-  file_path = 0;
 | 
			
		||||
-  dev_handle = 0;
 | 
			
		||||
-
 | 
			
		||||
-  grub_dl_unref (my_mod);
 | 
			
		||||
-  return GRUB_ERR_NONE;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
-static grub_err_t
 | 
			
		||||
-grub_chainloader_boot (void)
 | 
			
		||||
+grub_start_image (grub_efi_handle_t handle)
 | 
			
		||||
 {
 | 
			
		||||
   grub_efi_boot_services_t *b;
 | 
			
		||||
   grub_efi_status_t status;
 | 
			
		||||
@@ -87,7 +70,7 @@ grub_chainloader_boot (void)
 | 
			
		||||
   grub_efi_char16_t *exit_data = NULL;
 | 
			
		||||
 
 | 
			
		||||
   b = grub_efi_system_table->boot_services;
 | 
			
		||||
-  status = efi_call_3 (b->start_image, image_handle, &exit_data_size, &exit_data);
 | 
			
		||||
+  status = efi_call_3 (b->start_image, handle, &exit_data_size, &exit_data);
 | 
			
		||||
   if (status != GRUB_EFI_SUCCESS)
 | 
			
		||||
     {
 | 
			
		||||
       if (exit_data)
 | 
			
		||||
@@ -111,11 +94,37 @@ grub_chainloader_boot (void)
 | 
			
		||||
   if (exit_data)
 | 
			
		||||
     grub_efi_free_pool (exit_data);
 | 
			
		||||
 
 | 
			
		||||
-  grub_loader_unset ();
 | 
			
		||||
-
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+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);
 | 
			
		||||
+
 | 
			
		||||
+  grub_dl_unref (my_mod);
 | 
			
		||||
+  return GRUB_ERR_NONE;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static grub_err_t
 | 
			
		||||
+grub_chainloader_boot (void)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_err_t err;
 | 
			
		||||
+
 | 
			
		||||
+  err = grub_start_image (image_handle);
 | 
			
		||||
+
 | 
			
		||||
+  grub_loader_unset ();
 | 
			
		||||
+  return err;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
 copy_file_path (grub_efi_file_path_device_path_t *fp,
 | 
			
		||||
 		const char *str, grub_efi_uint16_t len)
 | 
			
		||||
@@ -150,7 +159,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)
 | 
			
		||||
@@ -526,10 +535,12 @@ 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_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;
 | 
			
		||||
   void *buffer = NULL;
 | 
			
		||||
   char *buffer_aligned = NULL;
 | 
			
		||||
   grub_efi_uint32_t i;
 | 
			
		||||
@@ -540,6 +551,7 @@ handle_image (void *data, grub_efi_uint32_t datasize)
 | 
			
		||||
   grub_uint32_t buffer_size;
 | 
			
		||||
   int found_entry_point = 0;
 | 
			
		||||
   int rc;
 | 
			
		||||
+  grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
 | 
			
		||||
 
 | 
			
		||||
   rc = read_header (data, datasize, &context);
 | 
			
		||||
   if (rc < 0)
 | 
			
		||||
@@ -797,10 +809,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_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching file path found");
 | 
			
		||||
@@ -829,19 +841,22 @@ error_exit:
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
 grub_secureboot_chainloader_unload (void)
 | 
			
		||||
 {
 | 
			
		||||
-  grub_efi_free_pages (address, pages);
 | 
			
		||||
-  grub_free (file_path);
 | 
			
		||||
-  grub_free (cmdline);
 | 
			
		||||
-  cmdline = 0;
 | 
			
		||||
-  file_path = 0;
 | 
			
		||||
-  dev_handle = 0;
 | 
			
		||||
+  grub_efi_free_pages (sb_context->address, sb_context->pages);
 | 
			
		||||
+  grub_free (sb_context->file_path);
 | 
			
		||||
+  grub_free (sb_context->cmdline);
 | 
			
		||||
+  grub_free (sb_context);
 | 
			
		||||
+
 | 
			
		||||
+  sb_context = 0;
 | 
			
		||||
 
 | 
			
		||||
   grub_dl_unref (my_mod);
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_load_image(void *boot_image)
 | 
			
		||||
+grub_load_image(grub_efi_device_path_t *file_path, void *boot_image,
 | 
			
		||||
+		grub_efi_uintn_t image_size, grub_efi_handle_t dev_handle,
 | 
			
		||||
+		grub_efi_char16_t *cmdline, grub_ssize_t cmdline_len,
 | 
			
		||||
+		grub_efi_handle_t *image_handle_out)
 | 
			
		||||
 {
 | 
			
		||||
   grub_efi_boot_services_t *b;
 | 
			
		||||
   grub_efi_status_t status;
 | 
			
		||||
@@ -850,7 +865,7 @@ grub_load_image(void *boot_image)
 | 
			
		||||
   b = grub_efi_system_table->boot_services;
 | 
			
		||||
 
 | 
			
		||||
   status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
 | 
			
		||||
-		       boot_image, fsize, &image_handle);
 | 
			
		||||
+		       boot_image, image_size, image_handle_out);
 | 
			
		||||
   if (status != GRUB_EFI_SUCCESS)
 | 
			
		||||
     {
 | 
			
		||||
       if (status == GRUB_EFI_OUT_OF_RESOURCES)
 | 
			
		||||
@@ -863,7 +878,7 @@ grub_load_image(void *boot_image)
 | 
			
		||||
   /* LoadImage does not set a device handler when the image is
 | 
			
		||||
      loaded from memory, so it is necessary to set it explicitly here.
 | 
			
		||||
      This is a mess.  */
 | 
			
		||||
-  loaded_image = grub_efi_get_loaded_image (image_handle);
 | 
			
		||||
+  loaded_image = grub_efi_get_loaded_image (*image_handle_out);
 | 
			
		||||
   if (! loaded_image)
 | 
			
		||||
     {
 | 
			
		||||
       grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
 | 
			
		||||
@@ -885,20 +900,25 @@ grub_secureboot_chainloader_boot (void)
 | 
			
		||||
 {
 | 
			
		||||
   grub_efi_boot_services_t *b;
 | 
			
		||||
   int rc;
 | 
			
		||||
+  grub_efi_handle_t handle = 0;
 | 
			
		||||
 
 | 
			
		||||
-  rc = handle_image ((void *)(unsigned long)address, fsize);
 | 
			
		||||
+  rc = handle_image (sb_context);
 | 
			
		||||
   if (rc == 0)
 | 
			
		||||
     {
 | 
			
		||||
       /* We weren't able to attempt to execute the image, so fall back
 | 
			
		||||
        * to LoadImage / StartImage.
 | 
			
		||||
        */
 | 
			
		||||
-      rc = grub_load_image((void *)(unsigned long)address);
 | 
			
		||||
+      rc = grub_load_image(sb_context->file_path,
 | 
			
		||||
+			   (void *)(unsigned long)sb_context->address,
 | 
			
		||||
+			   sb_context->fsize, sb_context->dev_handle,
 | 
			
		||||
+			   sb_context->cmdline, sb_context->cmdline_len,
 | 
			
		||||
+			   &handle);
 | 
			
		||||
       if (rc == 0)
 | 
			
		||||
-        grub_chainloader_boot ();
 | 
			
		||||
+	grub_start_image (handle);
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
   b = grub_efi_system_table->boot_services;
 | 
			
		||||
-  efi_call_1 (b->unload_image, image_handle);
 | 
			
		||||
+  efi_call_1 (b->unload_image, handle);
 | 
			
		||||
 
 | 
			
		||||
   grub_loader_unset ();
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
@@ -913,9 +933,15 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_efi_boot_services_t *b;
 | 
			
		||||
   grub_device_t dev = 0;
 | 
			
		||||
   grub_device_t orig_dev = 0;
 | 
			
		||||
-  grub_efi_device_path_t *dp = 0;
 | 
			
		||||
+  grub_efi_device_path_t *dp = 0, *file_path = 0;
 | 
			
		||||
   char *filename;
 | 
			
		||||
   void *boot_image = 0;
 | 
			
		||||
+  grub_efi_physical_address_t address = 0;
 | 
			
		||||
+  grub_ssize_t fsize;
 | 
			
		||||
+  grub_efi_uintn_t pages = 0;
 | 
			
		||||
+  grub_efi_char16_t *cmdline = 0;
 | 
			
		||||
+  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"));
 | 
			
		||||
@@ -923,12 +949,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;
 | 
			
		||||
 
 | 
			
		||||
   if (argc > 1)
 | 
			
		||||
@@ -1093,17 +1113,35 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
 
 | 
			
		||||
   if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
 | 
			
		||||
     {
 | 
			
		||||
+      sb_context = grub_malloc (sizeof (*sb_context));
 | 
			
		||||
+      if (sb_context == NULL)
 | 
			
		||||
+        goto fail;
 | 
			
		||||
+      sb_context->address = address;
 | 
			
		||||
+      sb_context->fsize = fsize;
 | 
			
		||||
+      sb_context->pages = pages;
 | 
			
		||||
+      sb_context->file_path = file_path;
 | 
			
		||||
+      sb_context->cmdline = cmdline;
 | 
			
		||||
+      sb_context->cmdline_len = cmdline_len;
 | 
			
		||||
+      sb_context->dev_handle = dev_handle;
 | 
			
		||||
+
 | 
			
		||||
       grub_file_close (file);
 | 
			
		||||
       grub_device_close (dev);
 | 
			
		||||
+
 | 
			
		||||
       grub_loader_set (grub_secureboot_chainloader_boot,
 | 
			
		||||
 		       grub_secureboot_chainloader_unload, 0);
 | 
			
		||||
       return 0;
 | 
			
		||||
     }
 | 
			
		||||
   else
 | 
			
		||||
     {
 | 
			
		||||
-      grub_load_image(boot_image);
 | 
			
		||||
+      grub_load_image(file_path, boot_image, fsize, dev_handle, cmdline,
 | 
			
		||||
+		      cmdline_len, &image_handle);
 | 
			
		||||
       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;
 | 
			
		||||
@@ -1130,6 +1168,12 @@ fail:
 | 
			
		||||
   if (cmdline)
 | 
			
		||||
     grub_free (cmdline);
 | 
			
		||||
 
 | 
			
		||||
+  if (image_handle != 0)
 | 
			
		||||
+    {
 | 
			
		||||
+      efi_call_1 (b->unload_image, image_handle);
 | 
			
		||||
+      image_handle = 0;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
   grub_dl_unref (my_mod);
 | 
			
		||||
 
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
							
								
								
									
										158
									
								
								0222-commands-boot-Add-API-to-pass-context-to-loader.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								0222-commands-boot-Add-API-to-pass-context-to-loader.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,158 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
Date: Fri, 29 Apr 2022 21:16:02 +0100
 | 
			
		||||
Subject: [PATCH] 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.coulson@canonical.com>
 | 
			
		||||
(cherry picked from commit 4322a64dde7e8fedb58e50b79408667129d45dd3)
 | 
			
		||||
---
 | 
			
		||||
 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..53691a62d9 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 *);
 | 
			
		||||
+static grub_err_t (*grub_loader_unload_func) (void *);
 | 
			
		||||
+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 *),
 | 
			
		||||
+		    grub_err_t (*unload) (void *),
 | 
			
		||||
+		    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..1846fa6c5f 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 *),
 | 
			
		||||
+				       grub_err_t (*unload) (void *),
 | 
			
		||||
+				       void *context,
 | 
			
		||||
+				       int flags);
 | 
			
		||||
+
 | 
			
		||||
 /* Unset current loader, if any.  */
 | 
			
		||||
 void EXPORT_FUNC (grub_loader_unset) (void);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										147
									
								
								0223-loader-efi-chainloader-Use-grub_loader_set_ex.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								0223-loader-efi-chainloader-Use-grub_loader_set_ex.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,147 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
Date: Fri, 29 Apr 2022 21:30:56 +0100
 | 
			
		||||
Subject: [PATCH] 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.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
(cherry picked from commit 4b7f0402b7cb0f67a93be736f2b75b818d7f44c9)
 | 
			
		||||
[rharwood: context sludge from other change]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/efi/chainloader.c | 38 ++++++++++++++++++++++----------------
 | 
			
		||||
 1 file changed, 22 insertions(+), 16 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
index 3342492ff1..fb874f1855 100644
 | 
			
		||||
--- a/grub-core/loader/efi/chainloader.c
 | 
			
		||||
+++ b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
@@ -48,8 +48,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
 | 
			
		||||
 
 | 
			
		||||
 static grub_dl_t my_mod;
 | 
			
		||||
 
 | 
			
		||||
-static grub_efi_handle_t image_handle;
 | 
			
		||||
-
 | 
			
		||||
 struct grub_secureboot_chainloader_context {
 | 
			
		||||
   grub_efi_physical_address_t address;
 | 
			
		||||
   grub_efi_uintn_t pages;
 | 
			
		||||
@@ -59,7 +57,6 @@ struct grub_secureboot_chainloader_context {
 | 
			
		||||
   grub_ssize_t cmdline_len;
 | 
			
		||||
   grub_efi_handle_t dev_handle;
 | 
			
		||||
 };
 | 
			
		||||
-static struct grub_secureboot_chainloader_context *sb_context;
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
 grub_start_image (grub_efi_handle_t handle)
 | 
			
		||||
@@ -98,11 +95,14 @@ grub_start_image (grub_efi_handle_t handle)
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_chainloader_unload (void)
 | 
			
		||||
+grub_chainloader_unload (void *context)
 | 
			
		||||
 {
 | 
			
		||||
+  grub_efi_handle_t image_handle;
 | 
			
		||||
   grub_efi_loaded_image_t *loaded_image;
 | 
			
		||||
   grub_efi_boot_services_t *b;
 | 
			
		||||
 
 | 
			
		||||
+  image_handle = (grub_efi_handle_t) context;
 | 
			
		||||
+
 | 
			
		||||
   loaded_image = grub_efi_get_loaded_image (image_handle);
 | 
			
		||||
   if (loaded_image != NULL)
 | 
			
		||||
     grub_free (loaded_image->load_options);
 | 
			
		||||
@@ -115,10 +115,12 @@ grub_chainloader_unload (void)
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_chainloader_boot (void)
 | 
			
		||||
+grub_chainloader_boot (void *context)
 | 
			
		||||
 {
 | 
			
		||||
+  grub_efi_handle_t image_handle;
 | 
			
		||||
   grub_err_t err;
 | 
			
		||||
 
 | 
			
		||||
+  image_handle = (grub_efi_handle_t) context;
 | 
			
		||||
   err = grub_start_image (image_handle);
 | 
			
		||||
 
 | 
			
		||||
   grub_loader_unset ();
 | 
			
		||||
@@ -839,15 +841,17 @@ error_exit:
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_secureboot_chainloader_unload (void)
 | 
			
		||||
+grub_secureboot_chainloader_unload (void *context)
 | 
			
		||||
 {
 | 
			
		||||
+  struct grub_secureboot_chainloader_context *sb_context;
 | 
			
		||||
+
 | 
			
		||||
+  sb_context = (struct grub_secureboot_chainloader_context *) context;
 | 
			
		||||
+
 | 
			
		||||
   grub_efi_free_pages (sb_context->address, sb_context->pages);
 | 
			
		||||
   grub_free (sb_context->file_path);
 | 
			
		||||
   grub_free (sb_context->cmdline);
 | 
			
		||||
   grub_free (sb_context);
 | 
			
		||||
 
 | 
			
		||||
-  sb_context = 0;
 | 
			
		||||
-
 | 
			
		||||
   grub_dl_unref (my_mod);
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
@@ -896,12 +900,15 @@ grub_load_image(grub_efi_device_path_t *file_path, void *boot_image,
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_secureboot_chainloader_boot (void)
 | 
			
		||||
+grub_secureboot_chainloader_boot (void *context)
 | 
			
		||||
 {
 | 
			
		||||
+  struct grub_secureboot_chainloader_context *sb_context;
 | 
			
		||||
   grub_efi_boot_services_t *b;
 | 
			
		||||
   int rc;
 | 
			
		||||
   grub_efi_handle_t handle = 0;
 | 
			
		||||
 
 | 
			
		||||
+  sb_context = (struct grub_secureboot_chainloader_context *) context;
 | 
			
		||||
+
 | 
			
		||||
   rc = handle_image (sb_context);
 | 
			
		||||
   if (rc == 0)
 | 
			
		||||
     {
 | 
			
		||||
@@ -942,6 +949,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_efi_char16_t *cmdline = 0;
 | 
			
		||||
   grub_ssize_t cmdline_len = 0;
 | 
			
		||||
   grub_efi_handle_t dev_handle = 0;
 | 
			
		||||
+  grub_efi_handle_t image_handle = 0;
 | 
			
		||||
+  struct grub_secureboot_chainloader_context *sb_context = 0;
 | 
			
		||||
 
 | 
			
		||||
   if (argc == 0)
 | 
			
		||||
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
 | 
			
		||||
@@ -1127,8 +1136,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
       grub_file_close (file);
 | 
			
		||||
       grub_device_close (dev);
 | 
			
		||||
 
 | 
			
		||||
-      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;
 | 
			
		||||
     }
 | 
			
		||||
   else
 | 
			
		||||
@@ -1142,7 +1151,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;
 | 
			
		||||
     }
 | 
			
		||||
@@ -1169,10 +1178,7 @@ fail:
 | 
			
		||||
     grub_free (cmdline);
 | 
			
		||||
 
 | 
			
		||||
   if (image_handle != 0)
 | 
			
		||||
-    {
 | 
			
		||||
-      efi_call_1 (b->unload_image, image_handle);
 | 
			
		||||
-      image_handle = 0;
 | 
			
		||||
-    }
 | 
			
		||||
+    efi_call_1 (b->unload_image, image_handle);
 | 
			
		||||
 
 | 
			
		||||
   grub_dl_unref (my_mod);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
Date: Mon, 2 May 2022 14:39:31 +0200
 | 
			
		||||
Subject: [PATCH] loader/i386/efi/linux: Avoid a use-after-free in the linuxefi
 | 
			
		||||
 loader
 | 
			
		||||
 | 
			
		||||
In some error paths in grub_cmd_linux, the pointer to lh may be
 | 
			
		||||
dereferenced after the buffer it points to has been freed. There aren't
 | 
			
		||||
any security implications from this because nothing else uses the
 | 
			
		||||
allocator after the buffer is freed and before the pointer is
 | 
			
		||||
dereferenced, but fix it anyway.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
(cherry picked from commit 8224f5a71af94bec8697de17e7e579792db9f9e2)
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/i386/efi/linux.c | 5 ++---
 | 
			
		||||
 1 file changed, 2 insertions(+), 3 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
index 941df6400b..27bc2aa161 100644
 | 
			
		||||
--- a/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
+++ b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
@@ -465,9 +465,6 @@ fail:
 | 
			
		||||
   if (file)
 | 
			
		||||
     grub_file_close (file);
 | 
			
		||||
 
 | 
			
		||||
-  if (kernel)
 | 
			
		||||
-    grub_free (kernel);
 | 
			
		||||
-
 | 
			
		||||
   if (grub_errno != GRUB_ERR_NONE)
 | 
			
		||||
     {
 | 
			
		||||
       grub_dl_unref (my_mod);
 | 
			
		||||
@@ -483,6 +480,8 @@ fail:
 | 
			
		||||
       kernel_free (params, sizeof(*params));
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+  grub_free (kernel);
 | 
			
		||||
+
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										296
									
								
								0225-loader-i386-efi-linux-Use-grub_loader_set_ex.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								0225-loader-i386-efi-linux-Use-grub_loader_set_ex.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,296 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
Date: Mon, 2 May 2022 17:04:23 +0200
 | 
			
		||||
Subject: [PATCH] loader/i386/efi/linux: Use grub_loader_set_ex
 | 
			
		||||
 | 
			
		||||
This ports the linuxefi loader to use grub_loader_set_ex in order to fix
 | 
			
		||||
a use-after-fre bug that occurs when grub_cmd_linux is executed more than
 | 
			
		||||
once before a boot attempt is performed.
 | 
			
		||||
 | 
			
		||||
This is more complicated than for the chainloader command, as the initrd
 | 
			
		||||
command needs access to the loader state. To solve this, the linuxefi
 | 
			
		||||
module registers a dummy initrd command at startup that returns an error.
 | 
			
		||||
The linuxefi command then registers a proper initrd command with a higher
 | 
			
		||||
priority that is passed the loader state.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
(cherry picked from commit 7cf736436b4c934df5ddfa6f44b46a7e07d99fdc)
 | 
			
		||||
[rharwood/pjones: set kernel_size in context]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/i386/efi/linux.c | 146 +++++++++++++++++++++++---------------
 | 
			
		||||
 1 file changed, 87 insertions(+), 59 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
index 27bc2aa161..e3c2d6fe0b 100644
 | 
			
		||||
--- a/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
+++ b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
@@ -34,13 +34,19 @@
 | 
			
		||||
 GRUB_MOD_LICENSE ("GPLv3+");
 | 
			
		||||
 
 | 
			
		||||
 static grub_dl_t my_mod;
 | 
			
		||||
-static int loaded;
 | 
			
		||||
-static void *kernel_mem;
 | 
			
		||||
-static grub_uint64_t kernel_size;
 | 
			
		||||
-static void *initrd_mem;
 | 
			
		||||
-static grub_uint32_t handover_offset;
 | 
			
		||||
-struct linux_kernel_params *params;
 | 
			
		||||
-static char *linux_cmdline;
 | 
			
		||||
+
 | 
			
		||||
+static grub_command_t cmd_linux, cmd_initrd;
 | 
			
		||||
+static grub_command_t cmd_linuxefi, cmd_initrdefi;
 | 
			
		||||
+
 | 
			
		||||
+struct grub_linuxefi_context {
 | 
			
		||||
+  void *kernel_mem;
 | 
			
		||||
+  grub_uint64_t kernel_size;
 | 
			
		||||
+  grub_uint32_t handover_offset;
 | 
			
		||||
+  struct linux_kernel_params *params;
 | 
			
		||||
+  char *cmdline;
 | 
			
		||||
+
 | 
			
		||||
+  void *initrd_mem;
 | 
			
		||||
+};
 | 
			
		||||
 
 | 
			
		||||
 #define MIN(a, b) \
 | 
			
		||||
   ({ typeof (a) _a = (a); \
 | 
			
		||||
@@ -123,25 +129,32 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_linuxefi_boot (void)
 | 
			
		||||
+grub_linuxefi_boot (void *data)
 | 
			
		||||
 {
 | 
			
		||||
+  struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data;
 | 
			
		||||
+
 | 
			
		||||
   asm volatile ("cli");
 | 
			
		||||
 
 | 
			
		||||
-  return grub_efi_linux_boot ((char *)kernel_mem,
 | 
			
		||||
-			      handover_offset,
 | 
			
		||||
-			      params);
 | 
			
		||||
+  return grub_efi_linux_boot ((char *)context->kernel_mem,
 | 
			
		||||
+			      context->handover_offset,
 | 
			
		||||
+			      context->params);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_linuxefi_unload (void)
 | 
			
		||||
+grub_linuxefi_unload (void *data)
 | 
			
		||||
 {
 | 
			
		||||
+  struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) data;
 | 
			
		||||
+  struct linux_kernel_params *params = context->params;
 | 
			
		||||
+
 | 
			
		||||
   grub_dl_unref (my_mod);
 | 
			
		||||
-  loaded = 0;
 | 
			
		||||
 
 | 
			
		||||
-  kernel_free(initrd_mem, params->ramdisk_size);
 | 
			
		||||
-  kernel_free(linux_cmdline, params->cmdline_size + 1);
 | 
			
		||||
-  kernel_free(kernel_mem, kernel_size);
 | 
			
		||||
-  kernel_free(params, sizeof(*params));
 | 
			
		||||
+  kernel_free (context->initrd_mem, params->ramdisk_size);
 | 
			
		||||
+  kernel_free (context->cmdline, params->cmdline_size + 1);
 | 
			
		||||
+  kernel_free (context->kernel_mem, context->kernel_size);
 | 
			
		||||
+  kernel_free (params, sizeof(*params));
 | 
			
		||||
+  cmd_initrd->data = 0;
 | 
			
		||||
+  cmd_initrdefi->data = 0;
 | 
			
		||||
+  grub_free (context);
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
@@ -188,13 +201,14 @@ read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
 | 
			
		||||
 #define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull))
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
-grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
-                 int argc, char *argv[])
 | 
			
		||||
+grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
 | 
			
		||||
 {
 | 
			
		||||
   grub_file_t *files = 0;
 | 
			
		||||
   int i, nfiles = 0;
 | 
			
		||||
   grub_size_t size = 0;
 | 
			
		||||
   grub_uint8_t *ptr;
 | 
			
		||||
+  struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data;
 | 
			
		||||
+  struct linux_kernel_params *params;
 | 
			
		||||
 
 | 
			
		||||
   if (argc == 0)
 | 
			
		||||
     {
 | 
			
		||||
@@ -202,12 +216,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
       goto fail;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
-  if (!loaded)
 | 
			
		||||
+  if (!context)
 | 
			
		||||
     {
 | 
			
		||||
       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
 | 
			
		||||
       goto fail;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+  params = context->params;
 | 
			
		||||
+
 | 
			
		||||
   files = grub_calloc (argc, sizeof (files[0]));
 | 
			
		||||
   if (!files)
 | 
			
		||||
     goto fail;
 | 
			
		||||
@@ -225,19 +241,19 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
 	}
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
-  initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
 | 
			
		||||
-  if (initrd_mem == NULL)
 | 
			
		||||
+  context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
 | 
			
		||||
+  if (context->initrd_mem == NULL)
 | 
			
		||||
     goto fail;
 | 
			
		||||
-  grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
 | 
			
		||||
+  grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem);
 | 
			
		||||
 
 | 
			
		||||
   params->ramdisk_size = LOW_U32(size);
 | 
			
		||||
-  params->ramdisk_image = LOW_U32(initrd_mem);
 | 
			
		||||
+  params->ramdisk_image = LOW_U32(context->initrd_mem);
 | 
			
		||||
 #if defined(__x86_64__)
 | 
			
		||||
   params->ext_ramdisk_size = HIGH_U32(size);
 | 
			
		||||
-  params->ext_ramdisk_image = HIGH_U32(initrd_mem);
 | 
			
		||||
+  params->ext_ramdisk_image = HIGH_U32(context->initrd_mem);
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
-  ptr = initrd_mem;
 | 
			
		||||
+  ptr = context->initrd_mem;
 | 
			
		||||
 
 | 
			
		||||
   for (i = 0; i < nfiles; i++)
 | 
			
		||||
     {
 | 
			
		||||
@@ -261,8 +277,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
     grub_file_close (files[i]);
 | 
			
		||||
   grub_free (files);
 | 
			
		||||
 
 | 
			
		||||
-  if (initrd_mem && grub_errno)
 | 
			
		||||
-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)initrd_mem,
 | 
			
		||||
+  if (context->initrd_mem && grub_errno)
 | 
			
		||||
+    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem,
 | 
			
		||||
 			 BYTES_TO_PAGES(size));
 | 
			
		||||
 
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
@@ -277,6 +293,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_ssize_t start, filelen;
 | 
			
		||||
   void *kernel = NULL;
 | 
			
		||||
   int setup_header_end_offset;
 | 
			
		||||
+  void *kernel_mem = 0;
 | 
			
		||||
+  grub_uint64_t kernel_size = 0;
 | 
			
		||||
+  grub_uint32_t handover_offset;
 | 
			
		||||
+  struct linux_kernel_params *params = 0;
 | 
			
		||||
+  char *cmdline = 0;
 | 
			
		||||
+  struct grub_linuxefi_context *context = 0;
 | 
			
		||||
 
 | 
			
		||||
   grub_dl_ref (my_mod);
 | 
			
		||||
 
 | 
			
		||||
@@ -390,27 +412,27 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_dprintf ("linux", "new lh is at %p\n", lh);
 | 
			
		||||
 
 | 
			
		||||
   grub_dprintf ("linux", "setting up cmdline\n");
 | 
			
		||||
-  linux_cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
 | 
			
		||||
-  if (!linux_cmdline)
 | 
			
		||||
+  cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
 | 
			
		||||
+  if (!cmdline)
 | 
			
		||||
     goto fail;
 | 
			
		||||
-  grub_dprintf ("linux", "linux_cmdline = %p\n", linux_cmdline);
 | 
			
		||||
+  grub_dprintf ("linux", "cmdline = %p\n", cmdline);
 | 
			
		||||
 
 | 
			
		||||
-  grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
 | 
			
		||||
+  grub_memcpy (cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
 | 
			
		||||
   grub_create_loader_cmdline (argc, argv,
 | 
			
		||||
-                              linux_cmdline + sizeof (LINUX_IMAGE) - 1,
 | 
			
		||||
+                              cmdline + sizeof (LINUX_IMAGE) - 1,
 | 
			
		||||
 			      lh->cmdline_size - (sizeof (LINUX_IMAGE) - 1),
 | 
			
		||||
 			      GRUB_VERIFY_KERNEL_CMDLINE);
 | 
			
		||||
 
 | 
			
		||||
-  grub_dprintf ("linux", "cmdline:%s\n", linux_cmdline);
 | 
			
		||||
+  grub_dprintf ("linux", "cmdline:%s\n", cmdline);
 | 
			
		||||
   grub_dprintf ("linux", "setting lh->cmd_line_ptr to 0x%08x\n",
 | 
			
		||||
-		LOW_U32(linux_cmdline));
 | 
			
		||||
-  lh->cmd_line_ptr = LOW_U32(linux_cmdline);
 | 
			
		||||
+		LOW_U32(cmdline));
 | 
			
		||||
+  lh->cmd_line_ptr = LOW_U32(cmdline);
 | 
			
		||||
 #if defined(__x86_64__)
 | 
			
		||||
-  if ((grub_efi_uintn_t)linux_cmdline > 0xffffffffull)
 | 
			
		||||
+  if ((grub_efi_uintn_t)cmdline > 0xffffffffull)
 | 
			
		||||
     {
 | 
			
		||||
       grub_dprintf ("linux", "setting params->ext_cmd_line_ptr to 0x%08x\n",
 | 
			
		||||
-		    HIGH_U32(linux_cmdline));
 | 
			
		||||
-      params->ext_cmd_line_ptr = HIGH_U32(linux_cmdline);
 | 
			
		||||
+		    HIGH_U32(cmdline));
 | 
			
		||||
+      params->ext_cmd_line_ptr = HIGH_U32(cmdline);
 | 
			
		||||
     }
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
@@ -435,16 +457,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
     }
 | 
			
		||||
   max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
 | 
			
		||||
   max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
 | 
			
		||||
-  kernel_mem = kernel_alloc (lh->init_size, N_("can't allocate kernel"));
 | 
			
		||||
+  kernel_size = lh->init_size;
 | 
			
		||||
+  kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel"));
 | 
			
		||||
   restore_addresses();
 | 
			
		||||
   if (!kernel_mem)
 | 
			
		||||
     goto fail;
 | 
			
		||||
   grub_dprintf("linux", "kernel_mem = %p\n", kernel_mem);
 | 
			
		||||
 
 | 
			
		||||
-  grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
 | 
			
		||||
-
 | 
			
		||||
-  loaded = 1;
 | 
			
		||||
-
 | 
			
		||||
   grub_dprintf ("linux", "setting lh->code32_start to 0x%08x\n",
 | 
			
		||||
 		LOW_U32(kernel_mem));
 | 
			
		||||
   lh->code32_start = LOW_U32(kernel_mem);
 | 
			
		||||
@@ -461,33 +480,42 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
 		"setting lh->ext_loader_{type,ver} = {0x%02x,0x%02x}\n",
 | 
			
		||||
 		params->ext_loader_type, params->ext_loader_ver);
 | 
			
		||||
 
 | 
			
		||||
+  context = grub_zalloc (sizeof (*context));
 | 
			
		||||
+  if (!context)
 | 
			
		||||
+    goto fail;
 | 
			
		||||
+  context->kernel_mem = kernel_mem;
 | 
			
		||||
+  context->kernel_size = kernel_size;
 | 
			
		||||
+  context->handover_offset = handover_offset;
 | 
			
		||||
+  context->params = params;
 | 
			
		||||
+  context->cmdline = cmdline;
 | 
			
		||||
+
 | 
			
		||||
+  grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0);
 | 
			
		||||
+
 | 
			
		||||
+  cmd_initrd->data = context;
 | 
			
		||||
+  cmd_initrdefi->data = context;
 | 
			
		||||
+
 | 
			
		||||
+  grub_file_close (file);
 | 
			
		||||
+  grub_free (kernel);
 | 
			
		||||
+  return 0;
 | 
			
		||||
+
 | 
			
		||||
 fail:
 | 
			
		||||
   if (file)
 | 
			
		||||
     grub_file_close (file);
 | 
			
		||||
 
 | 
			
		||||
-  if (grub_errno != GRUB_ERR_NONE)
 | 
			
		||||
-    {
 | 
			
		||||
-      grub_dl_unref (my_mod);
 | 
			
		||||
-      loaded = 0;
 | 
			
		||||
-    }
 | 
			
		||||
+  grub_dl_unref (my_mod);
 | 
			
		||||
 
 | 
			
		||||
-  if (!loaded)
 | 
			
		||||
-    {
 | 
			
		||||
-      if (lh)
 | 
			
		||||
-	kernel_free (linux_cmdline, lh->cmdline_size + 1);
 | 
			
		||||
+  if (lh)
 | 
			
		||||
+    kernel_free (cmdline, lh->cmdline_size + 1);
 | 
			
		||||
 
 | 
			
		||||
-      kernel_free (kernel_mem, kernel_size);
 | 
			
		||||
-      kernel_free (params, sizeof(*params));
 | 
			
		||||
-    }
 | 
			
		||||
+  kernel_free (kernel_mem, kernel_size);
 | 
			
		||||
+  kernel_free (params, sizeof(*params));
 | 
			
		||||
 
 | 
			
		||||
+  grub_free (context);
 | 
			
		||||
   grub_free (kernel);
 | 
			
		||||
 
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static grub_command_t cmd_linux, cmd_initrd;
 | 
			
		||||
-static grub_command_t cmd_linuxefi, cmd_initrdefi;
 | 
			
		||||
-
 | 
			
		||||
 GRUB_MOD_INIT(linux)
 | 
			
		||||
 {
 | 
			
		||||
   cmd_linux =
 | 
			
		||||
@ -0,0 +1,75 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
Date: Tue, 3 May 2022 09:47:35 +0200
 | 
			
		||||
Subject: [PATCH] loader/i386/efi/linux: Fix a memory leak in the initrd
 | 
			
		||||
 command
 | 
			
		||||
 | 
			
		||||
Subsequent invocations of the initrd command result in the previous
 | 
			
		||||
initrd being leaked, so fix that.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
 | 
			
		||||
(cherry picked from commit d98af31ce1e31bb22163960d53f5eb28c66582a0)
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/i386/efi/linux.c | 21 ++++++++++++---------
 | 
			
		||||
 1 file changed, 12 insertions(+), 9 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
index e3c2d6fe0b..9e5c11ac69 100644
 | 
			
		||||
--- a/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
+++ b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
@@ -209,6 +209,7 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
 | 
			
		||||
   grub_uint8_t *ptr;
 | 
			
		||||
   struct grub_linuxefi_context *context = (struct grub_linuxefi_context *) cmd->data;
 | 
			
		||||
   struct linux_kernel_params *params;
 | 
			
		||||
+  void *initrd_mem = 0;
 | 
			
		||||
 
 | 
			
		||||
   if (argc == 0)
 | 
			
		||||
     {
 | 
			
		||||
@@ -241,19 +242,19 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
 | 
			
		||||
 	}
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
-  context->initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
 | 
			
		||||
-  if (context->initrd_mem == NULL)
 | 
			
		||||
+  initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
 | 
			
		||||
+  if (initrd_mem == NULL)
 | 
			
		||||
     goto fail;
 | 
			
		||||
-  grub_dprintf ("linux", "initrd_mem = %p\n", context->initrd_mem);
 | 
			
		||||
+  grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
 | 
			
		||||
 
 | 
			
		||||
   params->ramdisk_size = LOW_U32(size);
 | 
			
		||||
-  params->ramdisk_image = LOW_U32(context->initrd_mem);
 | 
			
		||||
+  params->ramdisk_image = LOW_U32(initrd_mem);
 | 
			
		||||
 #if defined(__x86_64__)
 | 
			
		||||
   params->ext_ramdisk_size = HIGH_U32(size);
 | 
			
		||||
-  params->ext_ramdisk_image = HIGH_U32(context->initrd_mem);
 | 
			
		||||
+  params->ext_ramdisk_image = HIGH_U32(initrd_mem);
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
-  ptr = context->initrd_mem;
 | 
			
		||||
+  ptr = initrd_mem;
 | 
			
		||||
 
 | 
			
		||||
   for (i = 0; i < nfiles; i++)
 | 
			
		||||
     {
 | 
			
		||||
@@ -270,6 +271,9 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
 | 
			
		||||
       ptr += ALIGN_UP_OVERHEAD (cursize, 4);
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+  kernel_free(context->initrd_mem, params->ramdisk_size);
 | 
			
		||||
+
 | 
			
		||||
+  context->initrd_mem = initrd_mem;
 | 
			
		||||
   params->ramdisk_size = size;
 | 
			
		||||
 
 | 
			
		||||
  fail:
 | 
			
		||||
@@ -277,9 +281,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
 | 
			
		||||
     grub_file_close (files[i]);
 | 
			
		||||
   grub_free (files);
 | 
			
		||||
 
 | 
			
		||||
-  if (context->initrd_mem && grub_errno)
 | 
			
		||||
-    grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t)context->initrd_mem,
 | 
			
		||||
-			 BYTES_TO_PAGES(size));
 | 
			
		||||
+  if (initrd_mem && grub_errno)
 | 
			
		||||
+    kernel_free (initrd_mem, size);
 | 
			
		||||
 
 | 
			
		||||
   return grub_errno;
 | 
			
		||||
 }
 | 
			
		||||
							
								
								
									
										101
									
								
								0227-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								0227-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Julian Andres Klode <julian.klode@canonical.com>
 | 
			
		||||
Date: Thu, 2 Dec 2021 15:03:53 +0100
 | 
			
		||||
Subject: [PATCH] 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.klode@canonical.com>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit fa61ad69861c1cb3f68bf853d78fae7fd93986a0)
 | 
			
		||||
---
 | 
			
		||||
 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 cd129c398f..672ae16924 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. */
 | 
			
		||||
@ -0,0 +1,39 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Fri, 25 Jun 2021 02:19:05 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 1499a5068839fa37cb77ecef4b5bdacbd1ed12ea)
 | 
			
		||||
---
 | 
			
		||||
 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 e19aea3e51..ed69fc0f0f 100644
 | 
			
		||||
--- a/grub-core/kern/file.c
 | 
			
		||||
+++ b/grub-core/kern/file.c
 | 
			
		||||
@@ -81,6 +81,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;
 | 
			
		||||
 
 | 
			
		||||
@@ -135,6 +136,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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										198
									
								
								0229-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								0229-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,198 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 6 Jul 2021 14:02:55 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 882be97d1df6449b9fd4d593f0cb70005fde3494)
 | 
			
		||||
---
 | 
			
		||||
 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 0157ff7420..e2a6b1cf3c 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)
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 6 Jul 2021 14:13:40 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 8ce433557adeadbc46429aabb9f850b02ad2bdfb)
 | 
			
		||||
---
 | 
			
		||||
 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 e2a6b1cf3c..8955b8ecfd 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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										170
									
								
								0231-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								0231-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,170 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 6 Jul 2021 18:51:35 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 0e1d163382669bd734439d8864ee969616d971d9)
 | 
			
		||||
[rharwood: context conflict]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/video/readers/png.c | 85 +++----------------------------------------
 | 
			
		||||
 1 file changed, 6 insertions(+), 79 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
 | 
			
		||||
index 8955b8ecfd..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,
 | 
			
		||||
@@ -956,60 +937,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.  */
 | 
			
		||||
@ -0,0 +1,40 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 6 Jul 2021 23:25:07 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 1ae9a91d42cb40da8a6f11fac65541858e340afa)
 | 
			
		||||
---
 | 
			
		||||
 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];
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								0233-video-readers-png-Sanity-check-some-huffman-codes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								0233-video-readers-png-Sanity-check-some-huffman-codes.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 6 Jul 2021 19:19:11 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit c3a8ab0cbd24153ec7b1f84a96ddfdd72ef8d117)
 | 
			
		||||
---
 | 
			
		||||
 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]);
 | 
			
		||||
							
								
								
									
										255
									
								
								0234-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								0234-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,255 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Mon, 28 Jun 2021 14:16:14 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit ab2e5d2e4bff488bbb557ed435a61ae102ef9f0c)
 | 
			
		||||
---
 | 
			
		||||
 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;
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Mon, 28 Jun 2021 14:16:58 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit bc06e12b4de55cc6f926af9f064170c82b1403e9)
 | 
			
		||||
---
 | 
			
		||||
 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;
 | 
			
		||||
@ -0,0 +1,44 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Mon, 28 Jun 2021 14:25:17 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit f3a854def3e281b7ad4bbea730cd3046de1da52f)
 | 
			
		||||
---
 | 
			
		||||
 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)
 | 
			
		||||
@ -0,0 +1,53 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Wed, 7 Jul 2021 15:38:19 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 41aeb2004db9924fecd9f2dd64bc2a5a5594a4b5)
 | 
			
		||||
---
 | 
			
		||||
 grub-core/video/readers/jpeg.c | 4 ++++
 | 
			
		||||
 1 file changed, 4 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
 | 
			
		||||
index 1df1171d78..2da04094b3 100644
 | 
			
		||||
--- a/grub-core/video/readers/jpeg.c
 | 
			
		||||
+++ b/grub-core/video/readers/jpeg.c
 | 
			
		||||
@@ -705,6 +705,10 @@ 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 (vb * data->image_width <= hb * nc1)
 | 
			
		||||
+    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)
 | 
			
		||||
     for (c1 = 0;  c1 < nc1 && (!data->dri || rst);
 | 
			
		||||
@ -0,0 +1,34 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 13 Jul 2021 13:24:38 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit fdf32abc7a3928852422c0f291d8cd1dd6b34a8d)
 | 
			
		||||
---
 | 
			
		||||
 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
 | 
			
		||||
							
								
								
									
										46
									
								
								0239-net-netbuff-Block-overly-large-netbuff-allocs.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								0239-net-netbuff-Block-overly-large-netbuff-allocs.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 8 Mar 2022 23:47:46 +1100
 | 
			
		||||
Subject: [PATCH] net/netbuff: Block overly large netbuff allocs
 | 
			
		||||
 | 
			
		||||
A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment
 | 
			
		||||
reassembly.
 | 
			
		||||
 | 
			
		||||
This helps avoid some bugs (and provides a spot to instrument to catch
 | 
			
		||||
them at their source).
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit ee9591103004cd13b4efadda671536090ca7fd57)
 | 
			
		||||
---
 | 
			
		||||
 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
 | 
			
		||||
							
								
								
									
										44
									
								
								0240-net-ip-Do-IP-fragment-maths-safely.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								0240-net-ip-Do-IP-fragment-maths-safely.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Mon, 20 Dec 2021 19:41:21 +1100
 | 
			
		||||
Subject: [PATCH] net/ip: Do IP fragment maths safely
 | 
			
		||||
 | 
			
		||||
This avoids an underflow and subsequent unpleasantness.
 | 
			
		||||
 | 
			
		||||
Fixes: CVE-2022-28733
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit eb74e5743ca7e18a5e75c392fe0b21d1549a1936)
 | 
			
		||||
---
 | 
			
		||||
 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 ce6bdc75c6..cf74f1f794 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)
 | 
			
		||||
 	{
 | 
			
		||||
@ -0,0 +1,56 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Thu, 16 Sep 2021 01:29:54 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit eb2e69fcf51307757e43f55ee8c9354d1ee42dd1)
 | 
			
		||||
---
 | 
			
		||||
 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"));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,71 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Mon, 20 Dec 2021 21:55:43 +1100
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 6a97b3f4b1d5173aa516edc6dedbc63de7306d21)
 | 
			
		||||
---
 | 
			
		||||
 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;
 | 
			
		||||
							
								
								
									
										112
									
								
								0243-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								0243-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Mon, 20 Sep 2021 01:12:24 +1000
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit dada1dda695439bb55b2848dddc2d89843552f81)
 | 
			
		||||
---
 | 
			
		||||
 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 55aed92722..1001c611d1 100644
 | 
			
		||||
--- a/grub-core/net/net.c
 | 
			
		||||
+++ b/grub-core/net/net.c
 | 
			
		||||
@@ -1625,7 +1625,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;
 | 
			
		||||
 }
 | 
			
		||||
@@ -1847,7 +1848,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;
 | 
			
		||||
   }
 | 
			
		||||
@@ -1856,6 +1860,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 d54b13f09f..788ad1dc44 100644
 | 
			
		||||
--- a/grub-core/net/tftp.c
 | 
			
		||||
+++ b/grub-core/net/tftp.c
 | 
			
		||||
@@ -408,6 +408,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 42af7de250..9e4898cc6b 100644
 | 
			
		||||
--- a/include/grub/net.h
 | 
			
		||||
+++ b/include/grub/net.h
 | 
			
		||||
@@ -280,6 +280,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);
 | 
			
		||||
							
								
								
									
										35
									
								
								0244-net-tftp-Avoid-a-trivial-UAF.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								0244-net-tftp-Avoid-a-trivial-UAF.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 18 Jan 2022 14:29:20 +1100
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 956f4329cec23e4375182030ca9b2be631a61ba5)
 | 
			
		||||
---
 | 
			
		||||
 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 788ad1dc44..a95766dcbd 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);
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 1 Mar 2022 23:14:15 +1100
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit ec233d3ecf995293304de443579aab5c46c49e85)
 | 
			
		||||
---
 | 
			
		||||
 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 7f878b5615..19cb8768e3 100644
 | 
			
		||||
--- a/grub-core/net/http.c
 | 
			
		||||
+++ b/grub-core/net/http.c
 | 
			
		||||
@@ -427,7 +427,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);
 | 
			
		||||
@@ -435,7 +435,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;
 | 
			
		||||
							
								
								
									
										46
									
								
								0246-net-http-Fix-OOB-write-for-split-http-headers.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								0246-net-http-Fix-OOB-write-for-split-http-headers.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 8 Mar 2022 18:17:03 +1100
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit e9fb459638811c12b0989dbf64e3e124974ef617)
 | 
			
		||||
---
 | 
			
		||||
 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 19cb8768e3..58546739a2 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;
 | 
			
		||||
							
								
								
									
										48
									
								
								0247-net-http-Error-out-on-headers-with-LF-without-CR.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								0247-net-http-Error-out-on-headers-with-LF-without-CR.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Date: Tue, 8 Mar 2022 19:04:40 +1100
 | 
			
		||||
Subject: [PATCH] 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 <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit d232ad41ac4979a9de4d746e5fdff9caf0e303de)
 | 
			
		||||
---
 | 
			
		||||
 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 58546739a2..57d2721719 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)
 | 
			
		||||
     {
 | 
			
		||||
@ -0,0 +1,72 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
 | 
			
		||||
Date: Wed, 6 Apr 2022 18:03:37 +0530
 | 
			
		||||
Subject: [PATCH] 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 <sudhakar@linux.ibm.com>
 | 
			
		||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit a3988cb3f0a108dd67ac127a79a4c8479d23334e)
 | 
			
		||||
---
 | 
			
		||||
 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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										132
									
								
								0249-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								0249-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,132 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
 | 
			
		||||
Date: Wed, 6 Apr 2022 18:49:09 +0530
 | 
			
		||||
Subject: [PATCH] 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 <sudhakar@linux.ibm.com>
 | 
			
		||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 62d63d5e38c67a6e349148bf7cb87c560e935a7e)
 | 
			
		||||
---
 | 
			
		||||
 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);
 | 
			
		||||
 
 | 
			
		||||
-  p += (nr >> 3);
 | 
			
		||||
+  if (shifted_nr >= len)
 | 
			
		||||
+    return -1;
 | 
			
		||||
+
 | 
			
		||||
+  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)
 | 
			
		||||
							
								
								
									
										38
									
								
								0250-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								0250-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
 | 
			
		||||
Date: Wed, 6 Apr 2022 18:17:43 +0530
 | 
			
		||||
Subject: [PATCH] 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 <sudhakar@linux.ibm.com>
 | 
			
		||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 9a891f638509e031d322c94e3cbcf38d36f3993a)
 | 
			
		||||
---
 | 
			
		||||
 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;
 | 
			
		||||
@ -0,0 +1,79 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Darren Kenny <darren.kenny@oracle.com>
 | 
			
		||||
Date: Tue, 29 Mar 2022 10:49:56 +0000
 | 
			
		||||
Subject: [PATCH] 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.kenny@oracle.com>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 6d3f06c0b6a8992b9b1bb0e62af93ac5ff2781f0)
 | 
			
		||||
[rharwood: we've an extra variable here]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.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 07c0ff874b..2fcfb738fe 100644
 | 
			
		||||
--- a/grub-core/fs/btrfs.c
 | 
			
		||||
+++ b/grub-core/fs/btrfs.c
 | 
			
		||||
@@ -2254,6 +2254,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;
 | 
			
		||||
@@ -2320,6 +2321,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;
 | 
			
		||||
@@ -2330,6 +2343,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));
 | 
			
		||||
							
								
								
									
										134
									
								
								0252-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								0252-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,134 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Darren Kenny <darren.kenny@oracle.com>
 | 
			
		||||
Date: Tue, 29 Mar 2022 15:52:46 +0000
 | 
			
		||||
Subject: [PATCH] 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.kenny@oracle.com>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit 3849647b4b98a4419366708fc4b7f339c6f55ec7)
 | 
			
		||||
---
 | 
			
		||||
 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 2fcfb738fe..0e9b450413 100644
 | 
			
		||||
--- a/grub-core/fs/btrfs.c
 | 
			
		||||
+++ b/grub-core/fs/btrfs.c
 | 
			
		||||
@@ -941,6 +941,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;
 | 
			
		||||
@@ -999,6 +1005,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);
 | 
			
		||||
@@ -1018,6 +1034,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:
 | 
			
		||||
@@ -1054,6 +1083,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:
 | 
			
		||||
@@ -1153,6 +1196,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 %"
 | 
			
		||||
@@ -1165,6 +1210,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,
 | 
			
		||||
							
								
								
									
										75
									
								
								0253-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								0253-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Darren Kenny <darren.kenny@oracle.com>
 | 
			
		||||
Date: Thu, 7 Apr 2022 15:18:12 +0000
 | 
			
		||||
Subject: [PATCH] fs/btrfs: Fix more fuzz issues related to chunks
 | 
			
		||||
 | 
			
		||||
The corpus we generating issues in grub_btrfs_read_logical() when
 | 
			
		||||
attempting to iterate over nstripes entries in the boot mapping.
 | 
			
		||||
 | 
			
		||||
In most cases the reason for the failure was that the number of strips
 | 
			
		||||
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.kenny@oracle.com>
 | 
			
		||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
 | 
			
		||||
(cherry picked from commit e00cd76cbadcc897a9cc4087cb2fcb5dbe15e596)
 | 
			
		||||
---
 | 
			
		||||
 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 0e9b450413..47325f6ad7 100644
 | 
			
		||||
--- a/grub-core/fs/btrfs.c
 | 
			
		||||
+++ b/grub-core/fs/btrfs.c
 | 
			
		||||
@@ -947,6 +947,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;
 | 
			
		||||
@@ -1194,6 +1205,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;
 | 
			
		||||
@@ -1220,6 +1238,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,
 | 
			
		||||
							
								
								
									
										83
									
								
								0254-misc-Make-grub_min-and-grub_max-more-resilient.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								0254-misc-Make-grub_min-and-grub_max-more-resilient.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Mon, 21 Mar 2022 16:06:10 -0400
 | 
			
		||||
Subject: [PATCH] misc: Make grub_min() and grub_max() more resilient.
 | 
			
		||||
 | 
			
		||||
grub_min(a,b) and grub_max(a,b) use a relatively naive implementation
 | 
			
		||||
which leads to several problems:
 | 
			
		||||
- they evaluate their parameters more than once
 | 
			
		||||
- the naive way to address this, to declare temporary variables in a
 | 
			
		||||
  statement-expression, isn't resilient against nested uses, because
 | 
			
		||||
  MIN(a,MIN(b,c)) results in the temporary variables being declared in
 | 
			
		||||
  two nested scopes, which may result in a build warning depending on
 | 
			
		||||
  your build options.
 | 
			
		||||
 | 
			
		||||
This patch changes our implementation to use a statement-expression
 | 
			
		||||
inside a helper macro, and creates the symbols for the temporary
 | 
			
		||||
variables with __COUNTER__ (A GNU C cpp extension) and token pasting to
 | 
			
		||||
create uniquely named internal variables.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/multiboot_elfxx.c |  4 +---
 | 
			
		||||
 include/grub/misc.h                | 25 +++++++++++++++++++++++--
 | 
			
		||||
 2 files changed, 24 insertions(+), 5 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c
 | 
			
		||||
index f2318e0d16..87f6e31aa6 100644
 | 
			
		||||
--- a/grub-core/loader/multiboot_elfxx.c
 | 
			
		||||
+++ b/grub-core/loader/multiboot_elfxx.c
 | 
			
		||||
@@ -35,9 +35,7 @@
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 #include <grub/i386/relocator.h>
 | 
			
		||||
-
 | 
			
		||||
-#define CONCAT(a,b)	CONCAT_(a, b)
 | 
			
		||||
-#define CONCAT_(a,b)	a ## b
 | 
			
		||||
+#include <grub/misc.h>
 | 
			
		||||
 
 | 
			
		||||
 #pragma GCC diagnostic ignored "-Wcast-align"
 | 
			
		||||
 
 | 
			
		||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
 | 
			
		||||
index 6c4aa85ac5..cf84aec1db 100644
 | 
			
		||||
--- a/include/grub/misc.h
 | 
			
		||||
+++ b/include/grub/misc.h
 | 
			
		||||
@@ -35,6 +35,14 @@
 | 
			
		||||
 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
 | 
			
		||||
 #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
 | 
			
		||||
 
 | 
			
		||||
+#ifndef CONCAT_
 | 
			
		||||
+#define CONCAT_(a, b) a ## b
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
+#ifndef CONCAT
 | 
			
		||||
+#define CONCAT(a, b) CONCAT_(a, b)
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
 #define grub_dprintf(condition, ...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, __VA_ARGS__)
 | 
			
		||||
 
 | 
			
		||||
 void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
 | 
			
		||||
@@ -498,8 +506,21 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 | 
			
		||||
 #define grub_boot_time(...)
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
-#define grub_max(a, b) (((a) > (b)) ? (a) : (b))
 | 
			
		||||
-#define grub_min(a, b) (((a) < (b)) ? (a) : (b))
 | 
			
		||||
+#define _grub_min(a, b, _a, _b)						      \
 | 
			
		||||
+  ({ typeof (a) _a = (a);						      \
 | 
			
		||||
+     typeof (b) _b = (b);						      \
 | 
			
		||||
+     _a < _b ? _a : _b; })
 | 
			
		||||
+#define grub_min(a, b) _grub_min(a, b,					      \
 | 
			
		||||
+				 CONCAT(_a_,__COUNTER__),		      \
 | 
			
		||||
+				 CONCAT(_b_,__COUNTER__))
 | 
			
		||||
+
 | 
			
		||||
+#define _grub_max(a, b, _a, _b)						      \
 | 
			
		||||
+  ({ typeof (a) _a = (a);						      \
 | 
			
		||||
+     typeof (b) _b = (b);						      \
 | 
			
		||||
+     _a > _b ? _a : _b; })
 | 
			
		||||
+#define grub_max(a, b) _grub_max(a, b,					      \
 | 
			
		||||
+				 CONCAT(_a_,__COUNTER__),		      \
 | 
			
		||||
+				 CONCAT(_b_,__COUNTER__))
 | 
			
		||||
 
 | 
			
		||||
 #define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) - __builtin_clzll (n) - 1)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										92
									
								
								0255-ReiserFS-switch-to-using-grub_min-grub_max.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								0255-ReiserFS-switch-to-using-grub_min-grub_max.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Thu, 21 Apr 2022 16:31:17 -0400
 | 
			
		||||
Subject: [PATCH] ReiserFS: switch to using grub_min()/grub_max()
 | 
			
		||||
 | 
			
		||||
This is a minor cleanup patch to remove the bespoke MIN() and MAX()
 | 
			
		||||
definitions from the reiserfs driver, and uses grub_min() / grub_max()
 | 
			
		||||
instead.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/fs/reiserfs.c | 28 +++++++++-------------------
 | 
			
		||||
 1 file changed, 9 insertions(+), 19 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c
 | 
			
		||||
index af6a226a7f..b8253da7fe 100644
 | 
			
		||||
--- a/grub-core/fs/reiserfs.c
 | 
			
		||||
+++ b/grub-core/fs/reiserfs.c
 | 
			
		||||
@@ -42,16 +42,6 @@
 | 
			
		||||
 
 | 
			
		||||
 GRUB_MOD_LICENSE ("GPLv3+");
 | 
			
		||||
 
 | 
			
		||||
-#define MIN(a, b) \
 | 
			
		||||
-  ({ typeof (a) _a = (a); \
 | 
			
		||||
-     typeof (b) _b = (b); \
 | 
			
		||||
-     _a < _b ? _a : _b; })
 | 
			
		||||
-
 | 
			
		||||
-#define MAX(a, b) \
 | 
			
		||||
-  ({ typeof (a) _a = (a); \
 | 
			
		||||
-     typeof (b) _b = (b); \
 | 
			
		||||
-     _a > _b ? _a : _b; })
 | 
			
		||||
-
 | 
			
		||||
 #define REISERFS_SUPER_BLOCK_OFFSET 0x10000
 | 
			
		||||
 #define REISERFS_MAGIC_LEN 12
 | 
			
		||||
 #define REISERFS_MAGIC_STRING "ReIsEr"
 | 
			
		||||
@@ -1076,7 +1066,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
 | 
			
		||||
   grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2);
 | 
			
		||||
   initial_position = off;
 | 
			
		||||
   current_position = 0;
 | 
			
		||||
-  final_position = MIN (len + initial_position, node->size);
 | 
			
		||||
+  final_position = grub_min (len + initial_position, node->size);
 | 
			
		||||
   grub_dprintf ("reiserfs",
 | 
			
		||||
 		"Reading from %lld to %lld (%lld instead of requested %ld)\n",
 | 
			
		||||
 		(unsigned long long) initial_position,
 | 
			
		||||
@@ -1115,8 +1105,8 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
 | 
			
		||||
           grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block);
 | 
			
		||||
           if (initial_position < current_position + item_size)
 | 
			
		||||
             {
 | 
			
		||||
-              offset = MAX ((signed) (initial_position - current_position), 0);
 | 
			
		||||
-              length = (MIN (item_size, final_position - current_position)
 | 
			
		||||
+              offset = grub_max ((signed) (initial_position - current_position), 0);
 | 
			
		||||
+              length = (grub_min (item_size, final_position - current_position)
 | 
			
		||||
                         - offset);
 | 
			
		||||
               grub_dprintf ("reiserfs",
 | 
			
		||||
                             "Reading direct block %u from %u to %u...\n",
 | 
			
		||||
@@ -1161,9 +1151,9 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
 | 
			
		||||
               grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block);
 | 
			
		||||
               if (current_position + block_size >= initial_position)
 | 
			
		||||
                 {
 | 
			
		||||
-                  offset = MAX ((signed) (initial_position - current_position),
 | 
			
		||||
-                                0);
 | 
			
		||||
-                  length = (MIN (block_size, final_position - current_position)
 | 
			
		||||
+                  offset = grub_max ((signed) (initial_position - current_position),
 | 
			
		||||
+				     0);
 | 
			
		||||
+                  length = (grub_min (block_size, final_position - current_position)
 | 
			
		||||
                             - offset);
 | 
			
		||||
                   grub_dprintf ("reiserfs",
 | 
			
		||||
                                 "Reading indirect block %u from %u to %u...\n",
 | 
			
		||||
@@ -1205,7 +1195,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
 | 
			
		||||
   switch (found.type)
 | 
			
		||||
     {
 | 
			
		||||
       case GRUB_REISERFS_DIRECT:
 | 
			
		||||
-        read_length = MIN (len, item_size - file->offset);
 | 
			
		||||
+        read_length = grub_min (len, item_size - file->offset);
 | 
			
		||||
         grub_disk_read (found.data->disk,
 | 
			
		||||
                         (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
 | 
			
		||||
                         grub_le_to_cpu16 (found.header.item_location) + file->offset,
 | 
			
		||||
@@ -1224,12 +1214,12 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node,
 | 
			
		||||
                         item_size, (char *) indirect_block_ptr);
 | 
			
		||||
         if (grub_errno)
 | 
			
		||||
           goto fail;
 | 
			
		||||
-        len = MIN (len, file->size - file->offset);
 | 
			
		||||
+        len = grub_min (len, file->size - file->offset);
 | 
			
		||||
         for (indirect_block = file->offset / block_size;
 | 
			
		||||
              indirect_block < indirect_block_count && read_length < len;
 | 
			
		||||
              indirect_block++)
 | 
			
		||||
           {
 | 
			
		||||
-            read = MIN (block_size, len - read_length);
 | 
			
		||||
+            read = grub_min (block_size, len - read_length);
 | 
			
		||||
             grub_disk_read (found.data->disk,
 | 
			
		||||
                             (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE,
 | 
			
		||||
                             file->offset % block_size, read,
 | 
			
		||||
@ -0,0 +1,46 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Thu, 24 Mar 2022 14:40:01 -0400
 | 
			
		||||
Subject: [PATCH] misc: make grub_boot_time() also call
 | 
			
		||||
 grub_dprintf("boot",...)
 | 
			
		||||
 | 
			
		||||
Currently grub_boot_time() includes valuable debugging messages, but if
 | 
			
		||||
you build without BOOT_TIME_STATS enabled, they are silently and
 | 
			
		||||
confusingly compiled away.
 | 
			
		||||
 | 
			
		||||
This patch changes grub_boot_time() to also log when "boot" is enabled
 | 
			
		||||
in DEBUG, regardless of BOOT_TIME_STATS.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/kern/misc.c | 3 ++-
 | 
			
		||||
 include/grub/misc.h   | 2 +-
 | 
			
		||||
 2 files changed, 3 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
 | 
			
		||||
index a186ad3dd4..cb45461402 100644
 | 
			
		||||
--- a/grub-core/kern/misc.c
 | 
			
		||||
+++ b/grub-core/kern/misc.c
 | 
			
		||||
@@ -1334,7 +1334,8 @@ grub_real_boot_time (const char *file,
 | 
			
		||||
   n->next = 0;
 | 
			
		||||
 
 | 
			
		||||
   va_start (args, fmt);
 | 
			
		||||
-  n->msg = grub_xvasprintf (fmt, args);    
 | 
			
		||||
+  n->msg = grub_xvasprintf (fmt, args);
 | 
			
		||||
+  grub_dprintf ("boot", "%s\n", n->msg);
 | 
			
		||||
   va_end (args);
 | 
			
		||||
 
 | 
			
		||||
   *boot_time_last = n;
 | 
			
		||||
diff --git a/include/grub/misc.h b/include/grub/misc.h
 | 
			
		||||
index cf84aec1db..faae0ae860 100644
 | 
			
		||||
--- a/include/grub/misc.h
 | 
			
		||||
+++ b/include/grub/misc.h
 | 
			
		||||
@@ -503,7 +503,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 | 
			
		||||
 				       const char *fmt, ...) __attribute__ ((format (GNU_PRINTF, 3, 4)));
 | 
			
		||||
 #define grub_boot_time(...) grub_real_boot_time(GRUB_FILE, __LINE__, __VA_ARGS__)
 | 
			
		||||
 #else
 | 
			
		||||
-#define grub_boot_time(...)
 | 
			
		||||
+#define grub_boot_time(fmt, ...) grub_dprintf("boot", fmt "\n", ##__VA_ARGS__)
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 #define _grub_min(a, b, _a, _b)						      \
 | 
			
		||||
							
								
								
									
										30
									
								
								0257-modules-make-.module_license-read-only.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								0257-modules-make-.module_license-read-only.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Thu, 24 Feb 2022 16:32:51 -0500
 | 
			
		||||
Subject: [PATCH] modules: make .module_license read-only
 | 
			
		||||
 | 
			
		||||
Currently .module_license is set writable (that is, the section has the
 | 
			
		||||
SHF_WRITE flag set) in the module's ELF headers.  This probably never
 | 
			
		||||
actually matters, but it can't possibly be correct.
 | 
			
		||||
 | 
			
		||||
This patch sets that data as "const", which causes that flag not to be
 | 
			
		||||
set.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 include/grub/dl.h | 2 +-
 | 
			
		||||
 1 file changed, 1 insertion(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/include/grub/dl.h b/include/grub/dl.h
 | 
			
		||||
index 20d870f2a4..618ae6f474 100644
 | 
			
		||||
--- a/include/grub/dl.h
 | 
			
		||||
+++ b/include/grub/dl.h
 | 
			
		||||
@@ -121,7 +121,7 @@ grub_mod_fini (void)
 | 
			
		||||
 #define ATTRIBUTE_USED __unused__
 | 
			
		||||
 #endif
 | 
			
		||||
 #define GRUB_MOD_LICENSE(license)	\
 | 
			
		||||
-  static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license;
 | 
			
		||||
+  static const char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), ATTRIBUTE_USED)) = "LICENSE=" license;
 | 
			
		||||
 #define GRUB_MOD_DEP(name)	\
 | 
			
		||||
 static const char grub_module_depend_##name[] \
 | 
			
		||||
  __attribute__((section(GRUB_MOD_SECTION(moddeps)), ATTRIBUTE_USED)) = #name
 | 
			
		||||
							
								
								
									
										39
									
								
								0258-modules-strip-.llvm_addrsig-sections-and-similar.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								0258-modules-strip-.llvm_addrsig-sections-and-similar.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Thu, 24 Feb 2022 16:40:11 -0500
 | 
			
		||||
Subject: [PATCH] modules: strip .llvm_addrsig sections and similar.
 | 
			
		||||
 | 
			
		||||
Currently grub modules built with clang or gcc have several sections
 | 
			
		||||
which we don't actually need or support.
 | 
			
		||||
 | 
			
		||||
We already have a list of section to skip in genmod.sh, and this patch
 | 
			
		||||
adds the following sections to that list (as well as a few newlines):
 | 
			
		||||
 | 
			
		||||
.note.gnu.property
 | 
			
		||||
.llvm*
 | 
			
		||||
 | 
			
		||||
Note that the glob there won't work without a new enough linker, but the
 | 
			
		||||
failure is just reversion to the status quo, so that's not a big problem.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/genmod.sh.in | 5 ++++-
 | 
			
		||||
 1 file changed, 4 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in
 | 
			
		||||
index 1250589b3f..c2c5280d75 100644
 | 
			
		||||
--- a/grub-core/genmod.sh.in
 | 
			
		||||
+++ b/grub-core/genmod.sh.in
 | 
			
		||||
@@ -57,8 +57,11 @@ if test x@TARGET_APPLE_LINKER@ != x1; then
 | 
			
		||||
 	    @TARGET_STRIP@ --strip-unneeded \
 | 
			
		||||
 		-K grub_mod_init -K grub_mod_fini \
 | 
			
		||||
 		-K _grub_mod_init -K _grub_mod_fini \
 | 
			
		||||
-		-R .note.gnu.gold-version -R .note.GNU-stack \
 | 
			
		||||
+		-R .note.GNU-stack \
 | 
			
		||||
+		-R .note.gnu.gold-version \
 | 
			
		||||
+		-R .note.gnu.property \
 | 
			
		||||
 		-R .gnu.build.attributes \
 | 
			
		||||
+		-R '.llvm*' \
 | 
			
		||||
 		-R .rel.gnu.build.attributes \
 | 
			
		||||
 		-R .rela.gnu.build.attributes \
 | 
			
		||||
 		-R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \
 | 
			
		||||
@ -0,0 +1,35 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Mon, 21 Mar 2022 16:56:10 -0400
 | 
			
		||||
Subject: [PATCH] modules: Don't allocate space for non-allocable sections.
 | 
			
		||||
 | 
			
		||||
Currently when loading grub modules, we allocate space for all sections,
 | 
			
		||||
including those without SHF_ALLOC set.  We then copy the sections that
 | 
			
		||||
/do/ have SHF_ALLOC set into the allocated memory, leaving some of our
 | 
			
		||||
allocation untouched forever.  Additionally, on platforms with GOT
 | 
			
		||||
fixups and trampolines, we currently compute alignment round-ups for the
 | 
			
		||||
sections and sections with sh_size = 0.
 | 
			
		||||
 | 
			
		||||
This patch removes the extra space from the allocation computation, and
 | 
			
		||||
makes the allocation computation loop skip empty sections as the loading
 | 
			
		||||
loop does.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/kern/dl.c | 3 +++
 | 
			
		||||
 1 file changed, 3 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
 | 
			
		||||
index f304494574..aef8af8aa7 100644
 | 
			
		||||
--- a/grub-core/kern/dl.c
 | 
			
		||||
+++ b/grub-core/kern/dl.c
 | 
			
		||||
@@ -289,6 +289,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
        i < e->e_shnum;
 | 
			
		||||
        i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize))
 | 
			
		||||
     {
 | 
			
		||||
+      if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC))
 | 
			
		||||
+	continue;
 | 
			
		||||
+
 | 
			
		||||
       tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size;
 | 
			
		||||
       if (talign < s->sh_addralign)
 | 
			
		||||
 	talign = s->sh_addralign;
 | 
			
		||||
@ -0,0 +1,81 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Fri, 25 Mar 2022 15:40:12 -0400
 | 
			
		||||
Subject: [PATCH] pe: add the DOS header struct and fix some bad naming.
 | 
			
		||||
 | 
			
		||||
In order to properly validate a loaded kernel's support for being loaded
 | 
			
		||||
without a writable stack or executable, we need to be able to properly
 | 
			
		||||
parse arbitrary PE headers.
 | 
			
		||||
 | 
			
		||||
Currently, pe32.h is written in such a way that the MS-DOS header that
 | 
			
		||||
tells us where to find the PE header in the binary can't be accessed.
 | 
			
		||||
Further, for some reason it calls the DOS MZ magic "GRUB_PE32_MAGIC".
 | 
			
		||||
 | 
			
		||||
This patch adds the structure for the DOS header, renames the DOS magic
 | 
			
		||||
define, and adds defines for the actual PE magic.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/arm64/linux.c |  2 +-
 | 
			
		||||
 include/grub/efi/pe32.h        | 28 ++++++++++++++++++++++++++--
 | 
			
		||||
 2 files changed, 27 insertions(+), 3 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
 | 
			
		||||
index d2af47c2c0..cc67f43906 100644
 | 
			
		||||
--- a/grub-core/loader/arm64/linux.c
 | 
			
		||||
+++ b/grub-core/loader/arm64/linux.c
 | 
			
		||||
@@ -58,7 +58,7 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh)
 | 
			
		||||
   if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE)
 | 
			
		||||
     return grub_error(GRUB_ERR_BAD_OS, "invalid magic number");
 | 
			
		||||
 
 | 
			
		||||
-  if ((lh->code0 & 0xffff) != GRUB_PE32_MAGIC)
 | 
			
		||||
+  if ((lh->code0 & 0xffff) != GRUB_DOS_MAGIC)
 | 
			
		||||
     return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
 | 
			
		||||
 		       N_("plain image kernel not supported - rebuild with CONFIG_(U)EFI_STUB enabled"));
 | 
			
		||||
 
 | 
			
		||||
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
 | 
			
		||||
index a43adf2746..2a5e1ee003 100644
 | 
			
		||||
--- a/include/grub/efi/pe32.h
 | 
			
		||||
+++ b/include/grub/efi/pe32.h
 | 
			
		||||
@@ -46,7 +46,30 @@
 | 
			
		||||
 
 | 
			
		||||
 #define GRUB_PE32_MSDOS_STUB_SIZE	0x80
 | 
			
		||||
 
 | 
			
		||||
-#define GRUB_PE32_MAGIC			0x5a4d
 | 
			
		||||
+#define GRUB_DOS_MAGIC			0x5a4d
 | 
			
		||||
+
 | 
			
		||||
+struct grub_dos_header
 | 
			
		||||
+{
 | 
			
		||||
+  grub_uint16_t magic;
 | 
			
		||||
+  grub_uint16_t cblp;
 | 
			
		||||
+  grub_uint16_t cp;
 | 
			
		||||
+  grub_uint16_t crlc;
 | 
			
		||||
+  grub_uint16_t cparhdr;
 | 
			
		||||
+  grub_uint16_t minalloc;
 | 
			
		||||
+  grub_uint16_t maxalloc;
 | 
			
		||||
+  grub_uint16_t ss;
 | 
			
		||||
+  grub_uint16_t sp;
 | 
			
		||||
+  grub_uint16_t csum;
 | 
			
		||||
+  grub_uint16_t ip;
 | 
			
		||||
+  grub_uint16_t cs;
 | 
			
		||||
+  grub_uint16_t lfarlc;
 | 
			
		||||
+  grub_uint16_t ovno;
 | 
			
		||||
+  grub_uint16_t res0[4];
 | 
			
		||||
+  grub_uint16_t oemid;
 | 
			
		||||
+  grub_uint16_t oeminfo;
 | 
			
		||||
+  grub_uint16_t res1[10];
 | 
			
		||||
+  grub_uint32_t lfanew;
 | 
			
		||||
+};
 | 
			
		||||
 
 | 
			
		||||
 /* According to the spec, the minimal alignment is 512 bytes...
 | 
			
		||||
    But some examples (such as EFI drivers in the Intel
 | 
			
		||||
@@ -280,7 +303,8 @@ struct grub_pe32_section_table
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
-#define GRUB_PE32_SIGNATURE_SIZE 4
 | 
			
		||||
+#define GRUB_PE32_SIGNATURE_SIZE		4
 | 
			
		||||
+#define GRUB_PE32_SIGNATURE			"PE\0\0"
 | 
			
		||||
 
 | 
			
		||||
 struct grub_pe32_header
 | 
			
		||||
 {
 | 
			
		||||
@ -0,0 +1,85 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Wed, 9 Feb 2022 16:08:20 -0500
 | 
			
		||||
Subject: [PATCH] EFI: allocate kernel in EFI_RUNTIME_SERVICES_CODE instead of
 | 
			
		||||
 EFI_LOADER_DATA.
 | 
			
		||||
 | 
			
		||||
On some of the firmwares with more security mitigations, EFI_LOADER_DATA
 | 
			
		||||
doesn't get you executable memory, and we take a fault and reboot when
 | 
			
		||||
we enter kernel.
 | 
			
		||||
 | 
			
		||||
This patch correctly allocates the kernel code as EFI_RUNTIME_SERVICES_CODE
 | 
			
		||||
rather than EFI_LOADER_DATA.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
[rharwood: use kernel_size]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/loader/i386/efi/linux.c | 19 +++++++++++++------
 | 
			
		||||
 1 file changed, 13 insertions(+), 6 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
index 9e5c11ac69..92b2fb5091 100644
 | 
			
		||||
--- a/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
+++ b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
@@ -86,7 +86,9 @@ kernel_free(void *addr, grub_efi_uintn_t size)
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void *
 | 
			
		||||
-kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
 | 
			
		||||
+kernel_alloc(grub_efi_uintn_t size,
 | 
			
		||||
+	     grub_efi_memory_type_t memtype,
 | 
			
		||||
+	     const char * const errmsg)
 | 
			
		||||
 {
 | 
			
		||||
   void *addr = 0;
 | 
			
		||||
   unsigned int i;
 | 
			
		||||
@@ -112,7 +114,7 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
 | 
			
		||||
       prev_max = max;
 | 
			
		||||
       addr = grub_efi_allocate_pages_real (max, pages,
 | 
			
		||||
 					   max_addresses[i].alloc_type,
 | 
			
		||||
-					   GRUB_EFI_LOADER_DATA);
 | 
			
		||||
+					   memtype);
 | 
			
		||||
       if (addr)
 | 
			
		||||
 	grub_dprintf ("linux", "Allocated at %p\n", addr);
 | 
			
		||||
     }
 | 
			
		||||
@@ -242,7 +244,8 @@ grub_cmd_initrd (grub_command_t cmd, int argc, char *argv[])
 | 
			
		||||
 	}
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
-  initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
 | 
			
		||||
+  initrd_mem = kernel_alloc(size, GRUB_EFI_RUNTIME_SERVICES_DATA,
 | 
			
		||||
+			    N_("can't allocate initrd"));
 | 
			
		||||
   if (initrd_mem == NULL)
 | 
			
		||||
     goto fail;
 | 
			
		||||
   grub_dprintf ("linux", "initrd_mem = %p\n", initrd_mem);
 | 
			
		||||
@@ -393,7 +396,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
     }
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
-  params = kernel_alloc (sizeof(*params), "cannot allocate kernel parameters");
 | 
			
		||||
+  params = kernel_alloc (sizeof(*params), GRUB_EFI_RUNTIME_SERVICES_DATA,
 | 
			
		||||
+			 "cannot allocate kernel parameters");
 | 
			
		||||
   if (!params)
 | 
			
		||||
     goto fail;
 | 
			
		||||
   grub_dprintf ("linux", "params = %p\n", params);
 | 
			
		||||
@@ -415,7 +419,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_dprintf ("linux", "new lh is at %p\n", lh);
 | 
			
		||||
 
 | 
			
		||||
   grub_dprintf ("linux", "setting up cmdline\n");
 | 
			
		||||
-  cmdline = kernel_alloc (lh->cmdline_size + 1, N_("can't allocate cmdline"));
 | 
			
		||||
+  cmdline = kernel_alloc (lh->cmdline_size + 1,
 | 
			
		||||
+			  GRUB_EFI_RUNTIME_SERVICES_DATA,
 | 
			
		||||
+			  N_("can't allocate cmdline"));
 | 
			
		||||
   if (!cmdline)
 | 
			
		||||
     goto fail;
 | 
			
		||||
   grub_dprintf ("linux", "cmdline = %p\n", cmdline);
 | 
			
		||||
@@ -461,7 +467,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   max_addresses[1].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
 | 
			
		||||
   max_addresses[2].addr = GRUB_EFI_MAX_ALLOCATION_ADDRESS;
 | 
			
		||||
   kernel_size = lh->init_size;
 | 
			
		||||
-  kernel_mem = kernel_alloc (kernel_size, N_("can't allocate kernel"));
 | 
			
		||||
+  kernel_mem = kernel_alloc (kernel_size, GRUB_EFI_RUNTIME_SERVICES_CODE,
 | 
			
		||||
+			     N_("can't allocate kernel"));
 | 
			
		||||
   restore_addresses();
 | 
			
		||||
   if (!kernel_mem)
 | 
			
		||||
     goto fail;
 | 
			
		||||
							
								
								
									
										378
									
								
								0262-modules-load-module-sections-at-page-aligned-address.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								0262-modules-load-module-sections-at-page-aligned-address.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,378 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Mon, 21 Mar 2022 17:45:40 -0400
 | 
			
		||||
Subject: [PATCH] modules: load module sections at page-aligned addresses
 | 
			
		||||
 | 
			
		||||
Currently we load module sections at whatever alignment gcc+ld happened
 | 
			
		||||
to dump into the ELF section header, which is often pretty useless.  For
 | 
			
		||||
example, by default time.mod has these sections on a current x86_64
 | 
			
		||||
build:
 | 
			
		||||
 | 
			
		||||
$ eu-readelf -a grub-core/time.mod |& grep ^Section -A13
 | 
			
		||||
Section Headers:
 | 
			
		||||
[Nr] Name            Type         Addr  Off      Size     ES Flags Lk Inf Al
 | 
			
		||||
[ 0]                 NULL         0     00000000 00000000  0        0   0  0
 | 
			
		||||
[ 1] .text           PROGBITS     0     00000040 0000015e  0 AX     0   0  1
 | 
			
		||||
[ 2] .rela.text      RELA         0     00000458 000001e0 24 I      8   1  8
 | 
			
		||||
[ 3] .rodata.str1.1  PROGBITS     0     0000019e 000000a1  1 AMS    0   0  1
 | 
			
		||||
[ 4] .module_license PROGBITS     0     00000240 0000000f  0 A      0   0  8
 | 
			
		||||
[ 5] .data           PROGBITS     0     0000024f 00000000  0 WA     0   0  1
 | 
			
		||||
[ 6] .bss            NOBITS       0     00000250 00000008  0 WA     0   0  8
 | 
			
		||||
[ 7] .modname        PROGBITS     0     00000250 00000005  0        0   0  1
 | 
			
		||||
[ 8] .symtab         SYMTAB       0     00000258 00000150 24        9   6  8
 | 
			
		||||
[ 9] .strtab         STRTAB       0     000003a8 000000ab  0        0   0  1
 | 
			
		||||
[10] .shstrtab       STRTAB       0     00000638 00000059  0        0   0  1
 | 
			
		||||
 | 
			
		||||
With NX protections being page based, loading sections with either a 1
 | 
			
		||||
or 8 *byte* alignment does absolutely nothing to help us out.
 | 
			
		||||
 | 
			
		||||
This patch switches most EFI platforms to load module sections at 4kB
 | 
			
		||||
page-aligned addresses.  To do so, it adds an new per-arch function,
 | 
			
		||||
grub_arch_dl_min_alignment(), which returns the alignment needed for
 | 
			
		||||
dynamically loaded sections (in bytes).  Currently it sets it to 4096
 | 
			
		||||
when GRUB_MACHINE_EFI is true on x86_64, i386, arm, arm64, and emu, and
 | 
			
		||||
1-byte alignment on everything else.
 | 
			
		||||
 | 
			
		||||
It then changes the allocation size computation and the loader code in
 | 
			
		||||
grub_dl_load_segments() to align the locations and sizes up to these
 | 
			
		||||
boundaries, and fills any added padding with zeros.
 | 
			
		||||
 | 
			
		||||
All of this happens before relocations are applied, so the relocations
 | 
			
		||||
factor that in with no change.
 | 
			
		||||
 | 
			
		||||
As an aside, initially Daniel Kiper and I thought that it might be a
 | 
			
		||||
better idea to split the modules up into top-level sections as
 | 
			
		||||
.text.modules, .rodata.modules, .data.modules, etc., so that their page
 | 
			
		||||
permissions would get set by the loader that's loading grub itself.
 | 
			
		||||
This turns out to have two significant downsides: 1) either in mkimage
 | 
			
		||||
or in grub_dl_relocate_symbols(), you wind up having to dynamically
 | 
			
		||||
process the relocations to accommodate the moved module sections, and 2)
 | 
			
		||||
you then need to change the permissions on the modules and change them
 | 
			
		||||
back while relocating them in grub_dl_relocate_symbols(), which means
 | 
			
		||||
that any loader that /does/ honor the section flags but does /not/
 | 
			
		||||
generally support NX with the memory attributes API will cause grub to
 | 
			
		||||
fail.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/kern/arm/dl.c     | 13 +++++++++++++
 | 
			
		||||
 grub-core/kern/arm64/dl.c   | 13 +++++++++++++
 | 
			
		||||
 grub-core/kern/dl.c         | 29 +++++++++++++++++++++--------
 | 
			
		||||
 grub-core/kern/emu/full.c   | 13 +++++++++++++
 | 
			
		||||
 grub-core/kern/i386/dl.c    | 13 +++++++++++++
 | 
			
		||||
 grub-core/kern/ia64/dl.c    |  9 +++++++++
 | 
			
		||||
 grub-core/kern/mips/dl.c    |  8 ++++++++
 | 
			
		||||
 grub-core/kern/powerpc/dl.c |  9 +++++++++
 | 
			
		||||
 grub-core/kern/riscv/dl.c   | 13 +++++++++++++
 | 
			
		||||
 grub-core/kern/sparc64/dl.c |  9 +++++++++
 | 
			
		||||
 grub-core/kern/x86_64/dl.c  | 13 +++++++++++++
 | 
			
		||||
 include/grub/dl.h           |  2 ++
 | 
			
		||||
 docs/grub-dev.texi          |  6 +++---
 | 
			
		||||
 13 files changed, 139 insertions(+), 11 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c
 | 
			
		||||
index eab9d17ff2..9260737936 100644
 | 
			
		||||
--- a/grub-core/kern/arm/dl.c
 | 
			
		||||
+++ b/grub-core/kern/arm/dl.c
 | 
			
		||||
@@ -278,3 +278,16 @@ grub_arch_dl_check_header (void *ehdr)
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+#ifdef GRUB_MACHINE_EFI
 | 
			
		||||
+  return 4096;
 | 
			
		||||
+#else
 | 
			
		||||
+  return 1;
 | 
			
		||||
+#endif
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c
 | 
			
		||||
index 512e5a80b0..0d4a26857f 100644
 | 
			
		||||
--- a/grub-core/kern/arm64/dl.c
 | 
			
		||||
+++ b/grub-core/kern/arm64/dl.c
 | 
			
		||||
@@ -196,3 +196,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+#ifdef GRUB_MACHINE_EFI
 | 
			
		||||
+  return 4096;
 | 
			
		||||
+#else
 | 
			
		||||
+  return 1;
 | 
			
		||||
+#endif
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
 | 
			
		||||
index aef8af8aa7..8c7aacef39 100644
 | 
			
		||||
--- a/grub-core/kern/dl.c
 | 
			
		||||
+++ b/grub-core/kern/dl.c
 | 
			
		||||
@@ -277,7 +277,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
 {
 | 
			
		||||
   unsigned i;
 | 
			
		||||
   const Elf_Shdr *s;
 | 
			
		||||
-  grub_size_t tsize = 0, talign = 1;
 | 
			
		||||
+  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 got;
 | 
			
		||||
@@ -285,16 +285,24 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
 #endif
 | 
			
		||||
   char *ptr;
 | 
			
		||||
 
 | 
			
		||||
+  arch_addralign = grub_arch_dl_min_alignment ();
 | 
			
		||||
+
 | 
			
		||||
   for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff);
 | 
			
		||||
        i < e->e_shnum;
 | 
			
		||||
        i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize))
 | 
			
		||||
     {
 | 
			
		||||
+      grub_size_t sh_addralign;
 | 
			
		||||
+      grub_size_t sh_size;
 | 
			
		||||
+
 | 
			
		||||
       if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC))
 | 
			
		||||
 	continue;
 | 
			
		||||
 
 | 
			
		||||
-      tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size;
 | 
			
		||||
-      if (talign < s->sh_addralign)
 | 
			
		||||
-	talign = s->sh_addralign;
 | 
			
		||||
+      sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign);
 | 
			
		||||
+      sh_size = ALIGN_UP(s->sh_size, sh_addralign);
 | 
			
		||||
+
 | 
			
		||||
+      tsize = ALIGN_UP (tsize, sh_addralign) + sh_size;
 | 
			
		||||
+      if (talign < sh_addralign)
 | 
			
		||||
+	talign = sh_addralign;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
 #if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv)
 | 
			
		||||
@@ -323,6 +331,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
        i < e->e_shnum;
 | 
			
		||||
        i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
 | 
			
		||||
     {
 | 
			
		||||
+      grub_size_t sh_addralign = ALIGN_UP(s->sh_addralign, arch_addralign);
 | 
			
		||||
+      grub_size_t sh_size = ALIGN_UP(s->sh_size, sh_addralign);
 | 
			
		||||
+
 | 
			
		||||
       if (s->sh_flags & SHF_ALLOC)
 | 
			
		||||
 	{
 | 
			
		||||
 	  grub_dl_segment_t seg;
 | 
			
		||||
@@ -335,17 +346,19 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
 	    {
 | 
			
		||||
 	      void *addr;
 | 
			
		||||
 
 | 
			
		||||
-	      ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign);
 | 
			
		||||
+	      ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign);
 | 
			
		||||
 	      addr = ptr;
 | 
			
		||||
-	      ptr += s->sh_size;
 | 
			
		||||
+	      ptr += sh_size;
 | 
			
		||||
 
 | 
			
		||||
 	      switch (s->sh_type)
 | 
			
		||||
 		{
 | 
			
		||||
 		case SHT_PROGBITS:
 | 
			
		||||
 		  grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size);
 | 
			
		||||
+		  grub_memset ((char *)addr + s->sh_size, 0,
 | 
			
		||||
+			       sh_size - s->sh_size);
 | 
			
		||||
 		  break;
 | 
			
		||||
 		case SHT_NOBITS:
 | 
			
		||||
-		  grub_memset (addr, 0, s->sh_size);
 | 
			
		||||
+		  grub_memset (addr, 0, sh_size);
 | 
			
		||||
 		  break;
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
@@ -354,7 +367,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
 	  else
 | 
			
		||||
 	    seg->addr = 0;
 | 
			
		||||
 
 | 
			
		||||
-	  seg->size = s->sh_size;
 | 
			
		||||
+	  seg->size = sh_size;
 | 
			
		||||
 	  seg->section = i;
 | 
			
		||||
 	  seg->next = mod->segment;
 | 
			
		||||
 	  mod->segment = seg;
 | 
			
		||||
diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c
 | 
			
		||||
index e8d63b1f5f..1de1c28eb0 100644
 | 
			
		||||
--- a/grub-core/kern/emu/full.c
 | 
			
		||||
+++ b/grub-core/kern/emu/full.c
 | 
			
		||||
@@ -67,3 +67,16 @@ grub_arch_dl_init_linker (void)
 | 
			
		||||
 }
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+#ifdef GRUB_MACHINE_EFI
 | 
			
		||||
+  return 4096;
 | 
			
		||||
+#else
 | 
			
		||||
+  return 1;
 | 
			
		||||
+#endif
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c
 | 
			
		||||
index 1346da5cc9..d6b4681fc9 100644
 | 
			
		||||
--- a/grub-core/kern/i386/dl.c
 | 
			
		||||
+++ b/grub-core/kern/i386/dl.c
 | 
			
		||||
@@ -79,3 +79,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+#ifdef GRUB_MACHINE_EFI
 | 
			
		||||
+  return 4096;
 | 
			
		||||
+#else
 | 
			
		||||
+  return 1;
 | 
			
		||||
+#endif
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c
 | 
			
		||||
index db59300fea..92d82c5750 100644
 | 
			
		||||
--- a/grub-core/kern/ia64/dl.c
 | 
			
		||||
+++ b/grub-core/kern/ia64/dl.c
 | 
			
		||||
@@ -148,3 +148,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
     }
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+  return 1;
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c
 | 
			
		||||
index 5d7d299c74..6d83bd71e9 100644
 | 
			
		||||
--- a/grub-core/kern/mips/dl.c
 | 
			
		||||
+++ b/grub-core/kern/mips/dl.c
 | 
			
		||||
@@ -272,3 +272,11 @@ grub_arch_dl_init_linker (void)
 | 
			
		||||
   grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+  return 1;
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c
 | 
			
		||||
index cdd61b305f..5d9ba2e158 100644
 | 
			
		||||
--- a/grub-core/kern/powerpc/dl.c
 | 
			
		||||
+++ b/grub-core/kern/powerpc/dl.c
 | 
			
		||||
@@ -167,3 +167,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+  return 1;
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c
 | 
			
		||||
index f26b12aaa4..aa18f9e990 100644
 | 
			
		||||
--- a/grub-core/kern/riscv/dl.c
 | 
			
		||||
+++ b/grub-core/kern/riscv/dl.c
 | 
			
		||||
@@ -343,3 +343,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+#ifdef GRUB_MACHINE_EFI
 | 
			
		||||
+  return 4096;
 | 
			
		||||
+#else
 | 
			
		||||
+  return 1;
 | 
			
		||||
+#endif
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c
 | 
			
		||||
index f3d960186b..f054f08241 100644
 | 
			
		||||
--- a/grub-core/kern/sparc64/dl.c
 | 
			
		||||
+++ b/grub-core/kern/sparc64/dl.c
 | 
			
		||||
@@ -189,3 +189,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+  return 1;
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c
 | 
			
		||||
index e5a8bdcf4f..a105dc50ce 100644
 | 
			
		||||
--- a/grub-core/kern/x86_64/dl.c
 | 
			
		||||
+++ b/grub-core/kern/x86_64/dl.c
 | 
			
		||||
@@ -119,3 +119,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
 
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+/*
 | 
			
		||||
+ * Tell the loader what our minimum section alignment is.
 | 
			
		||||
+ */
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void)
 | 
			
		||||
+{
 | 
			
		||||
+#ifdef GRUB_MACHINE_EFI
 | 
			
		||||
+  return 4096;
 | 
			
		||||
+#else
 | 
			
		||||
+  return 1;
 | 
			
		||||
+#endif
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/include/grub/dl.h b/include/grub/dl.h
 | 
			
		||||
index 618ae6f474..f36ed5cb17 100644
 | 
			
		||||
--- a/include/grub/dl.h
 | 
			
		||||
+++ b/include/grub/dl.h
 | 
			
		||||
@@ -280,6 +280,8 @@ grub_err_t grub_arch_dl_check_header (void *ehdr);
 | 
			
		||||
 grub_err_t
 | 
			
		||||
 grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 | 
			
		||||
 			       Elf_Shdr *s, grub_dl_segment_t seg);
 | 
			
		||||
+grub_size_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void);
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 #if defined (_mips)
 | 
			
		||||
diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
 | 
			
		||||
index 90083772c8..c23ba313dc 100644
 | 
			
		||||
--- a/docs/grub-dev.texi
 | 
			
		||||
+++ b/docs/grub-dev.texi
 | 
			
		||||
@@ -755,9 +755,9 @@ declare startup asm file ($cpu_$platform_startup) as well as any other files
 | 
			
		||||
 (e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c).
 | 
			
		||||
 At this stage you will also need to add dummy dl.c and cache.S with functions
 | 
			
		||||
 grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t
 | 
			
		||||
-grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and
 | 
			
		||||
-void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They
 | 
			
		||||
-won't be used for now.
 | 
			
		||||
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c), grub_uint32_t
 | 
			
		||||
+grub_arch_dl_min_alignment (void), and void grub_arch_sync_caches (void
 | 
			
		||||
+*address, grub_size_t len) (cache.S). They won't be used for now.
 | 
			
		||||
 
 | 
			
		||||
 You will need to create directory include/$cpu/$platform and a file
 | 
			
		||||
 include/$cpu/types.h. The later folowing this template:
 | 
			
		||||
							
								
								
									
										317
									
								
								0263-nx-add-memory-attribute-get-set-API.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								0263-nx-add-memory-attribute-get-set-API.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,317 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Tue, 22 Mar 2022 10:56:21 -0400
 | 
			
		||||
Subject: [PATCH] nx: add memory attribute get/set API
 | 
			
		||||
 | 
			
		||||
For NX, we need to set the page access permission attributes for write
 | 
			
		||||
and execute permissions.
 | 
			
		||||
 | 
			
		||||
This patch adds two new primitives, grub_set_mem_attrs() and
 | 
			
		||||
grub_clear_mem_attrs(), and associated constant definitions, to be used
 | 
			
		||||
for that purpose.
 | 
			
		||||
 | 
			
		||||
For most platforms, it adds a dummy implementation that returns
 | 
			
		||||
GRUB_ERR_NONE.  On EFI platforms, it adds a common helper function,
 | 
			
		||||
grub_efi_status_to_err(), which translates EFI error codes to grub error
 | 
			
		||||
codes, adds headers for the EFI Memory Attribute Protocol (still pending
 | 
			
		||||
standardization), and an implementation of the grub nx primitives using
 | 
			
		||||
it.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
[rharwood: add pjones's none/nyi fixup]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/kern/efi/efi.c |  36 +++++++++++++
 | 
			
		||||
 grub-core/kern/efi/mm.c  | 131 +++++++++++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
 include/grub/efi/api.h   |  25 +++++++++
 | 
			
		||||
 include/grub/efi/efi.h   |   2 +
 | 
			
		||||
 include/grub/mm.h        |  32 ++++++++++++
 | 
			
		||||
 5 files changed, 226 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
 | 
			
		||||
index 7fcca69c17..4ac2b2754e 100644
 | 
			
		||||
--- a/grub-core/kern/efi/efi.c
 | 
			
		||||
+++ b/grub-core/kern/efi/efi.c
 | 
			
		||||
@@ -1096,3 +1096,39 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
 | 
			
		||||
 
 | 
			
		||||
   return 0;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+grub_err_t
 | 
			
		||||
+grub_efi_status_to_err (grub_efi_status_t status)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_err_t err;
 | 
			
		||||
+  switch (status)
 | 
			
		||||
+    {
 | 
			
		||||
+    case GRUB_EFI_SUCCESS:
 | 
			
		||||
+      err = GRUB_ERR_NONE;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_EFI_INVALID_PARAMETER:
 | 
			
		||||
+    default:
 | 
			
		||||
+      err = GRUB_ERR_BAD_ARGUMENT;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_EFI_OUT_OF_RESOURCES:
 | 
			
		||||
+      err = GRUB_ERR_OUT_OF_MEMORY;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_EFI_DEVICE_ERROR:
 | 
			
		||||
+      err = GRUB_ERR_IO;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_EFI_WRITE_PROTECTED:
 | 
			
		||||
+      err = GRUB_ERR_WRITE_ERROR;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_EFI_SECURITY_VIOLATION:
 | 
			
		||||
+      err = GRUB_ERR_ACCESS_DENIED;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_EFI_NOT_FOUND:
 | 
			
		||||
+      err = GRUB_ERR_FILE_NOT_FOUND;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_EFI_ABORTED:
 | 
			
		||||
+      err = GRUB_ERR_WAIT;
 | 
			
		||||
+      break;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+  return err;
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
 | 
			
		||||
index e84961d078..2c33758ed7 100644
 | 
			
		||||
--- a/grub-core/kern/efi/mm.c
 | 
			
		||||
+++ b/grub-core/kern/efi/mm.c
 | 
			
		||||
@@ -738,3 +738,134 @@ grub_efi_get_ram_base(grub_addr_t *base_addr)
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
 #endif
 | 
			
		||||
+
 | 
			
		||||
+static inline grub_uint64_t
 | 
			
		||||
+grub_mem_attrs_to_uefi_mem_attrs (grub_uint64_t attrs)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_uint64_t ret = GRUB_EFI_MEMORY_RP |
 | 
			
		||||
+		      GRUB_EFI_MEMORY_RO |
 | 
			
		||||
+		      GRUB_EFI_MEMORY_XP;
 | 
			
		||||
+
 | 
			
		||||
+  if (attrs & GRUB_MEM_ATTR_R)
 | 
			
		||||
+    ret &= ~GRUB_EFI_MEMORY_RP;
 | 
			
		||||
+
 | 
			
		||||
+  if (attrs & GRUB_MEM_ATTR_W)
 | 
			
		||||
+    ret &= ~GRUB_EFI_MEMORY_RO;
 | 
			
		||||
+
 | 
			
		||||
+  if (attrs & GRUB_MEM_ATTR_X)
 | 
			
		||||
+    ret &= ~GRUB_EFI_MEMORY_XP;
 | 
			
		||||
+
 | 
			
		||||
+  return ret;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline grub_uint64_t
 | 
			
		||||
+uefi_mem_attrs_to_grub_mem_attrs (grub_uint64_t attrs)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_uint64_t ret = GRUB_MEM_ATTR_R |
 | 
			
		||||
+		      GRUB_MEM_ATTR_W |
 | 
			
		||||
+		      GRUB_MEM_ATTR_X;
 | 
			
		||||
+
 | 
			
		||||
+  if (attrs & GRUB_EFI_MEMORY_RP)
 | 
			
		||||
+    ret &= ~GRUB_MEM_ATTR_R;
 | 
			
		||||
+
 | 
			
		||||
+  if (attrs & GRUB_EFI_MEMORY_RO)
 | 
			
		||||
+    ret &= ~GRUB_MEM_ATTR_W;
 | 
			
		||||
+
 | 
			
		||||
+  if (attrs & GRUB_EFI_MEMORY_XP)
 | 
			
		||||
+    ret &= ~GRUB_MEM_ATTR_X;
 | 
			
		||||
+
 | 
			
		||||
+  return ret;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+grub_err_t
 | 
			
		||||
+grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_uint64_t *attrs)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_efi_memory_attribute_protocol_t *proto;
 | 
			
		||||
+  grub_efi_physical_address_t physaddr = addr;
 | 
			
		||||
+  grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
 | 
			
		||||
+  grub_efi_status_t efi_status;
 | 
			
		||||
+
 | 
			
		||||
+  proto = grub_efi_locate_protocol (&protocol_guid, 0);
 | 
			
		||||
+  if (!proto)
 | 
			
		||||
+    return GRUB_ERR_NOT_IMPLEMENTED_YET;
 | 
			
		||||
+
 | 
			
		||||
+  if (physaddr & 0xfff || size & 0xfff || size == 0 || attrs == NULL)
 | 
			
		||||
+    {
 | 
			
		||||
+      grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" and attrs %p\n",
 | 
			
		||||
+		    __func__, physaddr, physaddr+size-1, attrs);
 | 
			
		||||
+      return 0;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+  efi_status = efi_call_4(proto->get_memory_attributes,
 | 
			
		||||
+			  proto, physaddr, size, attrs);
 | 
			
		||||
+  *attrs = uefi_mem_attrs_to_grub_mem_attrs (*attrs);
 | 
			
		||||
+
 | 
			
		||||
+  return grub_efi_status_to_err (efi_status);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+grub_err_t
 | 
			
		||||
+grub_update_mem_attrs (grub_addr_t addr, grub_size_t size,
 | 
			
		||||
+		       grub_uint64_t set_attrs, grub_uint64_t clear_attrs)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_efi_memory_attribute_protocol_t *proto;
 | 
			
		||||
+  grub_efi_physical_address_t physaddr = addr;
 | 
			
		||||
+  grub_efi_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
 | 
			
		||||
+  grub_efi_status_t efi_status = GRUB_EFI_SUCCESS;
 | 
			
		||||
+  grub_uint64_t before = 0, after = 0, uefi_set_attrs, uefi_clear_attrs;
 | 
			
		||||
+  grub_err_t err;
 | 
			
		||||
+
 | 
			
		||||
+  proto = grub_efi_locate_protocol (&protocol_guid, 0);
 | 
			
		||||
+  if (!proto)
 | 
			
		||||
+    return GRUB_ERR_NONE;
 | 
			
		||||
+
 | 
			
		||||
+  err = grub_get_mem_attrs (addr, size, &before);
 | 
			
		||||
+  if (err)
 | 
			
		||||
+    grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n",
 | 
			
		||||
+		  addr, size, &before, err);
 | 
			
		||||
+
 | 
			
		||||
+  if (physaddr & 0xfff || size & 0xfff || size == 0)
 | 
			
		||||
+    {
 | 
			
		||||
+      grub_dprintf ("nx", "%s called on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" +%s%s%s -%s%s%s\n",
 | 
			
		||||
+		    __func__, physaddr, physaddr + size - 1,
 | 
			
		||||
+		    (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
 | 
			
		||||
+		    (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
 | 
			
		||||
+		    (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "",
 | 
			
		||||
+		    (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
 | 
			
		||||
+		    (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
 | 
			
		||||
+		    (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "");
 | 
			
		||||
+      return 0;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+  uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs);
 | 
			
		||||
+  grub_dprintf ("nx", "translating set_attrs from 0x%lx to 0x%lx\n", set_attrs, uefi_set_attrs);
 | 
			
		||||
+  uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs);
 | 
			
		||||
+  grub_dprintf ("nx", "translating clear_attrs from 0x%lx to 0x%lx\n", clear_attrs, uefi_clear_attrs);
 | 
			
		||||
+  if (uefi_set_attrs)
 | 
			
		||||
+    efi_status = efi_call_4(proto->set_memory_attributes,
 | 
			
		||||
+			    proto, physaddr, size, uefi_set_attrs);
 | 
			
		||||
+  if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs)
 | 
			
		||||
+    efi_status = efi_call_4(proto->clear_memory_attributes,
 | 
			
		||||
+			    proto, physaddr, size, uefi_clear_attrs);
 | 
			
		||||
+
 | 
			
		||||
+  err = grub_get_mem_attrs (addr, size, &after);
 | 
			
		||||
+  if (err)
 | 
			
		||||
+    grub_dprintf ("nx", "grub_get_mem_attrs(0x%"PRIxGRUB_ADDR", %"PRIuGRUB_SIZE", %p) -> 0x%x\n",
 | 
			
		||||
+		  addr, size, &after, err);
 | 
			
		||||
+
 | 
			
		||||
+  grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" before:%c%c%c after:%c%c%c\n",
 | 
			
		||||
+		(set_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
 | 
			
		||||
+		(set_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
 | 
			
		||||
+		(set_attrs & GRUB_MEM_ATTR_X) ? "x" : "",
 | 
			
		||||
+		(clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
 | 
			
		||||
+		(clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
 | 
			
		||||
+		(clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "",
 | 
			
		||||
+		addr, addr + size - 1,
 | 
			
		||||
+		(before & GRUB_MEM_ATTR_R) ? 'r' : '-',
 | 
			
		||||
+		(before & GRUB_MEM_ATTR_W) ? 'w' : '-',
 | 
			
		||||
+		(before & GRUB_MEM_ATTR_X) ? 'x' : '-',
 | 
			
		||||
+		(after & GRUB_MEM_ATTR_R) ? 'r' : '-',
 | 
			
		||||
+		(after & GRUB_MEM_ATTR_W) ? 'w' : '-',
 | 
			
		||||
+		(after & GRUB_MEM_ATTR_X) ? 'x' : '-');
 | 
			
		||||
+
 | 
			
		||||
+  return grub_efi_status_to_err (efi_status);
 | 
			
		||||
+}
 | 
			
		||||
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
 | 
			
		||||
index f431f49973..464842ba37 100644
 | 
			
		||||
--- a/include/grub/efi/api.h
 | 
			
		||||
+++ b/include/grub/efi/api.h
 | 
			
		||||
@@ -363,6 +363,11 @@
 | 
			
		||||
       { 0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
 | 
			
		||||
   }
 | 
			
		||||
 
 | 
			
		||||
+#define GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID \
 | 
			
		||||
+  { 0xf4560cf6, 0x40ec, 0x4b4a, \
 | 
			
		||||
+    { 0xa1, 0x92, 0xbf, 0x1d, 0x57, 0xd0, 0xb1, 0x89 } \
 | 
			
		||||
+  }
 | 
			
		||||
+
 | 
			
		||||
 struct grub_efi_sal_system_table
 | 
			
		||||
 {
 | 
			
		||||
   grub_uint32_t signature;
 | 
			
		||||
@@ -2102,6 +2107,26 @@ struct grub_efi_ip6_config_manual_address {
 | 
			
		||||
 };
 | 
			
		||||
 typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t;
 | 
			
		||||
 
 | 
			
		||||
+struct grub_efi_memory_attribute_protocol
 | 
			
		||||
+{
 | 
			
		||||
+  grub_efi_status_t (*get_memory_attributes) (
 | 
			
		||||
+			    struct grub_efi_memory_attribute_protocol *this,
 | 
			
		||||
+			    grub_efi_physical_address_t base_address,
 | 
			
		||||
+			    grub_efi_uint64_t length,
 | 
			
		||||
+			    grub_efi_uint64_t *attributes);
 | 
			
		||||
+  grub_efi_status_t (*set_memory_attributes) (
 | 
			
		||||
+			    struct grub_efi_memory_attribute_protocol *this,
 | 
			
		||||
+			    grub_efi_physical_address_t base_address,
 | 
			
		||||
+			    grub_efi_uint64_t length,
 | 
			
		||||
+			    grub_efi_uint64_t attributes);
 | 
			
		||||
+  grub_efi_status_t (*clear_memory_attributes) (
 | 
			
		||||
+			    struct grub_efi_memory_attribute_protocol *this,
 | 
			
		||||
+			    grub_efi_physical_address_t base_address,
 | 
			
		||||
+			    grub_efi_uint64_t length,
 | 
			
		||||
+			    grub_efi_uint64_t attributes);
 | 
			
		||||
+};
 | 
			
		||||
+typedef struct grub_efi_memory_attribute_protocol grub_efi_memory_attribute_protocol_t;
 | 
			
		||||
+
 | 
			
		||||
 #if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
 | 
			
		||||
   || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
 | 
			
		||||
   || defined(__riscv)
 | 
			
		||||
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
 | 
			
		||||
index ec52083c49..34825c4adc 100644
 | 
			
		||||
--- a/include/grub/efi/efi.h
 | 
			
		||||
+++ b/include/grub/efi/efi.h
 | 
			
		||||
@@ -164,4 +164,6 @@ struct grub_net_card;
 | 
			
		||||
 grub_efi_handle_t
 | 
			
		||||
 grub_efinet_get_device_handle (struct grub_net_card *card);
 | 
			
		||||
 
 | 
			
		||||
+grub_err_t EXPORT_FUNC(grub_efi_status_to_err) (grub_efi_status_t status);
 | 
			
		||||
+
 | 
			
		||||
 #endif /* ! GRUB_EFI_EFI_HEADER */
 | 
			
		||||
diff --git a/include/grub/mm.h b/include/grub/mm.h
 | 
			
		||||
index 9c38dd3ca5..d81623d226 100644
 | 
			
		||||
--- a/include/grub/mm.h
 | 
			
		||||
+++ b/include/grub/mm.h
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
 
 | 
			
		||||
 #include <grub/types.h>
 | 
			
		||||
 #include <grub/symbol.h>
 | 
			
		||||
+#include <grub/err.h>
 | 
			
		||||
 #include <config.h>
 | 
			
		||||
 
 | 
			
		||||
 #ifndef NULL
 | 
			
		||||
@@ -38,6 +39,37 @@ void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size);
 | 
			
		||||
 void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size);
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+#define GRUB_MEM_ATTR_R	0x0000000000000004LLU
 | 
			
		||||
+#define GRUB_MEM_ATTR_W	0x0000000000000002LLU
 | 
			
		||||
+#define GRUB_MEM_ATTR_X	0x0000000000000001LLU
 | 
			
		||||
+
 | 
			
		||||
+#ifdef GRUB_MACHINE_EFI
 | 
			
		||||
+grub_err_t EXPORT_FUNC(grub_get_mem_attrs) (grub_addr_t addr,
 | 
			
		||||
+					    grub_size_t size,
 | 
			
		||||
+					    grub_uint64_t *attrs);
 | 
			
		||||
+grub_err_t EXPORT_FUNC(grub_update_mem_attrs) (grub_addr_t addr,
 | 
			
		||||
+					       grub_size_t size,
 | 
			
		||||
+					       grub_uint64_t set_attrs,
 | 
			
		||||
+					       grub_uint64_t clear_attrs);
 | 
			
		||||
+#else /* !GRUB_MACHINE_EFI */
 | 
			
		||||
+static inline grub_err_t
 | 
			
		||||
+grub_get_mem_attrs (grub_addr_t addr __attribute__((__unused__)),
 | 
			
		||||
+		    grub_size_t size __attribute__((__unused__)),
 | 
			
		||||
+		    grub_uint64_t *attrs __attribute__((__unused__)))
 | 
			
		||||
+{
 | 
			
		||||
+  return GRUB_ERR_NONE;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline grub_err_t
 | 
			
		||||
+grub_update_mem_attrs (grub_addr_t addr __attribute__((__unused__)),
 | 
			
		||||
+		       grub_size_t size __attribute__((__unused__)),
 | 
			
		||||
+		       grub_uint64_t set_attrs __attribute__((__unused__)),
 | 
			
		||||
+		       grub_uint64_t clear_attrs __attribute__((__unused__)))
 | 
			
		||||
+{
 | 
			
		||||
+  return GRUB_ERR_NONE;
 | 
			
		||||
+}
 | 
			
		||||
+#endif /* GRUB_MACHINE_EFI */
 | 
			
		||||
+
 | 
			
		||||
 void grub_mm_check_real (const char *file, int line);
 | 
			
		||||
 #define grub_mm_check() grub_mm_check_real (GRUB_FILE, __LINE__);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										263
									
								
								0264-nx-set-page-permissions-for-loaded-modules.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								0264-nx-set-page-permissions-for-loaded-modules.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,263 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Mon, 21 Mar 2022 17:46:35 -0400
 | 
			
		||||
Subject: [PATCH] nx: set page permissions for loaded modules.
 | 
			
		||||
 | 
			
		||||
For NX, we need to set write and executable permissions on the sections
 | 
			
		||||
of grub modules when we load them.
 | 
			
		||||
 | 
			
		||||
On sections with SHF_ALLOC set, which is typically everything except
 | 
			
		||||
.modname and the symbol and string tables, this patch clears the Read
 | 
			
		||||
Only flag on sections that have the ELF flag SHF_WRITE set, and clears
 | 
			
		||||
the No eXecute flag on sections with SHF_EXECINSTR set.  In all other
 | 
			
		||||
cases it sets both flags.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
[rharwood: arm tgptr -> tgaddr]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/kern/dl.c | 120 +++++++++++++++++++++++++++++++++++++++-------------
 | 
			
		||||
 include/grub/dl.h   |  44 +++++++++++++++++++
 | 
			
		||||
 2 files changed, 134 insertions(+), 30 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
 | 
			
		||||
index 8c7aacef39..d5de80186f 100644
 | 
			
		||||
--- a/grub-core/kern/dl.c
 | 
			
		||||
+++ b/grub-core/kern/dl.c
 | 
			
		||||
@@ -285,6 +285,8 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
 #endif
 | 
			
		||||
   char *ptr;
 | 
			
		||||
 
 | 
			
		||||
+  grub_dprintf ("modules", "loading segments for \"%s\"\n", mod->name);
 | 
			
		||||
+
 | 
			
		||||
   arch_addralign = grub_arch_dl_min_alignment ();
 | 
			
		||||
 
 | 
			
		||||
   for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff);
 | 
			
		||||
@@ -384,6 +386,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
 | 
			
		||||
   ptr += got;
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+  grub_dprintf ("modules", "done loading segments for \"%s\"\n", mod->name);
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -517,23 +520,6 @@ grub_dl_find_section (Elf_Ehdr *e, const char *name)
 | 
			
		||||
       return s;
 | 
			
		||||
   return NULL;
 | 
			
		||||
 }
 | 
			
		||||
-static long
 | 
			
		||||
-grub_dl_find_section_index (Elf_Ehdr *e, const char *name)
 | 
			
		||||
-{
 | 
			
		||||
-  Elf_Shdr *s;
 | 
			
		||||
-  const char *str;
 | 
			
		||||
-  unsigned i;
 | 
			
		||||
-
 | 
			
		||||
-  s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
 | 
			
		||||
-  str = (char *) e + s->sh_offset;
 | 
			
		||||
-
 | 
			
		||||
-  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
 | 
			
		||||
-       i < e->e_shnum;
 | 
			
		||||
-       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
 | 
			
		||||
-    if (grub_strcmp (str + s->sh_name, name) == 0)
 | 
			
		||||
-      return (long)i;
 | 
			
		||||
-  return -1;
 | 
			
		||||
-}
 | 
			
		||||
 
 | 
			
		||||
 /* Me, Vladimir Serbinenko, hereby I add this module check as per new
 | 
			
		||||
    GNU module policy. Note that this license check is informative only.
 | 
			
		||||
@@ -662,6 +648,7 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
 | 
			
		||||
   Elf_Shdr *s;
 | 
			
		||||
   unsigned i;
 | 
			
		||||
 
 | 
			
		||||
+  grub_dprintf ("modules", "relocating symbols for \"%s\"\n", mod->name);
 | 
			
		||||
   for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
 | 
			
		||||
        i < e->e_shnum;
 | 
			
		||||
        i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
 | 
			
		||||
@@ -670,24 +657,95 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
 | 
			
		||||
 	grub_dl_segment_t seg;
 | 
			
		||||
 	grub_err_t err;
 | 
			
		||||
 
 | 
			
		||||
-	/* Find the target segment.  */
 | 
			
		||||
-	for (seg = mod->segment; seg; seg = seg->next)
 | 
			
		||||
-	  if (seg->section == s->sh_info)
 | 
			
		||||
-	    break;
 | 
			
		||||
+	seg = grub_dl_find_segment(mod, s->sh_info);
 | 
			
		||||
+        if (!seg)
 | 
			
		||||
+	  continue;
 | 
			
		||||
 
 | 
			
		||||
-	if (seg)
 | 
			
		||||
-	  {
 | 
			
		||||
-	    if (!mod->symtab)
 | 
			
		||||
-	      return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table");
 | 
			
		||||
+	if (!mod->symtab)
 | 
			
		||||
+	  return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table");
 | 
			
		||||
 
 | 
			
		||||
-	    err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg);
 | 
			
		||||
-	    if (err)
 | 
			
		||||
-	      return err;
 | 
			
		||||
-	  }
 | 
			
		||||
+	err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg);
 | 
			
		||||
+	if (err)
 | 
			
		||||
+	  return err;
 | 
			
		||||
       }
 | 
			
		||||
 
 | 
			
		||||
+  grub_dprintf ("modules", "done relocating symbols for \"%s\"\n", mod->name);
 | 
			
		||||
   return GRUB_ERR_NONE;
 | 
			
		||||
 }
 | 
			
		||||
+
 | 
			
		||||
+static grub_err_t
 | 
			
		||||
+grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr)
 | 
			
		||||
+{
 | 
			
		||||
+  unsigned i;
 | 
			
		||||
+  const Elf_Shdr *s;
 | 
			
		||||
+  const Elf_Ehdr *e = 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;
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
+  grub_dprintf ("modules", "updating memory attributes for \"%s\"\n",
 | 
			
		||||
+		mod->name);
 | 
			
		||||
+  for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff);
 | 
			
		||||
+       i < e->e_shnum;
 | 
			
		||||
+       i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize))
 | 
			
		||||
+    {
 | 
			
		||||
+      grub_dl_segment_t seg;
 | 
			
		||||
+      grub_uint64_t set_attrs = GRUB_MEM_ATTR_R;
 | 
			
		||||
+      grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X;
 | 
			
		||||
+
 | 
			
		||||
+      seg = grub_dl_find_segment(mod, i);
 | 
			
		||||
+      if (!seg)
 | 
			
		||||
+	continue;
 | 
			
		||||
+
 | 
			
		||||
+      if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC))
 | 
			
		||||
+	continue;
 | 
			
		||||
+
 | 
			
		||||
+      if (s->sh_flags & SHF_WRITE)
 | 
			
		||||
+	{
 | 
			
		||||
+	  set_attrs |= GRUB_MEM_ATTR_W;
 | 
			
		||||
+	  clear_attrs &= ~GRUB_MEM_ATTR_W;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+      if (s->sh_flags & SHF_EXECINSTR)
 | 
			
		||||
+	{
 | 
			
		||||
+	  set_attrs |= GRUB_MEM_ATTR_X;
 | 
			
		||||
+	  clear_attrs &= ~GRUB_MEM_ATTR_X;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+      grub_dprintf ("modules", "setting memory attrs for section \"%s\" to -%s%s%s+%s%s%s\n",
 | 
			
		||||
+		    grub_dl_get_section_name(e, s),
 | 
			
		||||
+		    (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
 | 
			
		||||
+		    (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
 | 
			
		||||
+		    (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "",
 | 
			
		||||
+		    (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "",
 | 
			
		||||
+		    (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "",
 | 
			
		||||
+		    (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "");
 | 
			
		||||
+      grub_update_mem_attrs ((grub_addr_t)(seg->addr), seg->size, set_attrs, clear_attrs);
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv)
 | 
			
		||||
+  tgaddr = grub_min((grub_addr_t)mod->tramp, (grub_addr_t)mod->got);
 | 
			
		||||
+  tgsz = grub_max((grub_addr_t)mod->trampptr, (grub_addr_t)mod->gotptr) - tgaddr;
 | 
			
		||||
+
 | 
			
		||||
+  if (tgsz)
 | 
			
		||||
+    {
 | 
			
		||||
+      tgsz = ALIGN_UP(tgsz, arch_addralign);
 | 
			
		||||
+
 | 
			
		||||
+      grub_dprintf ("modules", "updating attributes for GOT and trampolines\n",
 | 
			
		||||
+		    mod->name);
 | 
			
		||||
+      grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_X,
 | 
			
		||||
+			     GRUB_MEM_ATTR_W);
 | 
			
		||||
+    }
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
+  grub_dprintf ("modules", "done updating module memory attributes for \"%s\"\n",
 | 
			
		||||
+		mod->name);
 | 
			
		||||
+
 | 
			
		||||
+  return GRUB_ERR_NONE;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void
 | 
			
		||||
 grub_dl_print_gdb_info (grub_dl_t mod, Elf_Ehdr *e)
 | 
			
		||||
 {
 | 
			
		||||
@@ -753,6 +811,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size)
 | 
			
		||||
   mod->ref_count = 1;
 | 
			
		||||
 
 | 
			
		||||
   grub_dprintf ("modules", "relocating to %p\n", mod);
 | 
			
		||||
+
 | 
			
		||||
   /* Me, Vladimir Serbinenko, hereby I add this module check as per new
 | 
			
		||||
      GNU module policy. Note that this license check is informative only.
 | 
			
		||||
      Modules have to be licensed under GPLv3 or GPLv3+ (optionally
 | 
			
		||||
@@ -766,7 +825,8 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size)
 | 
			
		||||
       || grub_dl_resolve_dependencies (mod, e)
 | 
			
		||||
       || grub_dl_load_segments (mod, e)
 | 
			
		||||
       || grub_dl_resolve_symbols (mod, e)
 | 
			
		||||
-      || grub_dl_relocate_symbols (mod, e))
 | 
			
		||||
+      || grub_dl_relocate_symbols (mod, e)
 | 
			
		||||
+      || grub_dl_set_mem_attrs (mod, e))
 | 
			
		||||
     {
 | 
			
		||||
       mod->fini = 0;
 | 
			
		||||
       grub_dl_unload (mod);
 | 
			
		||||
diff --git a/include/grub/dl.h b/include/grub/dl.h
 | 
			
		||||
index f36ed5cb17..45ac8e339f 100644
 | 
			
		||||
--- a/include/grub/dl.h
 | 
			
		||||
+++ b/include/grub/dl.h
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
 #include <grub/elf.h>
 | 
			
		||||
 #include <grub/list.h>
 | 
			
		||||
 #include <grub/misc.h>
 | 
			
		||||
+#include <grub/mm.h>
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 /*
 | 
			
		||||
@@ -268,6 +269,49 @@ grub_dl_is_persistent (grub_dl_t mod)
 | 
			
		||||
   return mod->persistent;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static inline const char *
 | 
			
		||||
+grub_dl_get_section_name (const Elf_Ehdr *e, const Elf_Shdr *s)
 | 
			
		||||
+{
 | 
			
		||||
+  Elf_Shdr *str_s;
 | 
			
		||||
+  const char *str;
 | 
			
		||||
+
 | 
			
		||||
+  str_s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
 | 
			
		||||
+  str = (char *) e + str_s->sh_offset;
 | 
			
		||||
+
 | 
			
		||||
+  return str + s->sh_name;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static inline long
 | 
			
		||||
+grub_dl_find_section_index (Elf_Ehdr *e, const char *name)
 | 
			
		||||
+{
 | 
			
		||||
+  Elf_Shdr *s;
 | 
			
		||||
+  const char *str;
 | 
			
		||||
+  unsigned i;
 | 
			
		||||
+
 | 
			
		||||
+  s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
 | 
			
		||||
+  str = (char *) e + s->sh_offset;
 | 
			
		||||
+
 | 
			
		||||
+  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
 | 
			
		||||
+       i < e->e_shnum;
 | 
			
		||||
+       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
 | 
			
		||||
+    if (grub_strcmp (str + s->sh_name, name) == 0)
 | 
			
		||||
+      return (long)i;
 | 
			
		||||
+  return -1;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/* Return the segment for a section of index N */
 | 
			
		||||
+static inline grub_dl_segment_t
 | 
			
		||||
+grub_dl_find_segment (grub_dl_t mod, unsigned n)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_dl_segment_t seg;
 | 
			
		||||
+
 | 
			
		||||
+  for (seg = mod->segment; seg; seg = seg->next)
 | 
			
		||||
+    if (seg->section == n)
 | 
			
		||||
+      return seg;
 | 
			
		||||
+
 | 
			
		||||
+  return NULL;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 void * EXPORT_FUNC(grub_resolve_symbol) (const char *name);
 | 
			
		||||
							
								
								
									
										565
									
								
								0265-nx-set-attrs-in-our-kernel-loaders.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										565
									
								
								0265-nx-set-attrs-in-our-kernel-loaders.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,565 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Tue, 22 Mar 2022 10:57:07 -0400
 | 
			
		||||
Subject: [PATCH] nx: set attrs in our kernel loaders
 | 
			
		||||
 | 
			
		||||
For NX, our kernel loaders need to set write and execute page
 | 
			
		||||
permissions on allocated pages and the stack.
 | 
			
		||||
 | 
			
		||||
This patch adds those calls.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
[rharwood: fix stack_attrs undefined, fix aarch64 callsites]
 | 
			
		||||
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 grub-core/kern/efi/mm.c            |  77 +++++++++++++++++
 | 
			
		||||
 grub-core/loader/arm64/linux.c     |  16 +++-
 | 
			
		||||
 grub-core/loader/arm64/xen_boot.c  |   4 +-
 | 
			
		||||
 grub-core/loader/efi/chainloader.c |  11 +++
 | 
			
		||||
 grub-core/loader/efi/linux.c       | 164 ++++++++++++++++++++++++++++++++++++-
 | 
			
		||||
 grub-core/loader/i386/efi/linux.c  |  26 +++++-
 | 
			
		||||
 grub-core/loader/i386/linux.c      |   5 ++
 | 
			
		||||
 include/grub/efi/efi.h             |   6 +-
 | 
			
		||||
 include/grub/efi/linux.h           |  16 +++-
 | 
			
		||||
 include/grub/efi/pe32.h            |   2 +
 | 
			
		||||
 10 files changed, 312 insertions(+), 15 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
 | 
			
		||||
index 2c33758ed7..e460b072e6 100644
 | 
			
		||||
--- a/grub-core/kern/efi/mm.c
 | 
			
		||||
+++ b/grub-core/kern/efi/mm.c
 | 
			
		||||
@@ -610,6 +610,81 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map,
 | 
			
		||||
 }
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
+grub_addr_t grub_stack_addr = (grub_addr_t)-1ll;
 | 
			
		||||
+grub_size_t grub_stack_size = 0;
 | 
			
		||||
+
 | 
			
		||||
+static void
 | 
			
		||||
+grub_nx_init (void)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_uint64_t attrs, stack_attrs;
 | 
			
		||||
+  grub_err_t err;
 | 
			
		||||
+  grub_addr_t stack_current, stack_end;
 | 
			
		||||
+  const grub_uint64_t page_size = 4096;
 | 
			
		||||
+  const grub_uint64_t page_mask = ~(page_size - 1);
 | 
			
		||||
+
 | 
			
		||||
+  /*
 | 
			
		||||
+   * These are to confirm that the flags are working as expected when
 | 
			
		||||
+   * debugging.
 | 
			
		||||
+   */
 | 
			
		||||
+  attrs = 0;
 | 
			
		||||
+  stack_current = (grub_addr_t)grub_nx_init & page_mask;
 | 
			
		||||
+  err = grub_get_mem_attrs (stack_current, page_size, &attrs);
 | 
			
		||||
+  if (err)
 | 
			
		||||
+    {
 | 
			
		||||
+      grub_dprintf ("nx",
 | 
			
		||||
+		    "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n",
 | 
			
		||||
+		    stack_current, err);
 | 
			
		||||
+      grub_error_pop ();
 | 
			
		||||
+    }
 | 
			
		||||
+  else
 | 
			
		||||
+    grub_dprintf ("nx", "page attrs for grub_nx_init (%p) are %c%c%c\n",
 | 
			
		||||
+		  grub_dl_load_core,
 | 
			
		||||
+		  (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-',
 | 
			
		||||
+		  (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-',
 | 
			
		||||
+		  (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-');
 | 
			
		||||
+
 | 
			
		||||
+  stack_current = (grub_addr_t)&stack_current & page_mask;
 | 
			
		||||
+  err = grub_get_mem_attrs (stack_current, page_size, &stack_attrs);
 | 
			
		||||
+  if (err)
 | 
			
		||||
+    {
 | 
			
		||||
+      grub_dprintf ("nx",
 | 
			
		||||
+		    "grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n",
 | 
			
		||||
+		    stack_current, err);
 | 
			
		||||
+      grub_error_pop ();
 | 
			
		||||
+    }
 | 
			
		||||
+  else
 | 
			
		||||
+    {
 | 
			
		||||
+      attrs = stack_attrs;
 | 
			
		||||
+      grub_dprintf ("nx", "page attrs for stack (%p) are %c%c%c\n",
 | 
			
		||||
+                    &attrs,
 | 
			
		||||
+                    (attrs & GRUB_MEM_ATTR_R) ? 'r' : '-',
 | 
			
		||||
+                    (attrs & GRUB_MEM_ATTR_R) ? 'w' : '-',
 | 
			
		||||
+                    (attrs & GRUB_MEM_ATTR_R) ? 'x' : '-');
 | 
			
		||||
+    }
 | 
			
		||||
+  for (stack_end = stack_current + page_size ;
 | 
			
		||||
+       !(attrs & GRUB_MEM_ATTR_R);
 | 
			
		||||
+       stack_end += page_size)
 | 
			
		||||
+    {
 | 
			
		||||
+      err = grub_get_mem_attrs (stack_current, page_size, &attrs);
 | 
			
		||||
+      if (err)
 | 
			
		||||
+	{
 | 
			
		||||
+	  grub_dprintf ("nx",
 | 
			
		||||
+			"grub_get_mem_attrs(0x%"PRIxGRUB_UINT64_T", ...) -> 0x%x\n",
 | 
			
		||||
+			stack_current, err);
 | 
			
		||||
+	  grub_error_pop ();
 | 
			
		||||
+	  break;
 | 
			
		||||
+	}
 | 
			
		||||
+    }
 | 
			
		||||
+  if (stack_end > stack_current)
 | 
			
		||||
+    {
 | 
			
		||||
+      grub_stack_addr = stack_current;
 | 
			
		||||
+      grub_stack_size = stack_end - stack_current;
 | 
			
		||||
+      grub_dprintf ("nx",
 | 
			
		||||
+		    "detected stack from 0x%"PRIxGRUB_ADDR" to 0x%"PRIxGRUB_ADDR"\n",
 | 
			
		||||
+		    grub_stack_addr, grub_stack_addr + grub_stack_size - 1);
 | 
			
		||||
+    }
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 void
 | 
			
		||||
 grub_efi_mm_init (void)
 | 
			
		||||
 {
 | 
			
		||||
@@ -623,6 +698,8 @@ grub_efi_mm_init (void)
 | 
			
		||||
   grub_efi_uint64_t required_pages;
 | 
			
		||||
   int mm_status;
 | 
			
		||||
 
 | 
			
		||||
+  grub_nx_init ();
 | 
			
		||||
+
 | 
			
		||||
   /* Prepare a memory region to store two memory maps.  */
 | 
			
		||||
   memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
 | 
			
		||||
   if (! memory_map)
 | 
			
		||||
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
 | 
			
		||||
index cc67f43906..de85583487 100644
 | 
			
		||||
--- a/grub-core/loader/arm64/linux.c
 | 
			
		||||
+++ b/grub-core/loader/arm64/linux.c
 | 
			
		||||
@@ -172,7 +172,8 @@ free_params (void)
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 grub_err_t
 | 
			
		||||
-grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args)
 | 
			
		||||
+grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args,
 | 
			
		||||
+				int nx_supported)
 | 
			
		||||
 {
 | 
			
		||||
   grub_err_t retval;
 | 
			
		||||
 
 | 
			
		||||
@@ -182,7 +183,8 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args)
 | 
			
		||||
 
 | 
			
		||||
   grub_dprintf ("linux", "linux command line: '%s'\n", args);
 | 
			
		||||
 
 | 
			
		||||
-  retval = grub_efi_linux_boot ((char *)addr, handover_offset, (void *)addr);
 | 
			
		||||
+  retval = grub_efi_linux_boot (addr, size, handover_offset,
 | 
			
		||||
+				(void *)addr, nx_supported);
 | 
			
		||||
 
 | 
			
		||||
   /* Never reached... */
 | 
			
		||||
   free_params();
 | 
			
		||||
@@ -192,7 +194,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, char *args)
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
 grub_linux_boot (void)
 | 
			
		||||
 {
 | 
			
		||||
-  return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr, linux_args));
 | 
			
		||||
+  return grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr,
 | 
			
		||||
+					(grub_size_t)kernel_size,
 | 
			
		||||
+					linux_args,
 | 
			
		||||
+					0);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
@@ -340,6 +345,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_off_t filelen;
 | 
			
		||||
   grub_uint32_t align;
 | 
			
		||||
   void *kernel = NULL;
 | 
			
		||||
+  int nx_supported = 1;
 | 
			
		||||
 
 | 
			
		||||
   grub_dl_ref (my_mod);
 | 
			
		||||
 
 | 
			
		||||
@@ -376,6 +382,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_dprintf ("linux", "kernel entry offset : %d\n", handover_offset);
 | 
			
		||||
   grub_dprintf ("linux", "kernel alignment    : 0x%x\n", align);
 | 
			
		||||
 
 | 
			
		||||
+  err = grub_efi_check_nx_image_support((grub_addr_t)kernel, filelen, &nx_supported);
 | 
			
		||||
+  if (err != GRUB_ERR_NONE)
 | 
			
		||||
+    goto fail;
 | 
			
		||||
+
 | 
			
		||||
   grub_loader_unset();
 | 
			
		||||
 
 | 
			
		||||
   kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1);
 | 
			
		||||
diff --git a/grub-core/loader/arm64/xen_boot.c b/grub-core/loader/arm64/xen_boot.c
 | 
			
		||||
index d9b7a9ba40..6e7e920416 100644
 | 
			
		||||
--- a/grub-core/loader/arm64/xen_boot.c
 | 
			
		||||
+++ b/grub-core/loader/arm64/xen_boot.c
 | 
			
		||||
@@ -266,7 +266,9 @@ xen_boot (void)
 | 
			
		||||
     return err;
 | 
			
		||||
 
 | 
			
		||||
   return grub_arch_efi_linux_boot_image (xen_hypervisor->start,
 | 
			
		||||
-					  xen_hypervisor->cmdline);
 | 
			
		||||
+                                         xen_hypervisor->size,
 | 
			
		||||
+                                         xen_hypervisor->cmdline,
 | 
			
		||||
+                                         0);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void
 | 
			
		||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
index fb874f1855..dd31ac9bb3 100644
 | 
			
		||||
--- a/grub-core/loader/efi/chainloader.c
 | 
			
		||||
+++ b/grub-core/loader/efi/chainloader.c
 | 
			
		||||
@@ -1070,6 +1070,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
       goto fail;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+  /*
 | 
			
		||||
+   * The OS kernel is going to set its own permissions when it takes over
 | 
			
		||||
+   * paging a few million instructions from now, and load_image() will set up
 | 
			
		||||
+   * anything that's needed based on the section headers, so there's no point
 | 
			
		||||
+   * in doing anything but clearing the protection bits here.
 | 
			
		||||
+   */
 | 
			
		||||
+  grub_dprintf("nx", "setting attributes for %p (%lu bytes) to %llx\n",
 | 
			
		||||
+	       (void *)(grub_addr_t)address, fsize, 0llu);
 | 
			
		||||
+  grub_update_mem_attrs (address, fsize,
 | 
			
		||||
+			 GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W|GRUB_MEM_ATTR_X, 0);
 | 
			
		||||
+
 | 
			
		||||
 #if defined (__i386__) || defined (__x86_64__)
 | 
			
		||||
   if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
 | 
			
		||||
     {
 | 
			
		||||
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
 | 
			
		||||
index 9265cf4200..277f352e0c 100644
 | 
			
		||||
--- a/grub-core/loader/efi/linux.c
 | 
			
		||||
+++ b/grub-core/loader/efi/linux.c
 | 
			
		||||
@@ -26,16 +26,127 @@
 | 
			
		||||
 
 | 
			
		||||
 #pragma GCC diagnostic push
 | 
			
		||||
 #pragma GCC diagnostic ignored "-Wcast-align"
 | 
			
		||||
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
 | 
			
		||||
+
 | 
			
		||||
+grub_err_t
 | 
			
		||||
+grub_efi_check_nx_image_support (grub_addr_t kernel_addr,
 | 
			
		||||
+				 grub_size_t kernel_size,
 | 
			
		||||
+				 int *nx_supported)
 | 
			
		||||
+{
 | 
			
		||||
+  struct grub_dos_header *doshdr;
 | 
			
		||||
+  grub_size_t sz = sizeof (*doshdr);
 | 
			
		||||
+
 | 
			
		||||
+  struct grub_pe32_header_32 *pe32;
 | 
			
		||||
+  struct grub_pe32_header_64 *pe64;
 | 
			
		||||
+
 | 
			
		||||
+  int image_is_compatible = 0;
 | 
			
		||||
+  int is_64_bit;
 | 
			
		||||
+
 | 
			
		||||
+  if (kernel_size < sz)
 | 
			
		||||
+    return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small"));
 | 
			
		||||
+
 | 
			
		||||
+  doshdr = (void *)kernel_addr;
 | 
			
		||||
+
 | 
			
		||||
+  if ((doshdr->magic & 0xffff) != GRUB_DOS_MAGIC)
 | 
			
		||||
+    return grub_error (GRUB_ERR_BAD_OS, N_("kernel DOS magic is invalid"));
 | 
			
		||||
+
 | 
			
		||||
+  sz = doshdr->lfanew + sizeof (*pe32);
 | 
			
		||||
+  if (kernel_size < sz)
 | 
			
		||||
+    return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small"));
 | 
			
		||||
+
 | 
			
		||||
+  pe32 = (struct grub_pe32_header_32 *)(kernel_addr + doshdr->lfanew);
 | 
			
		||||
+  pe64 = (struct grub_pe32_header_64 *)pe32;
 | 
			
		||||
+
 | 
			
		||||
+  if (grub_memcmp (pe32->signature, GRUB_PE32_SIGNATURE,
 | 
			
		||||
+		   GRUB_PE32_SIGNATURE_SIZE) != 0)
 | 
			
		||||
+    return grub_error (GRUB_ERR_BAD_OS, N_("kernel PE magic is invalid"));
 | 
			
		||||
+
 | 
			
		||||
+  switch (pe32->coff_header.machine)
 | 
			
		||||
+    {
 | 
			
		||||
+    case GRUB_PE32_MACHINE_ARMTHUMB_MIXED:
 | 
			
		||||
+    case GRUB_PE32_MACHINE_I386:
 | 
			
		||||
+    case GRUB_PE32_MACHINE_RISCV32:
 | 
			
		||||
+      is_64_bit = 0;
 | 
			
		||||
+      break;
 | 
			
		||||
+    case GRUB_PE32_MACHINE_ARM64:
 | 
			
		||||
+    case GRUB_PE32_MACHINE_IA64:
 | 
			
		||||
+    case GRUB_PE32_MACHINE_RISCV64:
 | 
			
		||||
+    case GRUB_PE32_MACHINE_X86_64:
 | 
			
		||||
+      is_64_bit = 1;
 | 
			
		||||
+      break;
 | 
			
		||||
+    default:
 | 
			
		||||
+      return grub_error (GRUB_ERR_BAD_OS, N_("PE machine type 0x%04hx unknown"),
 | 
			
		||||
+			 pe32->coff_header.machine);
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+  if (is_64_bit)
 | 
			
		||||
+    {
 | 
			
		||||
+      sz = doshdr->lfanew + sizeof (*pe64);
 | 
			
		||||
+      if (kernel_size < sz)
 | 
			
		||||
+	return grub_error (GRUB_ERR_BAD_OS, N_("kernel is too small"));
 | 
			
		||||
+
 | 
			
		||||
+      if (pe64->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT)
 | 
			
		||||
+	image_is_compatible = 1;
 | 
			
		||||
+    }
 | 
			
		||||
+  else
 | 
			
		||||
+    {
 | 
			
		||||
+      if (pe32->optional_header.dll_characteristics & GRUB_PE32_NX_COMPAT)
 | 
			
		||||
+	image_is_compatible = 1;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+  *nx_supported = image_is_compatible;
 | 
			
		||||
+  return GRUB_ERR_NONE;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+grub_err_t
 | 
			
		||||
+grub_efi_check_nx_required (int *nx_required)
 | 
			
		||||
+{
 | 
			
		||||
+  grub_efi_status_t status;
 | 
			
		||||
+  grub_efi_guid_t guid = GRUB_EFI_SHIM_LOCK_GUID;
 | 
			
		||||
+  grub_size_t mok_policy_sz = 0;
 | 
			
		||||
+  char *mok_policy = NULL;
 | 
			
		||||
+  grub_uint32_t mok_policy_attrs = 0;
 | 
			
		||||
+
 | 
			
		||||
+  status = grub_efi_get_variable_with_attributes ("MokPolicy", &guid,
 | 
			
		||||
+						  &mok_policy_sz,
 | 
			
		||||
+						  (void **)&mok_policy,
 | 
			
		||||
+						  &mok_policy_attrs);
 | 
			
		||||
+  if (status == GRUB_EFI_NOT_FOUND ||
 | 
			
		||||
+      mok_policy_sz == 0 ||
 | 
			
		||||
+      mok_policy == NULL)
 | 
			
		||||
+    {
 | 
			
		||||
+      *nx_required = 0;
 | 
			
		||||
+      return GRUB_ERR_NONE;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+  *nx_required = 0;
 | 
			
		||||
+  if (mok_policy_sz < 1 ||
 | 
			
		||||
+      mok_policy_attrs != (GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
 | 
			
		||||
+			   GRUB_EFI_VARIABLE_RUNTIME_ACCESS) ||
 | 
			
		||||
+      (mok_policy[mok_policy_sz-1] & GRUB_MOK_POLICY_NX_REQUIRED))
 | 
			
		||||
+    *nx_required = 1;
 | 
			
		||||
+
 | 
			
		||||
+  return GRUB_ERR_NONE;
 | 
			
		||||
+}
 | 
			
		||||
 
 | 
			
		||||
 typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
 | 
			
		||||
 
 | 
			
		||||
 grub_err_t
 | 
			
		||||
-grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
 | 
			
		||||
-		     void *kernel_params)
 | 
			
		||||
+grub_efi_linux_boot (grub_addr_t kernel_addr, grub_size_t kernel_size,
 | 
			
		||||
+		     grub_off_t handover_offset, void *kernel_params,
 | 
			
		||||
+		     int nx_supported)
 | 
			
		||||
 {
 | 
			
		||||
   grub_efi_loaded_image_t *loaded_image = NULL;
 | 
			
		||||
   handover_func hf;
 | 
			
		||||
   int offset = 0;
 | 
			
		||||
+  grub_uint64_t stack_set_attrs = GRUB_MEM_ATTR_R |
 | 
			
		||||
+				  GRUB_MEM_ATTR_W |
 | 
			
		||||
+				  GRUB_MEM_ATTR_X;
 | 
			
		||||
+  grub_uint64_t stack_clear_attrs = 0;
 | 
			
		||||
+  grub_uint64_t kernel_set_attrs = stack_set_attrs;
 | 
			
		||||
+  grub_uint64_t kernel_clear_attrs = stack_clear_attrs;
 | 
			
		||||
+  grub_uint64_t attrs;
 | 
			
		||||
+  int nx_required = 0;
 | 
			
		||||
 
 | 
			
		||||
 #ifdef __x86_64__
 | 
			
		||||
   offset = 512;
 | 
			
		||||
@@ -48,12 +159,57 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
 | 
			
		||||
    */
 | 
			
		||||
   loaded_image = grub_efi_get_loaded_image (grub_efi_image_handle);
 | 
			
		||||
   if (loaded_image)
 | 
			
		||||
-    loaded_image->image_base = kernel_addr;
 | 
			
		||||
+    loaded_image->image_base = (void *)kernel_addr;
 | 
			
		||||
   else
 | 
			
		||||
     grub_dprintf ("linux", "Loaded Image base address could not be set\n");
 | 
			
		||||
 
 | 
			
		||||
   grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
 | 
			
		||||
-		kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
 | 
			
		||||
+		(void *)kernel_addr, (void *)handover_offset, kernel_params);
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+  if (nx_required && !nx_supported)
 | 
			
		||||
+    return grub_error (GRUB_ERR_BAD_OS, N_("kernel does not support NX loading required by policy"));
 | 
			
		||||
+
 | 
			
		||||
+  if (nx_supported)
 | 
			
		||||
+    {
 | 
			
		||||
+      kernel_set_attrs &= ~GRUB_MEM_ATTR_W;
 | 
			
		||||
+      kernel_clear_attrs |= GRUB_MEM_ATTR_W;
 | 
			
		||||
+      stack_set_attrs &= ~GRUB_MEM_ATTR_X;
 | 
			
		||||
+      stack_clear_attrs |= GRUB_MEM_ATTR_X;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+  grub_dprintf ("nx", "Setting attributes for 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to r%cx\n",
 | 
			
		||||
+		    kernel_addr, kernel_addr + kernel_size - 1,
 | 
			
		||||
+		    (kernel_set_attrs & GRUB_MEM_ATTR_W) ? 'w' : '-');
 | 
			
		||||
+  grub_update_mem_attrs (kernel_addr, kernel_size,
 | 
			
		||||
+			 kernel_set_attrs, kernel_clear_attrs);
 | 
			
		||||
+
 | 
			
		||||
+  grub_get_mem_attrs (kernel_addr, 4096, &attrs);
 | 
			
		||||
+  grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n",
 | 
			
		||||
+		(grub_addr_t)kernel_addr,
 | 
			
		||||
+		(attrs & GRUB_MEM_ATTR_R) ? "r" : "-",
 | 
			
		||||
+		(attrs & GRUB_MEM_ATTR_W) ? "w" : "-",
 | 
			
		||||
+		(attrs & GRUB_MEM_ATTR_X) ? "x" : "-");
 | 
			
		||||
+  if (grub_stack_addr != (grub_addr_t)-1ll)
 | 
			
		||||
+    {
 | 
			
		||||
+      grub_dprintf ("nx", "Setting attributes for stack at 0x%"PRIxGRUB_ADDR"-0x%"PRIxGRUB_ADDR" to rw%c\n",
 | 
			
		||||
+		    grub_stack_addr, grub_stack_addr + grub_stack_size - 1,
 | 
			
		||||
+		    (stack_set_attrs & GRUB_MEM_ATTR_X) ? 'x' : '-');
 | 
			
		||||
+      grub_update_mem_attrs (grub_stack_addr, grub_stack_size,
 | 
			
		||||
+			     stack_set_attrs, stack_clear_attrs);
 | 
			
		||||
+
 | 
			
		||||
+      grub_get_mem_attrs (grub_stack_addr, 4096, &attrs);
 | 
			
		||||
+      grub_dprintf ("nx", "permissions for 0x%"PRIxGRUB_ADDR" are %s%s%s\n",
 | 
			
		||||
+		    grub_stack_addr,
 | 
			
		||||
+		    (attrs & GRUB_MEM_ATTR_R) ? "r" : "-",
 | 
			
		||||
+		    (attrs & GRUB_MEM_ATTR_W) ? "w" : "-",
 | 
			
		||||
+		    (attrs & GRUB_MEM_ATTR_X) ? "x" : "-");
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
+#if defined(__i386__) || defined(__x86_64__)
 | 
			
		||||
+  asm volatile ("cli");
 | 
			
		||||
+#endif
 | 
			
		||||
+
 | 
			
		||||
   hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
 | 
			
		||||
   hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
 | 
			
		||||
 
 | 
			
		||||
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
index 92b2fb5091..91ae274299 100644
 | 
			
		||||
--- a/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
+++ b/grub-core/loader/i386/efi/linux.c
 | 
			
		||||
@@ -44,7 +44,7 @@ struct grub_linuxefi_context {
 | 
			
		||||
   grub_uint32_t handover_offset;
 | 
			
		||||
   struct linux_kernel_params *params;
 | 
			
		||||
   char *cmdline;
 | 
			
		||||
-
 | 
			
		||||
+  int nx_supported;
 | 
			
		||||
   void *initrd_mem;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -110,13 +110,19 @@ kernel_alloc(grub_efi_uintn_t size,
 | 
			
		||||
       pages = BYTES_TO_PAGES(size);
 | 
			
		||||
       grub_dprintf ("linux", "Trying to allocate %lu pages from %p\n",
 | 
			
		||||
 		    (unsigned long)pages, (void *)(unsigned long)max);
 | 
			
		||||
+      size = pages * GRUB_EFI_PAGE_SIZE;
 | 
			
		||||
 
 | 
			
		||||
       prev_max = max;
 | 
			
		||||
       addr = grub_efi_allocate_pages_real (max, pages,
 | 
			
		||||
 					   max_addresses[i].alloc_type,
 | 
			
		||||
 					   memtype);
 | 
			
		||||
       if (addr)
 | 
			
		||||
-	grub_dprintf ("linux", "Allocated at %p\n", addr);
 | 
			
		||||
+	{
 | 
			
		||||
+	  grub_dprintf ("linux", "Allocated at %p\n", addr);
 | 
			
		||||
+	  grub_update_mem_attrs ((grub_addr_t)addr, size,
 | 
			
		||||
+				 GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W,
 | 
			
		||||
+				 GRUB_MEM_ATTR_X);
 | 
			
		||||
+	}
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
   while (grub_error_pop ())
 | 
			
		||||
@@ -137,9 +143,11 @@ grub_linuxefi_boot (void *data)
 | 
			
		||||
 
 | 
			
		||||
   asm volatile ("cli");
 | 
			
		||||
 
 | 
			
		||||
-  return grub_efi_linux_boot ((char *)context->kernel_mem,
 | 
			
		||||
+  return grub_efi_linux_boot ((grub_addr_t)context->kernel_mem,
 | 
			
		||||
+			      context->kernel_size,
 | 
			
		||||
 			      context->handover_offset,
 | 
			
		||||
-			      context->params);
 | 
			
		||||
+			      context->params,
 | 
			
		||||
+			      context->nx_supported);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static grub_err_t
 | 
			
		||||
@@ -304,7 +312,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   grub_uint32_t handover_offset;
 | 
			
		||||
   struct linux_kernel_params *params = 0;
 | 
			
		||||
   char *cmdline = 0;
 | 
			
		||||
+  int nx_supported = 1;
 | 
			
		||||
   struct grub_linuxefi_context *context = 0;
 | 
			
		||||
+  grub_err_t err;
 | 
			
		||||
 
 | 
			
		||||
   grub_dl_ref (my_mod);
 | 
			
		||||
 
 | 
			
		||||
@@ -334,6 +344,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
       goto fail;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+  err = grub_efi_check_nx_image_support ((grub_addr_t)kernel, filelen,
 | 
			
		||||
+					 &nx_supported);
 | 
			
		||||
+  if (err != GRUB_ERR_NONE)
 | 
			
		||||
+    return err;
 | 
			
		||||
+  grub_dprintf ("linux", "nx is%s supported by this kernel\n",
 | 
			
		||||
+		nx_supported ? "" : " not");
 | 
			
		||||
+
 | 
			
		||||
   lh = (struct linux_i386_kernel_header *)kernel;
 | 
			
		||||
   grub_dprintf ("linux", "original lh is at %p\n", kernel);
 | 
			
		||||
 
 | 
			
		||||
@@ -498,6 +515,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
   context->handover_offset = handover_offset;
 | 
			
		||||
   context->params = params;
 | 
			
		||||
   context->cmdline = cmdline;
 | 
			
		||||
+  context->nx_supported = nx_supported;
 | 
			
		||||
 
 | 
			
		||||
   grub_loader_set_ex (grub_linuxefi_boot, grub_linuxefi_unload, context, 0);
 | 
			
		||||
 
 | 
			
		||||
diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c
 | 
			
		||||
index 4aeb0e4b9a..3c1ff64763 100644
 | 
			
		||||
--- a/grub-core/loader/i386/linux.c
 | 
			
		||||
+++ b/grub-core/loader/i386/linux.c
 | 
			
		||||
@@ -805,6 +805,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 | 
			
		||||
       kernel_offset += len;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
+  grub_dprintf("efi", "setting attributes for %p (%zu bytes) to +rw-x\n",
 | 
			
		||||
+	       &linux_params, sizeof (lh) + len);
 | 
			
		||||
+  grub_update_mem_attrs ((grub_addr_t)&linux_params, sizeof (lh) + len,
 | 
			
		||||
+			 GRUB_MEM_ATTR_R|GRUB_MEM_ATTR_W, GRUB_MEM_ATTR_X);
 | 
			
		||||
+
 | 
			
		||||
   linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
 | 
			
		||||
   linux_params.kernel_alignment = (1 << align);
 | 
			
		||||
   linux_params.ps_mouse = linux_params.padding11 = 0;
 | 
			
		||||
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
 | 
			
		||||
index 34825c4adc..449e55269f 100644
 | 
			
		||||
--- a/include/grub/efi/efi.h
 | 
			
		||||
+++ b/include/grub/efi/efi.h
 | 
			
		||||
@@ -140,12 +140,16 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd,
 | 
			
		||||
 						char **device,
 | 
			
		||||
 						char **path);
 | 
			
		||||
 
 | 
			
		||||
+extern grub_addr_t EXPORT_VAR(grub_stack_addr);
 | 
			
		||||
+extern grub_size_t EXPORT_VAR(grub_stack_size);
 | 
			
		||||
+
 | 
			
		||||
 #if defined(__arm__) || defined(__aarch64__) || defined(__riscv)
 | 
			
		||||
 void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void);
 | 
			
		||||
 grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *);
 | 
			
		||||
 #include <grub/cpu/linux.h>
 | 
			
		||||
 grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_header *lh);
 | 
			
		||||
-grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, char *args);
 | 
			
		||||
+grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
 | 
			
		||||
+					  char *args, int nx_enabled);
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 grub_addr_t grub_efi_section_addr (const char *section);
 | 
			
		||||
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
 | 
			
		||||
index 887b02fd9f..b82f71006a 100644
 | 
			
		||||
--- a/include/grub/efi/linux.h
 | 
			
		||||
+++ b/include/grub/efi/linux.h
 | 
			
		||||
@@ -22,8 +22,20 @@
 | 
			
		||||
 #include <grub/err.h>
 | 
			
		||||
 #include <grub/symbol.h>
 | 
			
		||||
 
 | 
			
		||||
+#define GRUB_MOK_POLICY_NX_REQUIRED   0x1
 | 
			
		||||
+
 | 
			
		||||
 grub_err_t
 | 
			
		||||
-EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,
 | 
			
		||||
-				  void *kernel_param);
 | 
			
		||||
+EXPORT_FUNC(grub_efi_linux_boot) (grub_addr_t kernel_address,
 | 
			
		||||
+				  grub_size_t kernel_size,
 | 
			
		||||
+				  grub_off_t handover_offset,
 | 
			
		||||
+				  void *kernel_param, int nx_enabled);
 | 
			
		||||
+
 | 
			
		||||
+grub_err_t
 | 
			
		||||
+EXPORT_FUNC(grub_efi_check_nx_image_support) (grub_addr_t kernel_addr,
 | 
			
		||||
+					      grub_size_t kernel_size,
 | 
			
		||||
+					      int *nx_supported);
 | 
			
		||||
+
 | 
			
		||||
+grub_err_t
 | 
			
		||||
+EXPORT_FUNC(grub_efi_check_nx_required) (int *nx_required);
 | 
			
		||||
 
 | 
			
		||||
 #endif /* ! GRUB_EFI_LINUX_HEADER */
 | 
			
		||||
diff --git a/include/grub/efi/pe32.h b/include/grub/efi/pe32.h
 | 
			
		||||
index 2a5e1ee003..a5e623eb04 100644
 | 
			
		||||
--- a/include/grub/efi/pe32.h
 | 
			
		||||
+++ b/include/grub/efi/pe32.h
 | 
			
		||||
@@ -181,6 +181,8 @@ struct grub_pe32_optional_header
 | 
			
		||||
   struct grub_pe32_data_directory reserved_entry;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+#define GRUB_PE32_NX_COMPAT 0x0100
 | 
			
		||||
+
 | 
			
		||||
 struct grub_pe64_optional_header
 | 
			
		||||
 {
 | 
			
		||||
   grub_uint16_t magic;
 | 
			
		||||
							
								
								
									
										34
									
								
								0266-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								0266-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Peter Jones <pjones@redhat.com>
 | 
			
		||||
Date: Tue, 22 Mar 2022 10:57:20 -0400
 | 
			
		||||
Subject: [PATCH] nx: set the nx compatible flag in EFI grub images
 | 
			
		||||
 | 
			
		||||
For NX, we need the grub binary to announce that it is compatible with
 | 
			
		||||
the NX feature.  This implies that when loading the executable grub
 | 
			
		||||
image, several attributes are true:
 | 
			
		||||
 | 
			
		||||
- the binary doesn't need an executable stack
 | 
			
		||||
- the binary doesn't need sections to be both executable and writable
 | 
			
		||||
- the binary knows how to use the EFI Memory Attributes protocol on code
 | 
			
		||||
  it is loading.
 | 
			
		||||
 | 
			
		||||
This patch adds a definition for the PE DLL Characteristics flag
 | 
			
		||||
GRUB_PE32_NX_COMPAT, and changes grub-mkimage to set that flag.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Peter Jones <pjones@redhat.com>
 | 
			
		||||
---
 | 
			
		||||
 util/mkimage.c | 1 +
 | 
			
		||||
 1 file changed, 1 insertion(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/util/mkimage.c b/util/mkimage.c
 | 
			
		||||
index 8319e8dfbd..c3d33aaac8 100644
 | 
			
		||||
--- a/util/mkimage.c
 | 
			
		||||
+++ b/util/mkimage.c
 | 
			
		||||
@@ -1418,6 +1418,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 | 
			
		||||
 	    section = (struct grub_pe32_section_table *)(o64 + 1);
 | 
			
		||||
 	  }
 | 
			
		||||
 
 | 
			
		||||
+	PE_OHDR (o32, o64, dll_characteristics) = grub_host_to_target16 (GRUB_PE32_NX_COMPAT);
 | 
			
		||||
 	PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
 | 
			
		||||
 	PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address);
 | 
			
		||||
 	PE_OHDR (o32, o64, image_base) = 0;
 | 
			
		||||
							
								
								
									
										47
									
								
								grub.patches
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								grub.patches
									
									
									
									
									
								
							@ -217,3 +217,50 @@ Patch0216: 0216-powerpc-prefix-detection-support-device-names-with-c.patch
 | 
			
		||||
Patch0217: 0217-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch
 | 
			
		||||
Patch0218: 0218-rpm-sort-add-prereqs-for-declaration-of-strchrnul.patch
 | 
			
		||||
Patch0219: 0219-make-ofdisk_retries-optional.patch
 | 
			
		||||
Patch0220: 0220-loader-efi-chainloader-grub_load_and_start_image-doe.patch
 | 
			
		||||
Patch0221: 0221-loader-efi-chainloader-simplify-the-loader-state.patch
 | 
			
		||||
Patch0222: 0222-commands-boot-Add-API-to-pass-context-to-loader.patch
 | 
			
		||||
Patch0223: 0223-loader-efi-chainloader-Use-grub_loader_set_ex.patch
 | 
			
		||||
Patch0224: 0224-loader-i386-efi-linux-Avoid-a-use-after-free-in-the-.patch
 | 
			
		||||
Patch0225: 0225-loader-i386-efi-linux-Use-grub_loader_set_ex.patch
 | 
			
		||||
Patch0226: 0226-loader-i386-efi-linux-Fix-a-memory-leak-in-the-initr.patch
 | 
			
		||||
Patch0227: 0227-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
 | 
			
		||||
Patch0228: 0228-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
 | 
			
		||||
Patch0229: 0229-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
 | 
			
		||||
Patch0230: 0230-video-readers-png-Refuse-to-handle-multiple-image-he.patch
 | 
			
		||||
Patch0231: 0231-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
 | 
			
		||||
Patch0232: 0232-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
 | 
			
		||||
Patch0233: 0233-video-readers-png-Sanity-check-some-huffman-codes.patch
 | 
			
		||||
Patch0234: 0234-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
 | 
			
		||||
Patch0235: 0235-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
 | 
			
		||||
Patch0236: 0236-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
 | 
			
		||||
Patch0237: 0237-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
 | 
			
		||||
Patch0238: 0238-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
 | 
			
		||||
Patch0239: 0239-net-netbuff-Block-overly-large-netbuff-allocs.patch
 | 
			
		||||
Patch0240: 0240-net-ip-Do-IP-fragment-maths-safely.patch
 | 
			
		||||
Patch0241: 0241-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
 | 
			
		||||
Patch0242: 0242-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
 | 
			
		||||
Patch0243: 0243-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
 | 
			
		||||
Patch0244: 0244-net-tftp-Avoid-a-trivial-UAF.patch
 | 
			
		||||
Patch0245: 0245-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
 | 
			
		||||
Patch0246: 0246-net-http-Fix-OOB-write-for-split-http-headers.patch
 | 
			
		||||
Patch0247: 0247-net-http-Error-out-on-headers-with-LF-without-CR.patch
 | 
			
		||||
Patch0248: 0248-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
 | 
			
		||||
Patch0249: 0249-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
 | 
			
		||||
Patch0250: 0250-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
 | 
			
		||||
Patch0251: 0251-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
 | 
			
		||||
Patch0252: 0252-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
 | 
			
		||||
Patch0253: 0253-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
 | 
			
		||||
Patch0254: 0254-misc-Make-grub_min-and-grub_max-more-resilient.patch
 | 
			
		||||
Patch0255: 0255-ReiserFS-switch-to-using-grub_min-grub_max.patch
 | 
			
		||||
Patch0256: 0256-misc-make-grub_boot_time-also-call-grub_dprintf-boot.patch
 | 
			
		||||
Patch0257: 0257-modules-make-.module_license-read-only.patch
 | 
			
		||||
Patch0258: 0258-modules-strip-.llvm_addrsig-sections-and-similar.patch
 | 
			
		||||
Patch0259: 0259-modules-Don-t-allocate-space-for-non-allocable-secti.patch
 | 
			
		||||
Patch0260: 0260-pe-add-the-DOS-header-struct-and-fix-some-bad-naming.patch
 | 
			
		||||
Patch0261: 0261-EFI-allocate-kernel-in-EFI_RUNTIME_SERVICES_CODE-ins.patch
 | 
			
		||||
Patch0262: 0262-modules-load-module-sections-at-page-aligned-address.patch
 | 
			
		||||
Patch0263: 0263-nx-add-memory-attribute-get-set-API.patch
 | 
			
		||||
Patch0264: 0264-nx-set-page-permissions-for-loaded-modules.patch
 | 
			
		||||
Patch0265: 0265-nx-set-attrs-in-our-kernel-loaders.patch
 | 
			
		||||
Patch0266: 0266-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@
 | 
			
		||||
Name:		grub2
 | 
			
		||||
Epoch:		1
 | 
			
		||||
Version:	2.06
 | 
			
		||||
Release:	41%{?dist}
 | 
			
		||||
Release:	42%{?dist}
 | 
			
		||||
Summary:	Bootloader with support for Linux, Multiboot and more
 | 
			
		||||
License:	GPLv3+
 | 
			
		||||
URL:		http://www.gnu.org/software/grub/
 | 
			
		||||
@ -530,6 +530,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%changelog
 | 
			
		||||
* Mon May 16 2022 Robbie Harwood <rharwood@redhat.com> 1:2.06-42
 | 
			
		||||
- CVE fixes for 2022-05-24
 | 
			
		||||
- Resolves: CVE-2022-28736 CVE-2022-28735 CVE-2022-28734 CVE-2022-28733
 | 
			
		||||
- Resolves: CVE-2021-3697 CVE-2021-3696 CVE-2021-3695
 | 
			
		||||
 | 
			
		||||
* Mon May 16 2022 Robbie Harwood <rharwood@redhat.com> - 1:2.06-41
 | 
			
		||||
- ppc64le: make ofdisk retries optional
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,3 @@
 | 
			
		||||
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
 | 
			
		||||
grub,1,Free Software Foundation,grub,@@VERSION@@,https//www.gnu.org/software/grub/
 | 
			
		||||
grub.fedora,1,The Fedora Project,grub2,@@VERSION_RELEASE@@,https://src.fedoraproject.org/rpms/grub2
 | 
			
		||||
grub,2,Free Software Foundation,grub,@@VERSION@@,https//www.gnu.org/software/grub/
 | 
			
		||||
grub.rh,2,Red Hat,grub2,@@VERSION_RELEASE@@,mailto:secalert@redhat.com
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user