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

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