a47bcbb
From 8a2a8d6021d926f00c5f85dab2d66f4ed8be86a2 Mon Sep 17 00:00:00 2001
a47bcbb
From: Colin Watson <cjwatson@ubuntu.com>
a47bcbb
Date: Tue, 23 Oct 2012 10:40:49 -0400
a47bcbb
Subject: [PATCH] Don't allow insmod when secure boot is enabled.
f1d3c74
a47bcbb
Hi,
a47bcbb
a47bcbb
Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
a47bcbb
as far as it goes.  However, the insmod command is not the only way that
a47bcbb
modules can be loaded.  In particular, the 'normal' command, which
a47bcbb
implements the usual GRUB menu and the fully-featured command prompt,
a47bcbb
will implicitly load commands not currently loaded into memory.  This
a47bcbb
permits trivial Secure Boot violations by writing commands implementing
a47bcbb
whatever you want to do and pointing $prefix at the malicious code.
a47bcbb
a47bcbb
I'm currently test-building this patch (replacing your current
a47bcbb
grub-2.00-no-insmod-on-sb.patch), but this should be more correct.  It
a47bcbb
moves the check into grub_dl_load_file.
f1d3c74
---
a47bcbb
 grub-core/kern/dl.c      | 17 +++++++++++++++++
f1d3c74
 grub-core/kern/efi/efi.c | 28 ++++++++++++++++++++++++++++
f1d3c74
 include/grub/efi/efi.h   |  1 +
a47bcbb
 3 files changed, 46 insertions(+)
f742f42
a47bcbb
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
a47bcbb
index a498682..2578fce 100644
a47bcbb
--- a/grub-core/kern/dl.c
a47bcbb
+++ b/grub-core/kern/dl.c
a47bcbb
@@ -43,6 +43,10 @@
a47bcbb
 #include <sys/mman.h>
a47bcbb
 #endif
f742f42
 
f742f42
+#ifdef GRUB_MACHINE_EFI
f742f42
+#include <grub/efi/efi.h>
f742f42
+#endif
f742f42
+
a47bcbb
 
a47bcbb
 
a47bcbb
 #pragma GCC diagnostic ignored "-Wcast-align"
a47bcbb
@@ -721,6 +725,19 @@ grub_dl_load_file (const char *filename)
a47bcbb
   void *core = 0;
a47bcbb
   grub_dl_t mod = 0;
f742f42
 
f742f42
+#ifdef GRUB_MACHINE_EFI
a47bcbb
+  if (grub_efi_secure_boot ())
a47bcbb
+    {
a47bcbb
+#if 0
a47bcbb
+      /* This is an error, but grub2-mkconfig still generates a pile of
a47bcbb
+       * insmod commands, so emitting it would be mostly just obnoxious. */
a47bcbb
+      grub_error (GRUB_ERR_ACCESS_DENIED,
a47bcbb
+		  "Secure Boot forbids loading module from %s", filename);
a47bcbb
+#endif
a47bcbb
+      return 0;
a47bcbb
+    }
f742f42
+#endif
f742f42
+
a47bcbb
   file = grub_file_open (filename);
a47bcbb
   if (! file)
a47bcbb
     return 0;
f742f42
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
f1d3c74
index 820968f..ad7aa8d 100644
f742f42
--- a/grub-core/kern/efi/efi.c
f742f42
+++ b/grub-core/kern/efi/efi.c
f1d3c74
@@ -259,6 +259,34 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
f1d3c74
   return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var);
f742f42
 }
f742f42
 
f742f42
+grub_efi_boolean_t
f742f42
+grub_efi_secure_boot (void)
f742f42
+{
f742f42
+  grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
f742f42
+  grub_size_t datasize;
f742f42
+  char *secure_boot = NULL;
f742f42
+  char *setup_mode = NULL;
f742f42
+  grub_efi_boolean_t ret = 0;
f742f42
+
f742f42
+  secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
f742f42
+
f742f42
+  if (datasize != 1 || !secure_boot)
f742f42
+    goto out;
f742f42
+
f742f42
+  setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
f742f42
+
f742f42
+  if (datasize != 1 || !setup_mode)
f742f42
+    goto out;
f742f42
+
f742f42
+  if (*secure_boot && !*setup_mode)
f742f42
+    ret = 1;
f742f42
+
f742f42
+ out:
f742f42
+  grub_free (secure_boot);
f742f42
+  grub_free (setup_mode);
f742f42
+  return ret;
f742f42
+}
f742f42
+
f742f42
 #pragma GCC diagnostic ignored "-Wcast-align"
f742f42
 
f742f42
 /* Search the mods section from the PE32/PE32+ image. This code uses
f742f42
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
f1d3c74
index 9370fd5..a000c38 100644
f742f42
--- a/include/grub/efi/efi.h
f742f42
+++ b/include/grub/efi/efi.h
f1d3c74
@@ -72,6 +72,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
f1d3c74
 				     const grub_efi_guid_t *guid,
f1d3c74
 				     void *data,
f1d3c74
 				     grub_size_t datasize);
f742f42
+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
f742f42
 int
f742f42
 EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
f742f42
 					     const grub_efi_device_path_t *dp2);
f1d3c74
-- 
a47bcbb
1.7.12.1
f1d3c74