ea38f2f
From 6b6203b92cfb457a0669a9c87a29b360405bffc6 Mon Sep 17 00:00:00 2001
6a91557
From: Matthew Garrett <matthew.garrett@nebula.com>
6a91557
Date: Fri, 9 Aug 2013 18:36:30 -0400
ea38f2f
Subject: [PATCH 10/20] Add option to automatically enforce module signatures
ea38f2f
 when in Secure Boot mode
6a91557
6a91557
UEFI Secure Boot provides a mechanism for ensuring that the firmware will
6a91557
only load signed bootloaders and kernels. Certain use cases may also
6a91557
require that all kernel modules also be signed. Add a configuration option
6a91557
that enforces this automatically when enabled.
6a91557
6a91557
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
6a91557
---
6a91557
 Documentation/x86/zero-page.txt       |  2 ++
42d2805
 arch/x86/Kconfig                      | 11 ++++++
c3b50ba
 arch/x86/boot/compressed/eboot.c      | 66 +++++++++++++++++++++++++++++++++++
c3b50ba
 arch/x86/include/uapi/asm/bootparam.h |  3 +-
c3b50ba
 arch/x86/kernel/setup.c               |  6 ++++
c3b50ba
 include/linux/module.h                |  6 ++++
c3b50ba
 kernel/module.c                       |  7 ++++
42d2805
 7 files changed, 100 insertions(+), 1 deletion(-)
6a91557
6a91557
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
42d2805
index 95a4d34af3fd..b8527c6b7646 100644
6a91557
--- a/Documentation/x86/zero-page.txt
6a91557
+++ b/Documentation/x86/zero-page.txt
18c8249
@@ -31,6 +31,8 @@ Offset	Proto	Name		Meaning
6a91557
 1E9/001	ALL	eddbuf_entries	Number of entries in eddbuf (below)
6a91557
 1EA/001	ALL	edd_mbr_sig_buf_entries	Number of entries in edd_mbr_sig_buffer
6a91557
 				(below)
6a91557
+1EB/001	ALL     kbd_status      Numlock is enabled
6a91557
+1EC/001	ALL     secure_boot	Secure boot is enabled in the firmware
6a91557
 1EF/001	ALL	sentinel	Used to detect broken bootloaders
6a91557
 290/040	ALL	edd_mbr_sig_buffer EDD MBR signatures
6a91557
 2D0/A00	ALL	e820_map	E820 memory map table
6a91557
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
ea38f2f
index bada636d1065..d666ef8b616c 100644
6a91557
--- a/arch/x86/Kconfig
6a91557
+++ b/arch/x86/Kconfig
ea38f2f
@@ -1786,6 +1786,17 @@ config EFI_MIXED
6a91557
 
6a91557
 	   If unsure, say N.
6a91557
 
6a91557
+config EFI_SECURE_BOOT_SIG_ENFORCE
42d2805
+	def_bool n
42d2805
+	depends on EFI
6a91557
+	prompt "Force module signing when UEFI Secure Boot is enabled"
6a91557
+	---help---
6a91557
+	  UEFI Secure Boot provides a mechanism for ensuring that the
6a91557
+	  firmware will only load signed bootloaders and kernels. Certain
6a91557
+	  use cases may also require that all kernel modules also be signed.
6a91557
+	  Say Y here to automatically enable module signature enforcement
6a91557
+	  when a system boots with UEFI Secure Boot enabled.
6a91557
+
6a91557
 config SECCOMP
6a91557
 	def_bool y
6a91557
 	prompt "Enable seccomp to safely compute untrusted bytecode"
6a91557
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
ea38f2f
index cc69e37548db..ebc85c1eefd6 100644
6a91557
--- a/arch/x86/boot/compressed/eboot.c
6a91557
+++ b/arch/x86/boot/compressed/eboot.c
6a91557
@@ -12,6 +12,7 @@
6a91557
 #include <asm/efi.h>
6a91557
 #include <asm/setup.h>
6a91557
 #include <asm/desc.h>
6a91557
+#include <asm/bootparam_utils.h>
6a91557
 
f1193f2
 #include "../string.h"
f1193f2
 #include "eboot.h"
ea38f2f
@@ -537,6 +538,67 @@ static void setup_efi_pci(struct boot_params *params)
c3b50ba
 	efi_call_early(free_pool, pci_handle);
6a91557
 }
6a91557
 
6a91557
+static int get_secure_boot(void)
6a91557
+{
6a91557
+	u8 sb, setup;
6a91557
+	unsigned long datasize = sizeof(sb);
6a91557
+	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
6a91557
+	efi_status_t status;
6a91557
+
6a91557
+	status = efi_early->call((unsigned long)sys_table->runtime->get_variable,
6a91557
+				L"SecureBoot", &var_guid, NULL, &datasize, &sb);
6a91557
+
6a91557
+	if (status != EFI_SUCCESS)
6a91557
+		return 0;
6a91557
+
6a91557
+	if (sb == 0)
6a91557
+		return 0;
6a91557
+
6a91557
+
6a91557
+	status = efi_early->call((unsigned long)sys_table->runtime->get_variable,
6a91557
+				L"SetupMode", &var_guid, NULL, &datasize,
6a91557
+				&setup);
6a91557
+
6a91557
+	if (status != EFI_SUCCESS)
6a91557
+		return 0;
6a91557
+
6a91557
+	if (setup == 1)
6a91557
+		return 0;
6a91557
+
6a91557
+	return 1;
6a91557
+}
6a91557
+
6a91557
+
c3b50ba
+/*
c3b50ba
+ * See if we have Graphics Output Protocol
c3b50ba
+ */
c3b50ba
+static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
c3b50ba
+			      unsigned long size)
c3b50ba
+{
c3b50ba
+	efi_status_t status;
c3b50ba
+	void **gop_handle = NULL;
c3b50ba
+
c3b50ba
+	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
c3b50ba
+				size, (void **)&gop_handle);
c3b50ba
+	if (status != EFI_SUCCESS)
c3b50ba
+		return status;
c3b50ba
+
c3b50ba
+	status = efi_call_early(locate_handle,
c3b50ba
+				EFI_LOCATE_BY_PROTOCOL,
c3b50ba
+				proto, NULL, &size, gop_handle);
c3b50ba
+	if (status != EFI_SUCCESS)
c3b50ba
+		goto free_handle;
c3b50ba
+
c3b50ba
+	if (efi_early->is64)
c3b50ba
+		status = setup_gop64(si, proto, size, gop_handle);
c3b50ba
+	else
c3b50ba
+		status = setup_gop32(si, proto, size, gop_handle);
c3b50ba
+
c3b50ba
+free_handle:
c3b50ba
+	efi_call_early(free_pool, gop_handle);
c3b50ba
+	return status;
c3b50ba
+}
c3b50ba
+
c3b50ba
 static efi_status_t
c3b50ba
 setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
c3b50ba
 {
ea38f2f
@@ -1094,6 +1156,10 @@ struct boot_params *efi_main(struct efi_config *c,
6a91557
 	else
6a91557
 		setup_boot_services32(efi_early);
6a91557
 
6a91557
+	sanitize_boot_params(boot_params);
6a91557
+
6a91557
+	boot_params->secure_boot = get_secure_boot();
6a91557
+
6a91557
 	setup_graphics(boot_params);
6a91557
 
c33dae8
 	setup_efi_pci(boot_params);
6a91557
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
42d2805
index c18ce67495fa..2b3e5427097b 100644
6a91557
--- a/arch/x86/include/uapi/asm/bootparam.h
6a91557
+++ b/arch/x86/include/uapi/asm/bootparam.h
b18e6e7
@@ -134,7 +134,8 @@ struct boot_params {
6a91557
 	__u8  eddbuf_entries;				/* 0x1e9 */
6a91557
 	__u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
6a91557
 	__u8  kbd_status;				/* 0x1eb */
6a91557
-	__u8  _pad5[3];					/* 0x1ec */
6a91557
+	__u8  secure_boot;				/* 0x1ec */
6a91557
+	__u8  _pad5[2];					/* 0x1ed */
6a91557
 	/*
6a91557
 	 * The sentinel is set to a nonzero value (0xff) in header.S.
6a91557
 	 *
6a91557
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
ea38f2f
index bbfbca5fea0c..d40e961753c9 100644
6a91557
--- a/arch/x86/kernel/setup.c
6a91557
+++ b/arch/x86/kernel/setup.c
ea38f2f
@@ -1160,6 +1160,12 @@ void __init setup_arch(char **cmdline_p)
6a91557
 
6a91557
 	io_delay_init();
6a91557
 
6a91557
+#ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE
6a91557
+	if (boot_params.secure_boot) {
6a91557
+		enforce_signed_modules();
6a91557
+	}
6a91557
+#endif
6a91557
+
6a91557
 	/*
6a91557
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
6a91557
 	 */
6a91557
diff --git a/include/linux/module.h b/include/linux/module.h
ea38f2f
index 05bd6c989a0c..32327704e18d 100644
6a91557
--- a/include/linux/module.h
6a91557
+++ b/include/linux/module.h
ea38f2f
@@ -260,6 +260,12 @@ extern const typeof(name) __mod_##type##__##name##_device_table		\
6a91557
 
6a91557
 struct notifier_block;
6a91557
 
6a91557
+#ifdef CONFIG_MODULE_SIG
6a91557
+extern void enforce_signed_modules(void);
6a91557
+#else
6a91557
+static inline void enforce_signed_modules(void) {};
6a91557
+#endif
6a91557
+
6a91557
 #ifdef CONFIG_MODULES
6a91557
 
6a91557
 extern int modules_disabled; /* for sysctl */
6a91557
diff --git a/kernel/module.c b/kernel/module.c
ea38f2f
index cb864505d020..cb1f1da69bf4 100644
6a91557
--- a/kernel/module.c
6a91557
+++ b/kernel/module.c
ea38f2f
@@ -4285,6 +4285,13 @@ void module_layout(struct module *mod,
6a91557
 EXPORT_SYMBOL(module_layout);
6a91557
 #endif
6a91557
 
6a91557
+#ifdef CONFIG_MODULE_SIG
6a91557
+void enforce_signed_modules(void)
6a91557
+{
6a91557
+	sig_enforce = true;
6a91557
+}
6a91557
+#endif
6a91557
+
6a91557
 bool secure_modules(void)
6a91557
 {
6a91557
 #ifdef CONFIG_MODULE_SIG
18c8249
-- 
ea38f2f
2.9.3
18c8249