Blame SOURCES/0093-Don-t-allow-insmod-when-secure-boot-is-enabled.patch

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