- Use shim loader protocol to verify images in the shim_lock verifier.
- Add API to allow downstream consumers to re-use image handles produced
  by the verifier. This is necessary to avoid having images measured
  twice to the TPM.
- Register shim loader protocol as an image loader.

Signed-off-by: Mate Kukri <mate.ku...@canonical.com>
---
 grub-core/kern/efi/sb.c            | 45 ++++++++++++++++--------------
 grub-core/loader/efi/chainloader.c | 21 ++++++++------
 grub-core/loader/efi/linux.c       | 30 ++++++--------------
 include/grub/efi/api.h             |  5 ++++
 include/grub/efi/efi.h             | 19 ++++++++-----
 include/grub/efi/sb.h              |  5 ++--
 6 files changed, 66 insertions(+), 59 deletions(-)

diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 8d3e41360..fcc71e4e8 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -31,8 +31,11 @@
 #include <grub/verify.h>
 
 static grub_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
+static grub_guid_t shim_loader_guid = GRUB_EFI_SHIM_IMAGE_LOADER_GUID;
 
-static bool shim_lock_enabled = false;
+static grub_efi_loader_t *shim_loader = NULL;
+
+static grub_efi_handle_t last_verified_image_handle;
 
 /*
  * Determine whether we're in secure boot mode.
@@ -95,14 +98,6 @@ grub_efi_get_secureboot (void)
   if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1)
     {
       secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
-      /*
-       * TODO: Replace this all with shim's LoadImage protocol, delegating 
policy to it.
-       *
-       * We need to set shim_lock_enabled here because we disabled secure boot
-       * validation *inside* shim but not in the firmware, so we set this 
variable
-       * here to trigger that code path, whereas the actual verifier is not 
enabled.
-       */
-      shim_lock_enabled = true;
       goto out;
     }
 
@@ -183,14 +178,18 @@ shim_lock_verifier_init (grub_file_t io __attribute__ 
((unused)),
 static grub_err_t
 shim_lock_verifier_write (void *context __attribute__ ((unused)), void *buf, 
grub_size_t size)
 {
-  grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol 
(&shim_lock_guid, 0);
+  grub_efi_handle_t image_handle;
 
-  if (!sl)
-    return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not 
found"));
+  if (last_verified_image_handle)
+    {
+      shim_loader->unload_image (last_verified_image_handle);
+      last_verified_image_handle = NULL;
+    }
 
-  if (sl->verify (buf, size) != GRUB_EFI_SUCCESS)
+  if (shim_loader->load_image (false, grub_efi_image_handle, NULL, buf, size, 
&image_handle) != GRUB_EFI_SUCCESS)
     return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature"));
 
+  last_verified_image_handle = image_handle;
   return GRUB_ERR_NONE;
 }
 
@@ -205,11 +204,11 @@ void
 grub_shim_lock_verifier_setup (void)
 {
   struct grub_module_header *header;
-  grub_efi_shim_lock_protocol_t *sl =
-    grub_efi_locate_protocol (&shim_lock_guid, 0);
 
-  /* shim_lock is missing, check if GRUB image is built with 
--disable-shim-lock. */
-  if (!sl)
+  shim_loader = grub_efi_locate_protocol (&shim_loader_guid, 0);
+
+  /* shim is missing, check if GRUB image is built with --disable-shim-lock. */
+  if (!shim_loader)
     {
       FOR_MODULES (header)
        {
@@ -225,14 +224,18 @@ grub_shim_lock_verifier_setup (void)
   /* Enforce shim_lock_verifier. */
   grub_verifier_register (&shim_lock_verifier);
 
-  shim_lock_enabled = true;
+  /* Register shim loader if supported. */
+  grub_efi_register_loader (shim_loader);
 
   grub_env_set ("shim_lock", "y");
   grub_env_export ("shim_lock");
 }
 
-bool
-grub_is_shim_lock_enabled (void)
+
+grub_efi_handle_t
+grub_efi_get_last_verified_image_handle (void)
 {
-  return shim_lock_enabled;
+  grub_efi_handle_t tmp = last_verified_image_handle;
+  last_verified_image_handle = NULL;
+  return tmp;
 }
diff --git a/grub-core/loader/efi/chainloader.c 
b/grub-core/loader/efi/chainloader.c
index 11b64ac1b..e77bd863c 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -33,6 +33,7 @@
 #include <grub/efi/efi.h>
 #include <grub/efi/disk.h>
 #include <grub/efi/memory.h>
+#include <grub/efi/sb.h>
 #include <grub/command.h>
 #include <grub/i18n.h>
 #include <grub/net.h>
@@ -337,16 +338,20 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ 
((unused)),
     }
 #endif
 
-  status = grub_efi_load_image (0, grub_efi_image_handle, file_path,
-                               boot_image, size, &image_handle);
-  if (status != GRUB_EFI_SUCCESS)
+  image_handle = grub_efi_get_last_verified_image_handle ();
+  if (image_handle == NULL)
     {
-      if (status == GRUB_EFI_OUT_OF_RESOURCES)
-       grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
-      else
-       grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+      status = grub_efi_load_image (0, grub_efi_image_handle, file_path,
+                               boot_image, size, &image_handle);
+      if (status != GRUB_EFI_SUCCESS)
+       {
+         if (status == GRUB_EFI_OUT_OF_RESOURCES)
+           grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources");
+         else
+           grub_error (GRUB_ERR_BAD_OS, "cannot load image");
 
-      goto fail;
+         goto fail;
+       }
     }
 
   /* LoadImage does not set a device handler when the image is
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 7342f3ee7..b97b3e27b 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -206,11 +206,15 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, 
grub_size_t size, char *args)
   mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
   mempath[1].header.length = sizeof (grub_efi_device_path_t);
 
-  status = grub_efi_load_image (0, grub_efi_image_handle,
-                               (grub_efi_device_path_t *)mempath,
-                               (void *)addr, size, &image_handle);
-  if (status != GRUB_EFI_SUCCESS)
-    return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+  image_handle = grub_efi_get_last_verified_image_handle ();
+  if (image_handle == NULL)
+    {
+      status = grub_efi_load_image (0, grub_efi_image_handle,
+                                   (grub_efi_device_path_t *)mempath,
+                                   (void *)addr, size, &image_handle);
+      if (status != GRUB_EFI_SUCCESS)
+       return grub_error (GRUB_ERR_BAD_OS, "cannot load image");
+    }
 
   grub_dprintf ("linux", "linux command line: '%s'\n", args);
 
@@ -461,22 +465,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ 
((unused)),
 
   grub_dl_ref (my_mod);
 
-  if (grub_is_shim_lock_enabled () == true)
-    {
-#if defined(__i386__) || defined(__x86_64__)
-      grub_dprintf ("linux", "shim_lock enabled, falling back to legacy Linux 
kernel loader\n");
-
-      err = grub_cmd_linux_x86_legacy (cmd, argc, argv);
-
-      if (err == GRUB_ERR_NONE)
-       return GRUB_ERR_NONE;
-      else
-       goto fail;
-#else
-      grub_dprintf ("linux", "shim_lock enabled, trying Linux kernel EFI stub 
loader\n");
-#endif
-    }
-
   if (argc == 0)
     {
       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index b686e8afe..9ae908729 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -364,6 +364,11 @@
     { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
   }
 
+#define GRUB_EFI_SHIM_IMAGE_LOADER_GUID \
+  { 0x1f492041, 0xfadb, 0x4e59, \
+    {0x9e, 0x57, 0x7c, 0xaf, 0xe7, 0x3a, 0x55, 0xab } \
+  }
+
 #define GRUB_EFI_RNG_PROTOCOL_GUID \
   { 0x3152bca5, 0xeade, 0x433d, \
     { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 692a1b935..b4d2f2d46 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -150,15 +150,20 @@ EXPORT_FUNC (grub_efi_unload_image) (grub_efi_handle_t 
image_handle);
 typedef struct grub_efi_loader
 {
   grub_efi_status_t (__grub_efi_api *load_image) (grub_efi_boolean_t 
boot_policy,
-                                  grub_efi_handle_t parent_image_handle,
-                                  grub_efi_device_path_t *file_path,
-                                  void *source_buffer,
-                                  grub_efi_uintn_t source_size,
-                                  grub_efi_handle_t *image_handle);
+                                                 grub_efi_handle_t 
parent_image_handle,
+                                                 grub_efi_device_path_t 
*file_path,
+                                                 void *source_buffer,
+                                                 grub_efi_uintn_t source_size,
+                                                 grub_efi_handle_t 
*image_handle);
 
   grub_efi_status_t (__grub_efi_api *start_image) (grub_efi_handle_t 
image_handle,
-                                   grub_efi_uintn_t *exit_data_size,
-                                   grub_efi_char16_t **exit_data);
+                                                  grub_efi_uintn_t 
*exit_data_size,
+                                                  grub_efi_char16_t 
**exit_data);
+
+  grub_efi_status_t (__grub_efi_api *exit) (grub_efi_handle_t image_handle,
+                                           grub_efi_status_t exit_status,
+                                           grub_efi_uintn_t exit_data_size,
+                                           grub_efi_char16_t *exit_data);
 
   grub_efi_status_t (__grub_efi_api *unload_image) (grub_efi_handle_t 
image_handle);
 } grub_efi_loader_t;
diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
index 49a9ad01c..284e14992 100644
--- a/include/grub/efi/sb.h
+++ b/include/grub/efi/sb.h
@@ -21,6 +21,7 @@
 
 #include <grub/types.h>
 #include <grub/dl.h>
+#include <grub/efi/api.h>
 
 #define GRUB_EFI_SECUREBOOT_MODE_UNSET         0
 #define GRUB_EFI_SECUREBOOT_MODE_UNKNOWN       1
@@ -31,8 +32,8 @@
 extern grub_uint8_t
 EXPORT_FUNC (grub_efi_get_secureboot) (void);
 
-extern bool
-EXPORT_FUNC (grub_is_shim_lock_enabled) (void);
+extern grub_efi_handle_t
+EXPORT_FUNC (grub_efi_get_last_verified_image_handle) (void);
 
 extern void
 grub_shim_lock_verifier_setup (void);
-- 
2.39.2


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to