grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v4 9/9] efi: Add EFI shim lock verifier


From: Daniel Kiper
Subject: [PATCH v4 9/9] efi: Add EFI shim lock verifier
Date: Tue, 30 Oct 2018 14:12:58 +0100

This module provides shim lock verification for various kernels
if UEFI secure boot is enabled on a machine.

It is recommended to put this module into GRUB2 standalone image
(avoid putting iorw and memrw modules into it; they are disallowed
if UEFI secure boot is enabled). However, it is also possible to use
it as a normal module. Though such configurations are more fragile
and less secure due to various limitations.

If the module is loaded and UEFI secure boot is enabled then:
  - module itself cannot be unloaded (persistent module),
  - the iorw and memrw modules cannot be loaded,
  - if the iorw and memrw modules are loaded then
    machine boot is disabled,
  - GRUB2 defers modules and ACPI tables verification to
    other verifiers.

Signed-off-by: Daniel Kiper <address@hidden>
---
v4 - suggestions/fixes:
   - s/GRUB_VERIFY_FLAGS_DEFER/GRUB_VERIFY_FLAGS_DEFER_AUTH/,
   - defer ACPI tables verification to other verifiers,
   - add shim lock verifier user documentation.

v3 - suggestions/fixes:
   - disable module unload,
   - disable the iorw and memrw modules loading,
   - disable boot if the iorw and memrw modules are loaded,
   - defer GRUB2 modules verification to other verifiers.
---
 docs/grub.texi                     |   15 ++++
 grub-core/Makefile.core.def        |    6 ++
 grub-core/commands/efi/shim_lock.c |  141 ++++++++++++++++++++++++++++++++++++
 3 files changed, 162 insertions(+)
 create mode 100644 grub-core/commands/efi/shim_lock.c

diff --git a/docs/grub.texi b/docs/grub.texi
index 2adfa97..471d97c 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5544,6 +5544,7 @@ environment variables and commands are listed in the same 
order.
 @menu
 * Authentication and authorisation:: Users and access control
 * Using digital signatures::         Booting digitally signed code
+* UEFI secure boot and shim::        Booting digitally signed PE files
 @end menu
 
 @node Authentication and authorisation
@@ -5706,6 +5707,20 @@ or BIOS) configuration to cause the machine to boot from 
a different
 (attacker-controlled) device.  GRUB is at best only one link in a
 secure boot chain.
 
address@hidden UEFI secure boot and shim
address@hidden UEFI secure boot and shim support
+
+The GRUB, except the @command{chainloader} command, works with the UEFI secure
+boot and the shim. This functionality is provided by the shim_lock module. It
+is recommend to build in this and other required modules into the 
@file{core.img}.
+All modules not stored in the @file{core.img} and the ACPI tables for the
address@hidden command have to be signed, e.g. using PGP. Additionally, the
address@hidden and the @command{memrw} commands are prohibited if the UEFI
+secure boot is enabled. This is done due to security reasons. All above
+mentioned requirements are enforced by the shim_lock module. And itself it
+is a persistent module which means that it cannot be unloaded if it was
+loaded into the memory.
+
 @node Platform limitations
 @chapter Platform limitations
 
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 7904f85..6e2cc84 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -900,6 +900,12 @@ module = {
 };
 
 module = {
+  name = shim_lock;
+  common = commands/efi/shim_lock.c;
+  enable = x86_64_efi;
+};
+
+module = {
   name = hdparm;
   common = commands/hdparm.c;
   enable = pci;
diff --git a/grub-core/commands/efi/shim_lock.c 
b/grub-core/commands/efi/shim_lock.c
new file mode 100644
index 0000000..01246b0
--- /dev/null
+++ b/grub-core/commands/efi/shim_lock.c
@@ -0,0 +1,141 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2017  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  EFI shim lock verifier.
+ */
+
+#include <grub/dl.h>
+#include <grub/efi/efi.h>
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/verify.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define GRUB_EFI_SHIM_LOCK_GUID \
+  { 0x605dab50, 0xe046, 0x4300, \
+    { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
+  }
+
+struct grub_efi_shim_lock_protocol
+{
+  grub_efi_status_t
+  (*verify) (void *buffer, grub_uint32_t size);
+};
+typedef struct grub_efi_shim_lock_protocol grub_efi_shim_lock_protocol_t;
+
+static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
+static grub_efi_shim_lock_protocol_t *sl;
+
+/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. 
*/
+static const char * const disabled_mods[] = {"iorw", "memrw", NULL};
+
+static grub_err_t
+shim_lock_init (grub_file_t io, enum grub_file_type type,
+               void **context __attribute__ ((unused)),
+               enum grub_verify_flags *flags)
+{
+  const char *b, *e;
+  int i;
+
+  *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+
+  if (!sl)
+    return GRUB_ERR_NONE;
+
+  switch (type & GRUB_FILE_TYPE_MASK)
+    {
+    case GRUB_FILE_TYPE_GRUB_MODULE:
+      /* Establish GRUB module name. */
+      b = grub_strrchr (io->name, '/');
+      e = grub_strrchr (io->name, '.');
+
+      b = b ? (b + 1) : io->name;
+      e = e ? e : io->name + grub_strlen (io->name);
+      e = (e > b) ? e : io->name + grub_strlen (io->name);
+
+      for (i = 0; disabled_mods[i]; i++)
+       if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen 
(e)))
+         {
+           grub_error (GRUB_ERR_ACCESS_DENIED,
+                       N_("module cannot be loaded in UEFI secure boot mode: 
%s"),
+                       io->name);
+           return GRUB_ERR_ACCESS_DENIED;
+         }
+
+      /* Fall through. */
+
+    case GRUB_FILE_TYPE_ACPI_TABLE:
+      *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+
+      return GRUB_ERR_NONE;
+
+    case GRUB_FILE_TYPE_LINUX_KERNEL:
+    case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
+    case GRUB_FILE_TYPE_BSD_KERNEL:
+    case GRUB_FILE_TYPE_XNU_KERNEL:
+    case GRUB_FILE_TYPE_PLAN9_KERNEL:
+      for (i = 0; disabled_mods[i]; i++)
+       if (grub_dl_get (disabled_mods[i]))
+         {
+           grub_error (GRUB_ERR_ACCESS_DENIED,
+                       N_("cannot boot due to dangerous module in memory: %s"),
+                       disabled_mods[i]);
+           return GRUB_ERR_ACCESS_DENIED;
+         }
+
+      *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
+
+      /* Fall through. */
+
+    default:
+      return GRUB_ERR_NONE;
+    }
+}
+
+static grub_err_t
+shim_lock_write (void *context __attribute__ ((unused)), void *buf, 
grub_size_t size)
+{
+  if (sl->verify (buf, size) != GRUB_EFI_SUCCESS)
+    return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature"));
+
+  return GRUB_ERR_NONE;
+}
+
+struct grub_file_verifier shim_lock =
+  {
+    .name = "shim_lock",
+    .init = shim_lock_init,
+    .write = shim_lock_write
+  };
+
+GRUB_MOD_INIT(shim_lock)
+{
+  sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
+  grub_verifier_register (&shim_lock);
+
+  if (!sl)
+    return;
+
+  grub_dl_set_persistent (mod);
+}
+
+GRUB_MOD_FINI(shim_lock)
+{
+  grub_verifier_unregister (&shim_lock);
+}
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]