]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
efi/sb: Add support for the shim loader protocol
authorMate Kukri <mate.kukri@canonical.com>
Tue, 8 Jul 2025 20:21:14 +0000 (21:21 +0100)
committerDaniel Kiper <daniel.kiper@oracle.com>
Fri, 11 Jul 2025 15:46:14 +0000 (17:46 +0200)
Use loader protocol for image verification where available, otherwise
fall back to the old shim lock protocol.

Signed-off-by: Mate Kukri <mate.kukri@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/kern/efi/sb.c
grub-core/loader/efi/linux.c
include/grub/efi/api.h
include/grub/efi/sb.h

index 8d3e413608bbb227a45d37b19ecfea9513271ed1..48d1ea9683d81d3b40f4bbe8e12543d64541dc5f 100644 (file)
 #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_shim_lock_protocol_t *shim_lock = NULL;
 
 /*
  * Determine whether we're in secure boot mode.
@@ -95,14 +97,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,15 +177,25 @@ 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 (shim_loader != NULL)
+    {
+      if (shim_loader->load_image (false, grub_efi_image_handle, NULL, buf, size, &image_handle) != GRUB_EFI_SUCCESS)
+       /* If verification fails no handle is produced */
+        return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim loader signature"));
 
-  if (sl->verify (buf, size) != GRUB_EFI_SUCCESS)
-    return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature"));
+      shim_loader->unload_image (image_handle);
+      return GRUB_ERR_NONE;
+    }
+  if (shim_lock != NULL)
+    {
+      if (shim_lock->verify (buf, size) != GRUB_EFI_SUCCESS)
+        return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim lock signature"));
+      return GRUB_ERR_NONE;
+    }
 
-  return GRUB_ERR_NONE;
+  return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim protocols not found"));
 }
 
 struct grub_file_verifier shim_lock_verifier =
@@ -205,11 +209,17 @@ 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)
+  /* Secure Boot is off. Ignore shim. */
+  if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+    return;
+
+  /* Find both shim protocols. */
+  shim_loader = grub_efi_locate_protocol (&shim_loader_guid, 0);
+  shim_lock = grub_efi_locate_protocol (&shim_lock_guid, 0);
+
+  /* shim is missing, check if GRUB image is built with --disable-shim-lock. */
+  if (shim_loader == NULL && shim_lock == NULL)
     {
       FOR_MODULES (header)
        {
@@ -218,21 +228,18 @@ grub_shim_lock_verifier_setup (void)
        }
     }
 
-  /* Secure Boot is off. Do not load shim_lock. */
-  if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
-    return;
-
   /* 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_is_using_legacy_shim_lock_protocol (void)
 {
-  return shim_lock_enabled;
+  return (shim_loader == NULL && shim_lock != NULL) ? true : false;
 }
index 918884ef3b6f3ec678cc7ee85228c4470a2c01f9..0ef4559aaae88872c25650e812f58041fd05f4e0 100644 (file)
@@ -464,10 +464,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
 
   grub_dl_ref (my_mod);
 
-  if (grub_is_shim_lock_enabled () == true)
+  if (grub_is_using_legacy_shim_lock_protocol () == true)
     {
 #if defined(__i386__) || defined(__x86_64__)
-      grub_dprintf ("linux", "shim_lock enabled, falling back to legacy Linux kernel loader\n");
+      grub_dprintf ("linux", "using legacy shim_lock protocol, falling back to legacy Linux kernel loader\n");
 
       err = grub_cmd_linux_x86_legacy (cmd, argc, argv);
 
@@ -476,7 +476,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       else
        goto fail;
 #else
-      grub_dprintf ("linux", "shim_lock enabled, trying Linux kernel EFI stub loader\n");
+      grub_dprintf ("linux", "using legacy shim_lock protocol on non-x86, only db verifiable kernels will work\n");
 #endif
     }
 
index b686e8afeed2b4c65ed35a7799e7073d38d35148..9ae9087298eec2a17420ed2930b00945ff36d07e 100644 (file)
     { 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 } \
index 49a9ad01cc947b007ce0918133137dc9f09c86b7..4cae883769455c83db9ff61dc01921a472683b19 100644 (file)
@@ -32,7 +32,7 @@ extern grub_uint8_t
 EXPORT_FUNC (grub_efi_get_secureboot) (void);
 
 extern bool
-EXPORT_FUNC (grub_is_shim_lock_enabled) (void);
+EXPORT_FUNC (grub_is_using_legacy_shim_lock_protocol) (void);
 
 extern void
 grub_shim_lock_verifier_setup (void);