nalika / rpms / grub2

Forked from rpms/grub2 2 years ago
Clone

Blame SOURCES/0225-Rework-even-more-of-efi-chainload-so-non-sb-cases-wo.patch

f725e3
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
f725e3
From: Peter Jones <pjones@redhat.com>
f725e3
Date: Fri, 10 Jun 2016 14:06:15 -0400
f725e3
Subject: [PATCH] Rework even more of efi chainload so non-sb cases work right.
f725e3
f725e3
This ensures that if shim protocol is not loaded, or is loaded but shim
f725e3
is disabled, we will fall back to a correct load method for the efi
f725e3
chain loader.
f725e3
f725e3
Here's what I tested with this version:
f725e3
f725e3
results                             expected    actual
f725e3
------------------------------------------------------------
f725e3
sb + enabled + shim + fedora        success     success
f725e3
sb + enabled + shim + win           success     success
f725e3
sb + enabled + grub + fedora        fail        fail
f725e3
sb + enabled + grub + win           fail        fail
f725e3
f725e3
sb + mokdisabled + shim + fedora    success     success
f725e3
sb + mokdisabled + shim + win       success     success
f725e3
sb + mokdisabled + grub + fedora    fail        fail
f725e3
sb + mokdisabled + grub + win       fail        fail
f725e3
f725e3
sb disabled + shim + fedora         success     success*
f725e3
sb disabled + shim + win            success     success*
f725e3
sb disabled + grub + fedora         success     success
f725e3
sb disabled + grub + win            success     success
f725e3
f725e3
nosb + shim + fedora                success     success*
f725e3
nosb + shim + win                   success     success*
f725e3
nosb + grub + fedora                success     success
f725e3
nosb + grub + win                   success     success
f725e3
f725e3
* for some reason shim protocol is being installed in these cases, and I
f725e3
  can't see why, but I think it may be this firmware build returning an
f725e3
  erroneous value.  But this effectively falls back to the mokdisabled
f725e3
  behavior, which works correctly, and the presence of the "grub" (i.e.
f725e3
  no shim) tests effectively tests the desired behavior here.
f725e3
f725e3
Resolves: rhbz#1344512
f725e3
f725e3
Signed-off-by: Peter Jones <pjones@redhat.com>
f725e3
---
f725e3
 grub-core/kern/efi/sb.c            |  14 +++--
f725e3
 grub-core/loader/arm64/linux.c     |   4 +-
f725e3
 grub-core/loader/efi/chainloader.c | 117 ++++++++++++++++++++++---------------
f725e3
 grub-core/loader/efi/linux.c       |  13 +++--
f725e3
 grub-core/loader/i386/efi/linux.c  |  10 +++-
f725e3
 include/grub/efi/linux.h           |   2 +-
f725e3
 6 files changed, 100 insertions(+), 60 deletions(-)
f725e3
f725e3
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
f725e3
index a41b6c5b851..d74778b0cac 100644
f725e3
--- a/grub-core/kern/efi/sb.c
f725e3
+++ b/grub-core/kern/efi/sb.c
f725e3
@@ -36,14 +36,20 @@ grub_efi_secure_boot (void)
f725e3
   grub_efi_boolean_t ret = 0;
f725e3
 
f725e3
   secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
f725e3
-
f725e3
   if (datasize != 1 || !secure_boot)
f725e3
-    goto out;
f725e3
+    {
f725e3
+      grub_dprintf ("secureboot", "No SecureBoot variable\n");
f725e3
+      goto out;
f725e3
+    }
f725e3
+  grub_dprintf ("secureboot", "SecureBoot: %d\n", *secure_boot);
f725e3
 
f725e3
   setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
f725e3
-
f725e3
   if (datasize != 1 || !setup_mode)
f725e3
-    goto out;
f725e3
+    {
f725e3
+      grub_dprintf ("secureboot", "No SetupMode variable\n");
f725e3
+      goto out;
f725e3
+    }
f725e3
+  grub_dprintf ("secureboot", "SetupMode: %d\n", *setup_mode);
f725e3
 
f725e3
   if (*secure_boot && !*setup_mode)
f725e3
     ret = 1;
f725e3
diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
f725e3
index bdd9c9b4968..0452a20e98b 100644
f725e3
--- a/grub-core/loader/arm64/linux.c
f725e3
+++ b/grub-core/loader/arm64/linux.c
f725e3
@@ -380,6 +380,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
f725e3
   grub_file_t file = 0;
f725e3
   struct grub_arm64_linux_kernel_header lh;
f725e3
   struct grub_arm64_linux_pe_header *pe;
f725e3
+  int rc;
f725e3
 
f725e3
   grub_dl_ref (my_mod);
f725e3
 
f725e3
@@ -424,7 +425,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
f725e3
 
f725e3
   grub_dprintf ("linux", "kernel @ %p\n", kernel_addr);
f725e3
 
f725e3
-  if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size))
f725e3
+  rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size);
f725e3
+  if (rc < 0)
f725e3
     {
f725e3
       grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
f725e3
       goto fail;
f725e3
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
f725e3
index 4b77a7d5adb..3e89de9006c 100644
f725e3
--- a/grub-core/loader/efi/chainloader.c
f725e3
+++ b/grub-core/loader/efi/chainloader.c
f725e3
@@ -182,7 +182,6 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
f725e3
   /* Fill the file path for the directory.  */
f725e3
   d = (grub_efi_device_path_t *) ((char *) file_path
f725e3
 				  + ((char *) d - (char *) dp));
f725e3
-  grub_efi_print_device_path (d);
f725e3
   copy_file_path ((grub_efi_file_path_device_path_t *) d,
f725e3
 		  dir_start, dir_end - dir_start);
f725e3
 
f725e3
@@ -252,10 +251,9 @@ read_header (void *data, grub_efi_uint32_t size,
f725e3
   grub_efi_status_t status;
f725e3
 
f725e3
   shim_lock = grub_efi_locate_protocol (&guid, NULL);
f725e3
-
f725e3
   if (!shim_lock)
f725e3
     {
f725e3
-      grub_error (GRUB_ERR_BAD_ARGUMENT, "no shim lock protocol");
f725e3
+      grub_dprintf ("chain", "no shim lock protocol");
f725e3
       return 0;
f725e3
     }
f725e3
 
f725e3
@@ -280,7 +278,7 @@ read_header (void *data, grub_efi_uint32_t size,
f725e3
       break;
f725e3
     }
f725e3
 
f725e3
-  return 0;
f725e3
+  return -1;
f725e3
 }
f725e3
 
f725e3
 static void*
f725e3
@@ -514,18 +512,25 @@ handle_image (void *data, grub_efi_uint32_t datasize)
f725e3
   grub_uint32_t section_alignment;
f725e3
   grub_uint32_t buffer_size;
f725e3
   int found_entry_point = 0;
f725e3
+  int rc;
f725e3
 
f725e3
   b = grub_efi_system_table->boot_services;
f725e3
 
f725e3
-  if (read_header (data, datasize, &context))
f725e3
-    {
f725e3
-      grub_dprintf ("chain", "Succeed to read header\n");
f725e3
-    }
f725e3
-  else
f725e3
+  rc = read_header (data, datasize, &context);
f725e3
+  if (rc < 0)
f725e3
     {
f725e3
       grub_dprintf ("chain", "Failed to read header\n");
f725e3
       goto error_exit;
f725e3
     }
f725e3
+  else if (rc == 0)
f725e3
+    {
f725e3
+      grub_dprintf ("chain", "Secure Boot is not enabled\n");
f725e3
+      return 0;
f725e3
+    }
f725e3
+  else
f725e3
+    {
f725e3
+      grub_dprintf ("chain", "Header read without error\n");
f725e3
+    }
f725e3
 
f725e3
   /*
f725e3
    * The spec says, uselessly, of SectionAlignment:
f725e3
@@ -796,10 +801,56 @@ grub_secureboot_chainloader_unload (void)
f725e3
   return GRUB_ERR_NONE;
f725e3
 }
f725e3
 
f725e3
+static grub_err_t
f725e3
+grub_load_and_start_image(void *boot_image)
f725e3
+{
f725e3
+  grub_efi_boot_services_t *b;
f725e3
+  grub_efi_status_t status;
f725e3
+  grub_efi_loaded_image_t *loaded_image;
f725e3
+
f725e3
+  b = grub_efi_system_table->boot_services;
f725e3
+
f725e3
+  status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
f725e3
+		       boot_image, fsize, &image_handle);
f725e3
+  if (status != GRUB_EFI_SUCCESS)
f725e3
+    {
f725e3
+      if (status == GRUB_EFI_OUT_OF_RESOURCES)
f725e3
+	grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
f725e3
+      else
f725e3
+	grub_error (GRUB_ERR_BAD_OS, "cannot load image");
f725e3
+      return -1;
f725e3
+    }
f725e3
+
f725e3
+  /* LoadImage does not set a device handler when the image is
f725e3
+     loaded from memory, so it is necessary to set it explicitly here.
f725e3
+     This is a mess.  */
f725e3
+  loaded_image = grub_efi_get_loaded_image (image_handle);
f725e3
+  if (! loaded_image)
f725e3
+    {
f725e3
+      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
f725e3
+      return -1;
f725e3
+    }
f725e3
+  loaded_image->device_handle = dev_handle;
f725e3
+
f725e3
+  if (cmdline)
f725e3
+    {
f725e3
+      loaded_image->load_options = cmdline;
f725e3
+      loaded_image->load_options_size = cmdline_len;
f725e3
+    }
f725e3
+
f725e3
+  return 0;
f725e3
+}
f725e3
+
f725e3
 static grub_err_t
f725e3
 grub_secureboot_chainloader_boot (void)
f725e3
 {
f725e3
-  handle_image ((void *)address, fsize);
f725e3
+  int rc;
f725e3
+  rc = handle_image ((void *)address, fsize);
f725e3
+  if (rc == 0)
f725e3
+    {
f725e3
+      grub_load_and_start_image((void *)address);
f725e3
+    }
f725e3
+
f725e3
   grub_loader_unset ();
f725e3
   return grub_errno;
f725e3
 }
f725e3
@@ -813,9 +864,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
f725e3
   grub_efi_boot_services_t *b;
f725e3
   grub_device_t dev = 0;
f725e3
   grub_efi_device_path_t *dp = 0;
f725e3
-  grub_efi_loaded_image_t *loaded_image;
f725e3
   char *filename;
f725e3
   void *boot_image = 0;
f725e3
+  int rc;
f725e3
 
f725e3
   if (argc == 0)
f725e3
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
f725e3
@@ -902,9 +953,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
f725e3
   if (! file_path)
f725e3
     goto fail;
f725e3
 
f725e3
-  grub_printf ("file path: ");
f725e3
-  grub_efi_print_device_path (file_path);
f725e3
-
f725e3
   fsize = grub_file_size (file);
f725e3
   if (!fsize)
f725e3
     {
f725e3
@@ -979,51 +1027,28 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
f725e3
     }
f725e3
 #endif
f725e3
 
f725e3
-  if (grub_linuxefi_secure_validate((void *)address, fsize))
f725e3
+  rc = grub_linuxefi_secure_validate((void *)address, fsize);
f725e3
+  grub_dprintf ("chain", "linuxefi_secure_validate: %d\n", rc);
f725e3
+  if (rc > 0)
f725e3
     {
f725e3
       grub_file_close (file);
f725e3
       grub_loader_set (grub_secureboot_chainloader_boot,
f725e3
 		       grub_secureboot_chainloader_unload, 0);
f725e3
       return 0;
f725e3
     }
f725e3
-
f725e3
-  status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
f725e3
-		       boot_image, fsize, &image_handle);
f725e3
-  if (status != GRUB_EFI_SUCCESS)
f725e3
+  else if (rc == 0)
f725e3
     {
f725e3
-      if (status == GRUB_EFI_OUT_OF_RESOURCES)
f725e3
-	grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
f725e3
-      else
f725e3
-	grub_error (GRUB_ERR_BAD_OS, "cannot load image");
f725e3
-
f725e3
-      goto fail;
f725e3
-    }
f725e3
+      grub_load_and_start_image(boot_image);
f725e3
+      grub_file_close (file);
f725e3
+      grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
f725e3
 
f725e3
-  /* LoadImage does not set a device handler when the image is
f725e3
-     loaded from memory, so it is necessary to set it explicitly here.
f725e3
-     This is a mess.  */
f725e3
-  loaded_image = grub_efi_get_loaded_image (image_handle);
f725e3
-  if (! loaded_image)
f725e3
-    {
f725e3
-      grub_error (GRUB_ERR_BAD_OS, "no loaded image available");
f725e3
-      goto fail;
f725e3
-    }
f725e3
-  loaded_image->device_handle = dev_handle;
f725e3
-
f725e3
-  if (cmdline)
f725e3
-    {
f725e3
-      loaded_image->load_options = cmdline;
f725e3
-      loaded_image->load_options_size = cmdline_len;
f725e3
+      return 0;
f725e3
     }
f725e3
 
f725e3
   grub_file_close (file);
f725e3
   grub_device_close (dev);
f725e3
 
f725e3
-  grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
f725e3
-  return 0;
f725e3
-
f725e3
- fail:
f725e3
-
f725e3
+fail:
f725e3
   if (dev)
f725e3
     grub_device_close (dev);
f725e3
 
f725e3
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
f725e3
index aea378adf5c..8890bdf059a 100644
f725e3
--- a/grub-core/loader/efi/linux.c
f725e3
+++ b/grub-core/loader/efi/linux.c
f725e3
@@ -33,21 +33,24 @@ struct grub_efi_shim_lock
f725e3
 };
f725e3
 typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
f725e3
 
f725e3
-grub_efi_boolean_t
f725e3
+int
f725e3
 grub_linuxefi_secure_validate (void *data, grub_uint32_t size)
f725e3
 {
f725e3
   grub_efi_guid_t guid = SHIM_LOCK_GUID;
f725e3
   grub_efi_shim_lock_t *shim_lock;
f725e3
+  grub_efi_status_t status;
f725e3
 
f725e3
   shim_lock = grub_efi_locate_protocol(&guid, NULL);
f725e3
-
f725e3
+  grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock);
f725e3
   if (!shim_lock)
f725e3
-    return 1;
f725e3
+    return 0;
f725e3
 
f725e3
-  if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
f725e3
+  status = shim_lock->verify(data, size);
f725e3
+  grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", status);
f725e3
+  if (status == GRUB_EFI_SUCCESS)
f725e3
     return 1;
f725e3
 
f725e3
-  return 0;
f725e3
+  return -1;
f725e3
 }
f725e3
 
f725e3
 typedef void (*handover_func) (void *, grub_efi_system_table_t *, void *);
f725e3
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
f725e3
index 7ccf32d9d45..82f75b7f3ab 100644
f725e3
--- a/grub-core/loader/i386/efi/linux.c
f725e3
+++ b/grub-core/loader/i386/efi/linux.c
f725e3
@@ -155,6 +155,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
f725e3
   struct linux_kernel_header lh;
f725e3
   grub_ssize_t len, start, filelen;
f725e3
   void *kernel = NULL;
f725e3
+  int rc;
f725e3
 
f725e3
   grub_dl_ref (my_mod);
f725e3
 
f725e3
@@ -180,13 +181,16 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
f725e3
 
f725e3
   if (grub_file_read (file, kernel, filelen) != filelen)
f725e3
     {
f725e3
-      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"), argv[0]);
f725e3
+      grub_error (GRUB_ERR_FILE_READ_ERROR, N_("Can't read kernel %s"),
f725e3
+		  argv[0]);
f725e3
       goto fail;
f725e3
     }
f725e3
 
f725e3
-  if (! grub_linuxefi_secure_validate (kernel, filelen))
f725e3
+  rc = grub_linuxefi_secure_validate (kernel, filelen);
f725e3
+  if (rc < 0)
f725e3
     {
f725e3
-      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
f725e3
+      grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"),
f725e3
+		  argv[0]);
f725e3
       grub_free (kernel);
f725e3
       goto fail;
f725e3
     }
f725e3
diff --git a/include/grub/efi/linux.h b/include/grub/efi/linux.h
f725e3
index d9ede36773b..0033d9305a9 100644
f725e3
--- a/include/grub/efi/linux.h
f725e3
+++ b/include/grub/efi/linux.h
f725e3
@@ -22,7 +22,7 @@
f725e3
 #include <grub/err.h>
f725e3
 #include <grub/symbol.h>
f725e3
 
f725e3
-grub_efi_boolean_t
f725e3
+int
f725e3
 EXPORT_FUNC(grub_linuxefi_secure_validate) (void *data, grub_uint32_t size);
f725e3
 grub_err_t
f725e3
 EXPORT_FUNC(grub_efi_linux_boot) (void *kernel_address, grub_off_t offset,