]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
shim_lock: Only skip loading shim_lock verifier with explicit consent
authorDimitri John Ledkov <xnox@ubuntu.com>
Sat, 20 Feb 2021 17:10:34 +0000 (17:10 +0000)
committerDaniel Kiper <daniel.kiper@oracle.com>
Tue, 2 Mar 2021 14:54:19 +0000 (15:54 +0100)
Commit 32ddc42c (efi: Only register shim_lock verifier if shim_lock
protocol is found and SB enabled) reintroduced CVE-2020-15705 which
previously only existed in the out-of-tree linuxefi patches and was
fixed as part of the BootHole patch series.

Under Secure Boot enforce loading shim_lock verifier. Allow skipping
shim_lock verifier if SecureBoot/MokSBState EFI variables indicate
skipping validations, or if GRUB image is built with --disable-shim-lock.

Fixes: 132ddc42c (efi: Only register shim_lock verifier if shim_lock
       protocol is found and SB enabled)
Fixes: CVE-2020-15705
Fixes: CVE-2021-3418
Reported-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
docs/grub.texi
grub-core/kern/efi/sb.c
include/grub/kernel.h
include/grub/util/install.h
util/grub-install-common.c
util/grub-mkimage.c
util/mkimage.c

index 81b90947ae7c8241bf82aef1fda98bd66cccea81..2f2ae22289bbec49ef71534a987de2eae8ccbcbc 100644 (file)
@@ -5950,7 +5950,10 @@ secure boot chain.
 The GRUB, except the @command{chainloader} command, works with the UEFI secure
 boot and the shim. This functionality is provided by the shim_lock verifier. It
 is built into the @file{core.img} and is registered if the UEFI secure boot is
-enabled.
+enabled. The @samp{shim_lock} variable is set to @samp{y} when shim_lock verifier
+is registered. If it is desired to use UEFI secure boot without shim, one can
+disable shim_lock by disabling shim verification with MokSbState UEFI variable
+or by building grub image with @samp{--disable-shim-lock} option.
 
 All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables,
 Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands
index 5d7210a82ea55a16ef44667c3baf716697a55a16..41dadcd14d4b4da5b4348be9466e9aa383117194 100644 (file)
 #include <grub/efi/efi.h>
 #include <grub/efi/pe32.h>
 #include <grub/efi/sb.h>
+#include <grub/env.h>
 #include <grub/err.h>
 #include <grub/file.h>
 #include <grub/i386/linux.h>
+#include <grub/kernel.h>
 #include <grub/mm.h>
 #include <grub/types.h>
 #include <grub/verify.h>
@@ -160,14 +162,27 @@ struct grub_file_verifier shim_lock_verifier =
 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)
-    return;
+    {
+      FOR_MODULES (header)
+       {
+         if (header->type == OBJ_TYPE_DISABLE_SHIM_LOCK)
+           return;
+       }
+    }
 
+  /* 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);
+
+  grub_env_set ("shim_lock", "y");
+  grub_env_export ("shim_lock");
 }
index 133a37c8d035c22b476339a6256d5950f4b91d40..abbca5ea3359b7603144f5957fe4c39e0af66622 100644 (file)
@@ -29,7 +29,8 @@ enum
   OBJ_TYPE_CONFIG,
   OBJ_TYPE_PREFIX,
   OBJ_TYPE_PUBKEY,
-  OBJ_TYPE_DTB
+  OBJ_TYPE_DTB,
+  OBJ_TYPE_DISABLE_SHIM_LOCK
 };
 
 /* The module header.  */
index c14985858e6183e2e2c5275a444efd66e3baf935..b93c73caac646abaa12e23e4f585d1afa6d083bc 100644 (file)
@@ -65,6 +65,8 @@
       N_("embed FILE as public key for signature checking"), 0},       \
   { "sbat", GRUB_INSTALL_OPTIONS_SBAT, N_("FILE"), 0,                  \
       N_("SBAT metadata"), 0 },                                                \
+  { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \
+      N_("disable shim_lock verifier"), 0 },                           \
   { "verbose", 'v', 0, 0,                                              \
     N_("print verbose messages."), 1 }
 
@@ -125,7 +127,8 @@ enum grub_install_options {
   GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
   GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
   GRUB_INSTALL_OPTIONS_DTB,
-  GRUB_INSTALL_OPTIONS_SBAT
+  GRUB_INSTALL_OPTIONS_SBAT,
+  GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK
 };
 
 extern char *grub_install_source_directory;
@@ -187,7 +190,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
                             const struct grub_install_image_target_desc *image_target,
                             int note,
                             grub_compression_t comp, const char *dtb_file,
-                            const char *sbat_path);
+                            const char *sbat_path, const int disable_shim_lock);
 
 const struct grub_install_image_target_desc *
 grub_install_get_image_target (const char *arg);
index 89af26c264b59c03be7a9f6449911a969ef8db86..b4f28840f10e184b9ea4f33143e13a13b5499077 100644 (file)
@@ -333,6 +333,7 @@ handle_install_list (struct install_list *il, const char *val,
 static char **pubkeys;
 static size_t npubkeys;
 static char *sbat;
+static int disable_shim_lock;
 static grub_compression_t compression;
 
 int
@@ -369,6 +370,9 @@ grub_install_parse (int key, char *arg)
 
       sbat = xstrdup (arg);
       return 1;
+    case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
+      disable_shim_lock = 1;
+      return 1;
 
     case GRUB_INSTALL_OPTIONS_VERBOSITY:
       verbosity++;
@@ -531,10 +535,11 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
                  " --output '%s' "
                  " --dtb '%s' "
                  "--sbat '%s' "
-                 "--format '%s' --compression '%s' %s %s\n",
+                 "--format '%s' --compression '%s' %s %s %s\n",
                  dir, prefix,
                  outname, dtb ? : "", sbat ? : "", mkimage_target,
-                 compnames[compression], note ? "--note" : "", s);
+                 compnames[compression], note ? "--note" : "",
+                 disable_shim_lock ? "--disable-shim-lock" : "", s);
   free (s);
 
   tgt = grub_install_get_image_target (mkimage_target);
@@ -544,7 +549,8 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_install_generate_image (dir, prefix, fp, outname,
                               modules.entries, memdisk_path,
                               pubkeys, npubkeys, config_path, tgt,
-                              note, compression, dtb, sbat);
+                              note, compression, dtb, sbat,
+                              disable_shim_lock);
   while (dc--)
     grub_install_pop_module ();
 }
index 75b884710f1d4032c02f82c39b45b561dbb74f66..c0d559937020b2d2d20007734c7c85d89f1e3041 100644 (file)
@@ -82,6 +82,7 @@ static struct argp_option options[] = {
   {"format",  'O', N_("FORMAT"), 0, 0, 0},
   {"compression",  'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
   {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
+  {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
   { 0, 0, 0, 0, 0, 0 }
 };
@@ -126,6 +127,7 @@ struct arguments
   char *config;
   char *sbat;
   int note;
+  int disable_shim_lock;
   const struct grub_install_image_target_desc *image_target;
   grub_compression_t comp;
 };
@@ -233,6 +235,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
       arguments->sbat = xstrdup (arg);
       break;
 
+    case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
+      arguments->disable_shim_lock = 1;
+      break;
+
     case 'v':
       verbosity++;
       break;
@@ -319,7 +325,7 @@ main (int argc, char *argv[])
                               arguments.npubkeys, arguments.config,
                               arguments.image_target, arguments.note,
                               arguments.comp, arguments.dtb,
-                              arguments.sbat);
+                              arguments.sbat, arguments.disable_shim_lock);
 
   if (grub_util_file_sync (fp) < 0)
     grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
index b354ec1d9bb3322ee0072973f68221c9df122327..a26cf76f72f2be0af65efc5c7355b86441fc3e56 100644 (file)
@@ -870,7 +870,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
                             size_t npubkeys, char *config_path,
                             const struct grub_install_image_target_desc *image_target,
                             int note, grub_compression_t comp, const char *dtb_path,
-                            const char *sbat_path)
+                            const char *sbat_path, int disable_shim_lock)
 {
   char *kernel_img, *core_img;
   size_t total_module_size, core_size;
@@ -929,6 +929,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
   if (sbat_path != NULL && image_target->id != IMAGE_EFI)
     grub_util_error (_(".sbat section can be embedded into EFI images only"));
 
+  if (disable_shim_lock)
+    total_module_size += sizeof (struct grub_module_header);
+
   if (config_path)
     {
       config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@@ -1065,6 +1068,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
       offset += dtb_size;
     }
 
+  if (disable_shim_lock)
+    {
+      struct grub_module_header *header;
+
+      header = (struct grub_module_header *) (kernel_img + offset);
+      header->type = grub_host_to_target32 (OBJ_TYPE_DISABLE_SHIM_LOCK);
+      header->size = grub_host_to_target32 (sizeof (*header));
+      offset += sizeof (*header);
+    }
+
   if (config_path)
     {
       struct grub_module_header *header;