Blob Blame History Raw
From 085e51ec31d08c9b7e027fe8a25a9894765b9547 Mon Sep 17 00:00:00 2001
From: Colin Watson <cjwatson@ubuntu.com>
Date: Tue, 23 Oct 2012 10:40:49 -0400
Subject: [PATCH 070/176] Don't allow insmod when secure boot is enabled.

Hi,

Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
as far as it goes.  However, the insmod command is not the only way that
modules can be loaded.  In particular, the 'normal' command, which
implements the usual GRUB menu and the fully-featured command prompt,
will implicitly load commands not currently loaded into memory.  This
permits trivial Secure Boot violations by writing commands implementing
whatever you want to do and pointing $prefix at the malicious code.

I'm currently test-building this patch (replacing your current
grub-2.00-no-insmod-on-sb.patch), but this should be more correct.  It
moves the check into grub_dl_load_file.
---
 grub-core/kern/dl.c      | 22 ++++++++++++++++++++++
 grub-core/kern/efi/efi.c | 28 ++++++++++++++++++++++++++++
 include/grub/efi/efi.h   |  1 +
 3 files changed, 51 insertions(+)

diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index e394cd96f..621070918 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -32,12 +32,21 @@
 #include <grub/env.h>
 #include <grub/cache.h>
 #include <grub/i18n.h>
+#include <grub/efi/sb.h>
 
 /* Platforms where modules are in a readonly area of memory.  */
 #if defined(GRUB_MACHINE_QEMU)
 #define GRUB_MODULES_MACHINE_READONLY
 #endif
 
+#ifdef GRUB_MACHINE_EMU
+#include <sys/mman.h>
+#endif
+
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#endif
+
 
 
 #pragma GCC diagnostic ignored "-Wcast-align"
@@ -686,6 +695,19 @@ grub_dl_load_file (const char *filename)
   void *core = 0;
   grub_dl_t mod = 0;
 
+#ifdef GRUB_MACHINE_EFI
+  if (grub_efi_secure_boot ())
+    {
+#if 0
+      /* This is an error, but grub2-mkconfig still generates a pile of
+       * insmod commands, so emitting it would be mostly just obnoxious. */
+      grub_error (GRUB_ERR_ACCESS_DENIED,
+		  "Secure Boot forbids loading module from %s", filename);
+#endif
+      return 0;
+    }
+#endif
+
   grub_boot_time ("Loading module %s", filename);
 
   file = grub_file_open (filename);
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 684ca93f8..2588b481e 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -269,6 +269,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
   return NULL;
 }
 
+grub_efi_boolean_t
+grub_efi_secure_boot (void)
+{
+  grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+  grub_size_t datasize;
+  char *secure_boot = NULL;
+  char *setup_mode = NULL;
+  grub_efi_boolean_t ret = 0;
+
+  secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
+
+  if (datasize != 1 || !secure_boot)
+    goto out;
+
+  setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
+
+  if (datasize != 1 || !setup_mode)
+    goto out;
+
+  if (*secure_boot && !*setup_mode)
+    ret = 1;
+
+ out:
+  grub_free (secure_boot);
+  grub_free (setup_mode);
+  return ret;
+}
+
 #pragma GCC diagnostic ignored "-Wcast-align"
 
 /* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 764cd11f5..62a3d9726 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -76,6 +76,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
 				     const grub_efi_guid_t *guid,
 				     void *data,
 				     grub_size_t datasize);
+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
 int
 EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
 					     const grub_efi_device_path_t *dp2);
-- 
2.13.0