c78952
From eb8fd62e887e624f5c6e7c2ee8512981e8b5be97 Mon Sep 17 00:00:00 2001
f4c76c
From: Colin Watson <cjwatson@ubuntu.com>
f4c76c
Date: Tue, 23 Oct 2012 10:40:49 -0400
31cddd
Subject: [PATCH] Don't allow insmod when secure boot is enabled.
f4c76c
f4c76c
Hi,
f4c76c
f4c76c
Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
f4c76c
as far as it goes.  However, the insmod command is not the only way that
f4c76c
modules can be loaded.  In particular, the 'normal' command, which
f4c76c
implements the usual GRUB menu and the fully-featured command prompt,
f4c76c
will implicitly load commands not currently loaded into memory.  This
f4c76c
permits trivial Secure Boot violations by writing commands implementing
f4c76c
whatever you want to do and pointing $prefix at the malicious code.
f4c76c
f4c76c
I'm currently test-building this patch (replacing your current
f4c76c
grub-2.00-no-insmod-on-sb.patch), but this should be more correct.  It
f4c76c
moves the check into grub_dl_load_file.
f4c76c
---
9d15b4
 grub-core/kern/dl.c      | 22 ++++++++++++++++++++++
f4c76c
 grub-core/kern/efi/efi.c | 28 ++++++++++++++++++++++++++++
f4c76c
 include/grub/efi/efi.h   |  1 +
9d15b4
 3 files changed, 51 insertions(+)
f4c76c
f4c76c
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
ec4acb
index e394cd96f8c..621070918d4 100644
f4c76c
--- a/grub-core/kern/dl.c
f4c76c
+++ b/grub-core/kern/dl.c
9d15b4
@@ -32,12 +32,21 @@
9d15b4
 #include <grub/env.h>
9d15b4
 #include <grub/cache.h>
9d15b4
 #include <grub/i18n.h>
9d15b4
+#include <grub/efi/sb.h>
9d15b4
 
9d15b4
 /* Platforms where modules are in a readonly area of memory.  */
9d15b4
 #if defined(GRUB_MACHINE_QEMU)
f4c76c
 #define GRUB_MODULES_MACHINE_READONLY
f4c76c
 #endif
f4c76c
 
f4c76c
+#ifdef GRUB_MACHINE_EMU
f4c76c
+#include <sys/mman.h>
f4c76c
+#endif
f4c76c
+
f4c76c
+#ifdef GRUB_MACHINE_EFI
f4c76c
+#include <grub/efi/efi.h>
f4c76c
+#endif
f4c76c
+
f4c76c
 
f4c76c
 
f4c76c
 #pragma GCC diagnostic ignored "-Wcast-align"
9d15b4
@@ -686,6 +695,19 @@ grub_dl_load_file (const char *filename)
f4c76c
   void *core = 0;
f4c76c
   grub_dl_t mod = 0;
f4c76c
 
f4c76c
+#ifdef GRUB_MACHINE_EFI
f4c76c
+  if (grub_efi_secure_boot ())
f4c76c
+    {
f4c76c
+#if 0
f4c76c
+      /* This is an error, but grub2-mkconfig still generates a pile of
f4c76c
+       * insmod commands, so emitting it would be mostly just obnoxious. */
f4c76c
+      grub_error (GRUB_ERR_ACCESS_DENIED,
f4c76c
+		  "Secure Boot forbids loading module from %s", filename);
f4c76c
+#endif
f4c76c
+      return 0;
f4c76c
+    }
f4c76c
+#endif
f4c76c
+
f4c76c
   grub_boot_time ("Loading module %s", filename);
f4c76c
 
f4c76c
   file = grub_file_open (filename);
f4c76c
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
ec4acb
index 684ca93f8f4..2588b481e76 100644
f4c76c
--- a/grub-core/kern/efi/efi.c
f4c76c
+++ b/grub-core/kern/efi/efi.c
6f1e3d
@@ -269,6 +269,34 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
f4c76c
   return NULL;
f4c76c
 }
f4c76c
 
f4c76c
+grub_efi_boolean_t
f4c76c
+grub_efi_secure_boot (void)
f4c76c
+{
f4c76c
+  grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
f4c76c
+  grub_size_t datasize;
f4c76c
+  char *secure_boot = NULL;
f4c76c
+  char *setup_mode = NULL;
f4c76c
+  grub_efi_boolean_t ret = 0;
f4c76c
+
f4c76c
+  secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
f4c76c
+
f4c76c
+  if (datasize != 1 || !secure_boot)
f4c76c
+    goto out;
f4c76c
+
f4c76c
+  setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
f4c76c
+
f4c76c
+  if (datasize != 1 || !setup_mode)
f4c76c
+    goto out;
f4c76c
+
f4c76c
+  if (*secure_boot && !*setup_mode)
f4c76c
+    ret = 1;
f4c76c
+
f4c76c
+ out:
f4c76c
+  grub_free (secure_boot);
f4c76c
+  grub_free (setup_mode);
f4c76c
+  return ret;
f4c76c
+}
f4c76c
+
f4c76c
 #pragma GCC diagnostic ignored "-Wcast-align"
f4c76c
 
f4c76c
 /* Search the mods section from the PE32/PE32+ image. This code uses
f4c76c
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
ec4acb
index 91e29ce66f1..bb3ab7dfdeb 100644
f4c76c
--- a/include/grub/efi/efi.h
f4c76c
+++ b/include/grub/efi/efi.h
6f1e3d
@@ -83,6 +83,7 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
f4c76c
 				     const grub_efi_guid_t *guid,
f4c76c
 				     void *data,
f4c76c
 				     grub_size_t datasize);
f4c76c
+grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
f4c76c
 int
f4c76c
 EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
f4c76c
 					     const grub_efi_device_path_t *dp2);