b1b2d34
From 0c5837031a4e996877930fd023a5877dd1d615ba Mon Sep 17 00:00:00 2001
306dfcc
From: Matthew Garrett <mjg@redhat.com>
f0f4ff2
Date: Thu, 20 Sep 2012 10:40:56 -0400
b1b2d34
Subject: [PATCH 01/19] Secure boot: Add new capability
306dfcc
306dfcc
Secure boot adds certain policy requirements, including that root must not
306dfcc
be able to do anything that could cause the kernel to execute arbitrary code.
306dfcc
The simplest way to handle this would seem to be to add a new capability
306dfcc
and gate various functionality on that. We'll then strip it from the initial
306dfcc
capability set if required.
306dfcc
306dfcc
Signed-off-by: Matthew Garrett <mjg@redhat.com>
306dfcc
---
be7ac52
 include/uapi/linux/capability.h | 6 +++++-
306dfcc
 1 file changed, 5 insertions(+), 1 deletion(-)
306dfcc
4fc17ca
diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h
4fc17ca
index ba478fa..7109e65 100644
be7ac52
--- a/include/uapi/linux/capability.h
be7ac52
+++ b/include/uapi/linux/capability.h
4fc17ca
@@ -343,7 +343,11 @@ struct vfs_cap_data {
306dfcc
 
306dfcc
 #define CAP_BLOCK_SUSPEND    36
306dfcc
 
306dfcc
-#define CAP_LAST_CAP         CAP_BLOCK_SUSPEND
f0f4ff2
+/* Allow things that trivially permit root to modify the running kernel */
306dfcc
+
f0f4ff2
+#define CAP_COMPROMISE_KERNEL  37
306dfcc
+
f0f4ff2
+#define CAP_LAST_CAP         CAP_COMPROMISE_KERNEL
306dfcc
 
306dfcc
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
306dfcc
 
306dfcc
-- 
b1b2d34
1.8.1.2
306dfcc
306dfcc
b1b2d34
From 87c8fddbcb3042fc4174b53763adbf66045a12be Mon Sep 17 00:00:00 2001
f82b107
From: Josh Boyer <jwboyer@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:41:05 -0400
b1b2d34
Subject: [PATCH 02/19] SELinux: define mapping for new Secure Boot capability
306dfcc
f82b107
Add the name of the new Secure Boot capability.  This allows SELinux
f82b107
policies to properly map CAP_COMPROMISE_KERNEL to the appropriate
f82b107
capability class.
306dfcc
f82b107
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
306dfcc
---
f82b107
 security/selinux/include/classmap.h | 4 ++--
f82b107
 1 file changed, 2 insertions(+), 2 deletions(-)
306dfcc
f82b107
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
47a1ebc
index 14d04e6..ed99a2d 100644
f82b107
--- a/security/selinux/include/classmap.h
f82b107
+++ b/security/selinux/include/classmap.h
f82b107
@@ -146,8 +146,8 @@ struct security_class_mapping secclass_map[] = {
f82b107
 	{ "memprotect", { "mmap_zero", NULL } },
f82b107
 	{ "peer", { "recv", NULL } },
f82b107
 	{ "capability2",
f82b107
-	  { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend",
f82b107
-	    NULL } },
f82b107
+	  { "mac_override", "mac_admin", "syslog", "wake_alarm",
f82b107
+	    "block_suspend", "compromise_kernel", NULL } },
f82b107
 	{ "kernel_service", { "use_as_override", "create_files_as", NULL } },
f82b107
 	{ "tun_socket",
47a1ebc
 	  { COMMON_SOCK_PERMS, "attach_queue", NULL } },
306dfcc
-- 
b1b2d34
1.8.1.2
306dfcc
306dfcc
b1b2d34
From df14b5319bf3ed2110839e233ac61e6136745be8 Mon Sep 17 00:00:00 2001
f82b107
From: Josh Boyer <jwboyer@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:41:02 -0400
b1b2d34
Subject: [PATCH 03/19] Secure boot: Add a dummy kernel parameter that will
f82b107
 switch on Secure Boot mode
306dfcc
f82b107
This forcibly drops CAP_COMPROMISE_KERNEL from both cap_permitted and cap_bset
f82b107
in the init_cred struct, which everything else inherits from.  This works on
f82b107
any machine and can be used to develop even if the box doesn't have UEFI.
306dfcc
f82b107
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
306dfcc
---
f82b107
 Documentation/kernel-parameters.txt |  7 +++++++
f82b107
 kernel/cred.c                       | 17 +++++++++++++++++
f82b107
 2 files changed, 24 insertions(+)
306dfcc
f82b107
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
b1b2d34
index 6c72381..7dffdd5 100644
f82b107
--- a/Documentation/kernel-parameters.txt
f82b107
+++ b/Documentation/kernel-parameters.txt
f82b107
@@ -2654,6 +2654,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
f82b107
 			Note: increases power consumption, thus should only be
f82b107
 			enabled if running jitter sensitive (HPC/RT) workloads.
306dfcc
 
f82b107
+	secureboot_enable=
f82b107
+			[KNL] Enables an emulated UEFI Secure Boot mode.  This
f82b107
+			locks down various aspects of the kernel guarded by the
f82b107
+			CAP_COMPROMISE_KERNEL capability.  This includes things
f82b107
+			like /dev/mem, IO port access, and other areas.  It can
f82b107
+			be used on non-UEFI machines for testing purposes.
f82b107
+
f82b107
 	security=	[SECURITY] Choose a security module to enable at boot.
f82b107
 			If this boot parameter is not specified, only the first
f82b107
 			security module asking for security registration will be
f82b107
diff --git a/kernel/cred.c b/kernel/cred.c
f82b107
index e0573a4..c3f4e3e 100644
f82b107
--- a/kernel/cred.c
f82b107
+++ b/kernel/cred.c
f82b107
@@ -565,6 +565,23 @@ void __init cred_init(void)
f82b107
 				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
f82b107
 }
306dfcc
 
f82b107
+void __init secureboot_enable()
f82b107
+{
f82b107
+	pr_info("Secure boot enabled\n");
f82b107
+	cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL);
f82b107
+	cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL);
f82b107
+}
306dfcc
+
f82b107
+/* Dummy Secure Boot enable option to fake out UEFI SB=1 */
f82b107
+static int __init secureboot_enable_opt(char *str)
f82b107
+{
f82b107
+	int sb_enable = !!simple_strtol(str, NULL, 0);
f82b107
+	if (sb_enable)
f82b107
+		secureboot_enable();
f82b107
+	return 1;
f82b107
+}
f82b107
+__setup("secureboot_enable=", secureboot_enable_opt);
f82b107
+
f82b107
 /**
f82b107
  * prepare_kernel_cred - Prepare a set of credentials for a kernel service
f82b107
  * @daemon: A userspace daemon to be used as a reference
306dfcc
-- 
b1b2d34
1.8.1.2
306dfcc
306dfcc
b1b2d34
From 49c76a665e8a09da48cbe271ea40266ca1a226c0 Mon Sep 17 00:00:00 2001
306dfcc
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:41:03 -0400
b1b2d34
Subject: [PATCH 04/19] efi: Enable secure boot lockdown automatically when
f82b107
 enabled in firmware
306dfcc
f82b107
The firmware has a set of flags that indicate whether secure boot is enabled
f82b107
and enforcing. Use them to indicate whether the kernel should lock itself
a8e5aec
down.  We also indicate the machine is in secure boot mode by adding the
a8e5aec
EFI_SECURE_BOOT bit for use with efi_enabled.
306dfcc
306dfcc
Signed-off-by: Matthew Garrett <mjg@redhat.com>
a8e5aec
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
306dfcc
---
f82b107
 Documentation/x86/zero-page.txt       |  2 ++
f82b107
 arch/x86/boot/compressed/eboot.c      | 32 ++++++++++++++++++++++++++++++++
f82b107
 arch/x86/include/uapi/asm/bootparam.h |  3 ++-
b1b2d34
 arch/x86/kernel/setup.c               |  7 +++++++
f82b107
 include/linux/cred.h                  |  2 ++
a8e5aec
 include/linux/efi.h                   |  1 +
b1b2d34
 6 files changed, 46 insertions(+), 1 deletion(-)
306dfcc
f82b107
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
47a1ebc
index 199f453..ff651d3 100644
f82b107
--- a/Documentation/x86/zero-page.txt
f82b107
+++ b/Documentation/x86/zero-page.txt
47a1ebc
@@ -30,6 +30,8 @@ Offset	Proto	Name		Meaning
f82b107
 1E9/001	ALL	eddbuf_entries	Number of entries in eddbuf (below)
f82b107
 1EA/001	ALL	edd_mbr_sig_buf_entries	Number of entries in edd_mbr_sig_buffer
f82b107
 				(below)
f82b107
+1EB/001	ALL	kbd_status	Numlock is enabled
f82b107
+1EC/001	ALL	secure_boot	Kernel should enable secure boot lockdowns
47a1ebc
 1EF/001	ALL	sentinel	Used to detect broken bootloaders
f82b107
 290/040	ALL	edd_mbr_sig_buffer EDD MBR signatures
f82b107
 2D0/A00	ALL	e820_map	E820 memory map table
f82b107
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
47a1ebc
index f8fa411..96bd86b 100644
f82b107
--- a/arch/x86/boot/compressed/eboot.c
f82b107
+++ b/arch/x86/boot/compressed/eboot.c
47a1ebc
@@ -849,6 +849,36 @@ fail:
f82b107
 	return status;
f82b107
 }
306dfcc
 
f82b107
+static int get_secure_boot(efi_system_table_t *_table)
f82b107
+{
f82b107
+	u8 sb, setup;
f82b107
+	unsigned long datasize = sizeof(sb);
f82b107
+	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
f82b107
+	efi_status_t status;
306dfcc
+
306dfcc
+	status = efi_call_phys5(sys_table->runtime->get_variable,
306dfcc
+				L"SecureBoot", &var_guid, NULL, &datasize, &sb);
306dfcc
+
306dfcc
+	if (status != EFI_SUCCESS)
306dfcc
+		return 0;
306dfcc
+
306dfcc
+	if (sb == 0)
306dfcc
+		return 0;
306dfcc
+
306dfcc
+
306dfcc
+	status = efi_call_phys5(sys_table->runtime->get_variable,
306dfcc
+				L"SetupMode", &var_guid, NULL, &datasize,
306dfcc
+				&setup);
306dfcc
+
306dfcc
+	if (status != EFI_SUCCESS)
306dfcc
+		return 0;
306dfcc
+
306dfcc
+	if (setup == 1)
306dfcc
+		return 0;
306dfcc
+
306dfcc
+	return 1;
306dfcc
+}
306dfcc
+
306dfcc
 /*
306dfcc
  * Because the x86 boot code expects to be passed a boot_params we
306dfcc
  * need to create one ourselves (usually the bootloader would create
47a1ebc
@@ -1143,6 +1173,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
306dfcc
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
306dfcc
 		goto fail;
306dfcc
 
306dfcc
+	boot_params->secure_boot = get_secure_boot(sys_table);
306dfcc
+
306dfcc
 	setup_graphics(boot_params);
306dfcc
 
f82b107
 	setup_efi_pci(boot_params);
f82b107
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
47a1ebc
index c15ddaf..85d7685 100644
f82b107
--- a/arch/x86/include/uapi/asm/bootparam.h
f82b107
+++ b/arch/x86/include/uapi/asm/bootparam.h
47a1ebc
@@ -131,7 +131,8 @@ struct boot_params {
306dfcc
 	__u8  eddbuf_entries;				/* 0x1e9 */
306dfcc
 	__u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
306dfcc
 	__u8  kbd_status;				/* 0x1eb */
47a1ebc
-	__u8  _pad5[3];					/* 0x1ec */
306dfcc
+	__u8  secure_boot;				/* 0x1ec */
47a1ebc
+	__u8  _pad5[2];					/* 0x1ed */
47a1ebc
 	/*
47a1ebc
 	 * The sentinel is set to a nonzero value (0xff) in header.S.
47a1ebc
 	 *
306dfcc
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
b1b2d34
index 8b24289..d74b441 100644
306dfcc
--- a/arch/x86/kernel/setup.c
306dfcc
+++ b/arch/x86/kernel/setup.c
b1b2d34
@@ -1042,6 +1042,13 @@ void __init setup_arch(char **cmdline_p)
306dfcc
 
306dfcc
 	io_delay_init();
306dfcc
 
a8e5aec
+	if (boot_params.secure_boot) {
b1b2d34
+#ifdef CONFIG_EFI
a8e5aec
+		set_bit(EFI_SECURE_BOOT, &x86_efi_facility);
b1b2d34
+#endif
306dfcc
+		secureboot_enable();
a8e5aec
+	}
306dfcc
+
306dfcc
 	/*
306dfcc
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
306dfcc
 	 */
306dfcc
diff --git a/include/linux/cred.h b/include/linux/cred.h
95c6648
index 04421e8..9e69542 100644
306dfcc
--- a/include/linux/cred.h
306dfcc
+++ b/include/linux/cred.h
95c6648
@@ -156,6 +156,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *);
306dfcc
 extern int set_create_files_as(struct cred *, struct inode *);
306dfcc
 extern void __init cred_init(void);
306dfcc
 
306dfcc
+extern void secureboot_enable(void);
306dfcc
+
306dfcc
 /*
306dfcc
  * check for validity of credentials
306dfcc
  */
f82b107
diff --git a/include/linux/efi.h b/include/linux/efi.h
a8e5aec
index 7a9498a..1ae16b6 100644
f82b107
--- a/include/linux/efi.h
f82b107
+++ b/include/linux/efi.h
a8e5aec
@@ -627,6 +627,7 @@ extern int __init efi_setup_pcdp_console(char *);
a8e5aec
 #define EFI_RUNTIME_SERVICES	3	/* Can we use runtime services? */
a8e5aec
 #define EFI_MEMMAP		4	/* Can we use EFI memory map? */
a8e5aec
 #define EFI_64BIT		5	/* Is the firmware 64-bit? */
a8e5aec
+#define EFI_SECURE_BOOT	6	/* Are we in Secure Boot mode? */
306dfcc
 
a8e5aec
 #ifdef CONFIG_EFI
a8e5aec
 # ifdef CONFIG_X86
306dfcc
-- 
b1b2d34
1.8.1.2
f0f4ff2
f0f4ff2
b1b2d34
From d4d1b3ad3e1a553c807b4ecafcbde4bf816e4db2 Mon Sep 17 00:00:00 2001
5e72ee3
From: Dave Howells <dhowells@redhat.com>
5e72ee3
Date: Tue, 23 Oct 2012 09:30:54 -0400
b1b2d34
Subject: [PATCH 05/19] Add EFI signature data types
f82b107
f82b107
Add the data types that are used for containing hashes, keys and certificates
f82b107
for cryptographic verification.
5e72ee3
5e72ee3
Signed-off-by: David Howells <dhowells@redhat.com>
5e72ee3
---
5e72ee3
 include/linux/efi.h | 20 ++++++++++++++++++++
5e72ee3
 1 file changed, 20 insertions(+)
5e72ee3
5e72ee3
diff --git a/include/linux/efi.h b/include/linux/efi.h
a8e5aec
index 1ae16b6..de7021d 100644
5e72ee3
--- a/include/linux/efi.h
5e72ee3
+++ b/include/linux/efi.h
f82b107
@@ -388,6 +388,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
5e72ee3
 #define EFI_FILE_SYSTEM_GUID \
5e72ee3
     EFI_GUID(  0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
5e72ee3
 
5e72ee3
+#define EFI_CERT_SHA256_GUID \
5e72ee3
+    EFI_GUID(  0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 )
5e72ee3
+
5e72ee3
+#define EFI_CERT_X509_GUID \
5e72ee3
+    EFI_GUID(  0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
5e72ee3
+
5e72ee3
 typedef struct {
5e72ee3
 	efi_guid_t guid;
5e72ee3
 	u64 table;
f82b107
@@ -523,6 +529,20 @@ typedef struct {
5e72ee3
 
5e72ee3
 #define EFI_INVALID_TABLE_ADDR		(~0UL)
5e72ee3
 
5e72ee3
+typedef struct  {
5e72ee3
+	efi_guid_t signature_owner;
5e72ee3
+	u8 signature_data[];
5e72ee3
+} efi_signature_data_t;
5e72ee3
+
5e72ee3
+typedef struct {
5e72ee3
+	efi_guid_t signature_type;
5e72ee3
+	u32 signature_list_size;
5e72ee3
+	u32 signature_header_size;
5e72ee3
+	u32 signature_size;
5e72ee3
+	u8 signature_header[];
5e72ee3
+	/* efi_signature_data_t signatures[][] */
5e72ee3
+} efi_signature_list_t;
5e72ee3
+
5e72ee3
 /*
5e72ee3
  * All runtime access to EFI goes through this structure:
5e72ee3
  */
5e72ee3
-- 
b1b2d34
1.8.1.2
5e72ee3
5e72ee3
b1b2d34
From 3cffca89eadf7e0f0a266c370f8034f33723831a Mon Sep 17 00:00:00 2001
5e72ee3
From: Dave Howells <dhowells@redhat.com>
5e72ee3
Date: Tue, 23 Oct 2012 09:36:28 -0400
b1b2d34
Subject: [PATCH 06/19] Add an EFI signature blob parser and key loader.
f82b107
f82b107
X.509 certificates are loaded into the specified keyring as asymmetric type
f82b107
keys.
5e72ee3
5e72ee3
Signed-off-by: David Howells <dhowells@redhat.com>
5e72ee3
---
95c6648
 crypto/asymmetric_keys/Kconfig      |   8 +++
5e72ee3
 crypto/asymmetric_keys/Makefile     |   1 +
95c6648
 crypto/asymmetric_keys/efi_parser.c | 108 ++++++++++++++++++++++++++++++++++++
5e72ee3
 include/linux/efi.h                 |   4 ++
95c6648
 4 files changed, 121 insertions(+)
5e72ee3
 create mode 100644 crypto/asymmetric_keys/efi_parser.c
5e72ee3
5e72ee3
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
95c6648
index 6d2c2ea..ace9c30 100644
5e72ee3
--- a/crypto/asymmetric_keys/Kconfig
5e72ee3
+++ b/crypto/asymmetric_keys/Kconfig
95c6648
@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER
5e72ee3
 	  data and provides the ability to instantiate a crypto key from a
5e72ee3
 	  public key packet found inside the certificate.
5e72ee3
 
5e72ee3
+config EFI_SIGNATURE_LIST_PARSER
5e72ee3
+	bool "EFI signature list parser"
95c6648
+	depends on EFI
5e72ee3
+	select X509_CERTIFICATE_PARSER
5e72ee3
+	help
5e72ee3
+	  This option provides support for parsing EFI signature lists for
5e72ee3
+	  X.509 certificates and turning them into keys.
5e72ee3
+
5e72ee3
 endif # ASYMMETRIC_KEY_TYPE
5e72ee3
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
5e72ee3
index 0727204..cd8388e 100644
5e72ee3
--- a/crypto/asymmetric_keys/Makefile
5e72ee3
+++ b/crypto/asymmetric_keys/Makefile
5e72ee3
@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o
5e72ee3
 
5e72ee3
 obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
5e72ee3
 obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
5e72ee3
+obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o
5e72ee3
 
5e72ee3
 #
5e72ee3
 # X.509 Certificate handling
5e72ee3
diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c
5e72ee3
new file mode 100644
95c6648
index 0000000..636feb1
5e72ee3
--- /dev/null
5e72ee3
+++ b/crypto/asymmetric_keys/efi_parser.c
95c6648
@@ -0,0 +1,108 @@
5e72ee3
+/* EFI signature/key/certificate list parser
5e72ee3
+ *
5e72ee3
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
5e72ee3
+ * Written by David Howells (dhowells@redhat.com)
5e72ee3
+ *
5e72ee3
+ * This program is free software; you can redistribute it and/or
5e72ee3
+ * modify it under the terms of the GNU General Public Licence
5e72ee3
+ * as published by the Free Software Foundation; either version
5e72ee3
+ * 2 of the Licence, or (at your option) any later version.
5e72ee3
+ */
5e72ee3
+
5e72ee3
+#define pr_fmt(fmt) "EFI: "fmt
5e72ee3
+#include <linux/module.h>
5e72ee3
+#include <linux/printk.h>
5e72ee3
+#include <linux/err.h>
5e72ee3
+#include <linux/efi.h>
5e72ee3
+#include <keys/asymmetric-type.h>
5e72ee3
+
5e72ee3
+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID;
5e72ee3
+
5e72ee3
+/**
5e72ee3
+ * parse_efi_signature_list - Parse an EFI signature list for certificates
5e72ee3
+ * @data: The data blob to parse
5e72ee3
+ * @size: The size of the data blob
5e72ee3
+ * @keyring: The keyring to add extracted keys to
5e72ee3
+ */
5e72ee3
+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring)
5e72ee3
+{
5e72ee3
+	unsigned offs = 0;
5e72ee3
+	size_t lsize, esize, hsize, elsize;
5e72ee3
+
5e72ee3
+	pr_devel("-->%s(,%zu)\n", __func__, size);
5e72ee3
+
5e72ee3
+	while (size > 0) {
5e72ee3
+		efi_signature_list_t list;
5e72ee3
+		const efi_signature_data_t *elem;
5e72ee3
+		key_ref_t key;
5e72ee3
+
5e72ee3
+		if (size < sizeof(list))
5e72ee3
+			return -EBADMSG;
5e72ee3
+
5e72ee3
+		memcpy(&list, data, sizeof(list));
5e72ee3
+		pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
5e72ee3
+			 offs,
5e72ee3
+			 list.signature_type.b, list.signature_list_size,
5e72ee3
+			 list.signature_header_size, list.signature_size);
5e72ee3
+
5e72ee3
+		lsize = list.signature_list_size;
5e72ee3
+		hsize = list.signature_header_size;
5e72ee3
+		esize = list.signature_size;
5e72ee3
+		elsize = lsize - sizeof(list) - hsize;
5e72ee3
+
5e72ee3
+		if (lsize > size) {
5e72ee3
+			pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
5e72ee3
+				 __func__, offs);
5e72ee3
+			return -EBADMSG;
5e72ee3
+		}
5e72ee3
+		if (lsize < sizeof(list) ||
5e72ee3
+		    lsize - sizeof(list) < hsize ||
5e72ee3
+		    esize < sizeof(*elem) ||
5e72ee3
+		    elsize < esize ||
5e72ee3
+		    elsize % esize != 0) {
5e72ee3
+			pr_devel("- bad size combo @%x\n", offs);
f82b107
+			return -EBADMSG;
5e72ee3
+		}
5e72ee3
+
5e72ee3
+		if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) {
5e72ee3
+			data += lsize;
5e72ee3
+			size -= lsize;
5e72ee3
+			offs += lsize;
5e72ee3
+			continue;
5e72ee3
+		}
5e72ee3
+
5e72ee3
+		data += sizeof(list) + hsize;
5e72ee3
+		size -= sizeof(list) + hsize;
5e72ee3
+		offs += sizeof(list) + hsize;
5e72ee3
+
5e72ee3
+		for (; elsize > 0; elsize -= esize) {
5e72ee3
+			elem = data;
5e72ee3
+
5e72ee3
+			pr_devel("ELEM[%04x]\n", offs);
5e72ee3
+
5e72ee3
+			key = key_create_or_update(
5e72ee3
+				make_key_ref(keyring, 1),
5e72ee3
+				"asymmetric",
5e72ee3
+				NULL,
5e72ee3
+				&elem->signature_data,
5e72ee3
+				esize - sizeof(*elem),
5e72ee3
+				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
5e72ee3
+				KEY_USR_VIEW,
5e72ee3
+				KEY_ALLOC_NOT_IN_QUOTA);
5e72ee3
+
5e72ee3
+			if (IS_ERR(key))
5e72ee3
+				pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
5e72ee3
+				       PTR_ERR(key));
5e72ee3
+			else
95c6648
+				pr_notice("Loaded cert '%s' linked to '%s'\n",
95c6648
+					  key_ref_to_ptr(key)->description,
95c6648
+					  keyring->description);
5e72ee3
+
5e72ee3
+			data += esize;
5e72ee3
+			size -= esize;
5e72ee3
+			offs += esize;
5e72ee3
+		}
5e72ee3
+	}
5e72ee3
+
5e72ee3
+	return 0;
5e72ee3
+}
5e72ee3
diff --git a/include/linux/efi.h b/include/linux/efi.h
a8e5aec
index de7021d..64b3e55 100644
5e72ee3
--- a/include/linux/efi.h
5e72ee3
+++ b/include/linux/efi.h
f82b107
@@ -612,6 +612,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime);
5e72ee3
 extern void efi_reserve_boot_services(void);
5e72ee3
 extern struct efi_memory_map memmap;
5e72ee3
 
5e72ee3
+struct key;
5e72ee3
+extern int __init parse_efi_signature_list(const void *data, size_t size,
5e72ee3
+					   struct key *keyring);
5e72ee3
+
f82b107
 /**
f82b107
  * efi_range_is_wc - check the WC bit on an address range
f82b107
  * @start: starting kvirt address
f82b107
-- 
b1b2d34
1.8.1.2
f82b107
f82b107
b1b2d34
From 89ea7424726ae4f7265ab84e703cf2da77acda57 Mon Sep 17 00:00:00 2001
f82b107
From: Josh Boyer <jwboyer@redhat.com>
f82b107
Date: Fri, 26 Oct 2012 12:36:24 -0400
b1b2d34
Subject: [PATCH 07/19] MODSIGN: Add module certificate blacklist keyring
f82b107
f82b107
This adds an additional keyring that is used to store certificates that
f82b107
are blacklisted.  This keyring is searched first when loading signed modules
f82b107
and if the module's certificate is found, it will refuse to load.  This is
f82b107
useful in cases where third party certificates are used for module signing.
f82b107
f82b107
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
f82b107
---
f82b107
 init/Kconfig             |  8 ++++++++
f82b107
 kernel/modsign_pubkey.c  | 14 ++++++++++++++
f82b107
 kernel/module-internal.h |  3 +++
95c6648
 kernel/module_signing.c  | 12 ++++++++++++
95c6648
 4 files changed, 37 insertions(+)
f82b107
f82b107
diff --git a/init/Kconfig b/init/Kconfig
a8e5aec
index be8b7f5..d972b77 100644
f82b107
--- a/init/Kconfig
f82b107
+++ b/init/Kconfig
f82b107
@@ -1665,6 +1665,14 @@ config MODULE_SIG_FORCE
f82b107
 	  Reject unsigned modules or signed modules for which we don't have a
f82b107
 	  key.  Without this, such modules will simply taint the kernel.
f82b107
 
f82b107
+config MODULE_SIG_BLACKLIST
f82b107
+	bool "Support for blacklisting module signature certificates"
f82b107
+	depends on MODULE_SIG
f82b107
+	help
f82b107
+	  This adds support for keeping a blacklist of certificates that
f82b107
+	  should not pass module signature verification.  If a module is
f82b107
+	  signed with something in this keyring, the load will be rejected.
f82b107
+
f82b107
 choice
f82b107
 	prompt "Which hash algorithm should modules be signed with?"
f82b107
 	depends on MODULE_SIG
f82b107
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
f82b107
index 2b6e699..4cd408d 100644
f82b107
--- a/kernel/modsign_pubkey.c
f82b107
+++ b/kernel/modsign_pubkey.c
f82b107
@@ -17,6 +17,9 @@
f82b107
 #include "module-internal.h"
f82b107
 
f82b107
 struct key *modsign_keyring;
f82b107
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
f82b107
+struct key *modsign_blacklist;
f82b107
+#endif
f82b107
 
f82b107
 extern __initdata const u8 modsign_certificate_list[];
f82b107
 extern __initdata const u8 modsign_certificate_list_end[];
f82b107
@@ -43,6 +46,17 @@ static __init int module_verify_init(void)
f82b107
 	if (IS_ERR(modsign_keyring))
f82b107
 		panic("Can't allocate module signing keyring\n");
f82b107
 
f82b107
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
f82b107
+	modsign_blacklist = keyring_alloc(".modsign_blacklist",
f82b107
+				    KUIDT_INIT(0), KGIDT_INIT(0),
f82b107
+				    current_cred(),
f82b107
+				    (KEY_POS_ALL & ~KEY_POS_SETATTR) |
f82b107
+				    KEY_USR_VIEW | KEY_USR_READ,
f82b107
+				    KEY_ALLOC_NOT_IN_QUOTA, NULL);
f82b107
+	if (IS_ERR(modsign_blacklist))
f82b107
+		panic("Can't allocate module signing blacklist keyring\n");
f82b107
+#endif
f82b107
+
f82b107
 	return 0;
f82b107
 }
f82b107
 
f82b107
diff --git a/kernel/module-internal.h b/kernel/module-internal.h
f82b107
index 24f9247..51a8380 100644
f82b107
--- a/kernel/module-internal.h
f82b107
+++ b/kernel/module-internal.h
f82b107
@@ -10,5 +10,8 @@
f82b107
  */
f82b107
 
f82b107
 extern struct key *modsign_keyring;
f82b107
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
f82b107
+extern struct key *modsign_blacklist;
f82b107
+#endif
f82b107
 
f82b107
 extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
f82b107
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
95c6648
index f2970bd..5423195 100644
f82b107
--- a/kernel/module_signing.c
f82b107
+++ b/kernel/module_signing.c
f82b107
@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
f82b107
 
f82b107
 	pr_debug("Look up: \"%s\"\n", id);
f82b107
 
f82b107
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
95c6648
+	key = keyring_search(make_key_ref(modsign_blacklist, 1),
f82b107
+				   &key_type_asymmetric, id);
95c6648
+	if (!IS_ERR(key)) {
f82b107
+		/* module is signed with a cert in the blacklist.  reject */
f82b107
+		pr_err("Module key '%s' is in blacklist\n", id);
95c6648
+		key_ref_put(key);
f82b107
+		kfree(id);
f82b107
+		return ERR_PTR(-EKEYREJECTED);
f82b107
+	}
f82b107
+#endif
f82b107
+
f82b107
 	key = keyring_search(make_key_ref(modsign_keyring, 1),
f82b107
 			     &key_type_asymmetric, id);
f82b107
 	if (IS_ERR(key))
f82b107
-- 
b1b2d34
1.8.1.2
f82b107
f82b107
b1b2d34
From 733a5c25b896d8d5fa0051825a671911b50cb47d Mon Sep 17 00:00:00 2001
f82b107
From: Josh Boyer <jwboyer@redhat.com>
f82b107
Date: Fri, 26 Oct 2012 12:42:16 -0400
b1b2d34
Subject: [PATCH 08/19] MODSIGN: Import certificates from UEFI Secure Boot
f82b107
f82b107
Secure Boot stores a list of allowed certificates in the 'db' variable.
f82b107
This imports those certificates into the module signing keyring.  This
f82b107
allows for a third party signing certificate to be used in conjunction
f82b107
with signed modules.  By importing the public certificate into the 'db'
f82b107
variable, a user can allow a module signed with that certificate to
f82b107
load.  The shim UEFI bootloader has a similar certificate list stored
f82b107
in the 'MokListRT' variable.  We import those as well.
f82b107
f82b107
In the opposite case, Secure Boot maintains a list of disallowed
f82b107
certificates in the 'dbx' variable.  We load those certificates into
f82b107
the newly introduced module blacklist keyring and forbid any module
f82b107
signed with those from loading.
f82b107
f82b107
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
f82b107
---
f82b107
 include/linux/efi.h   |  6 ++++
f82b107
 init/Kconfig          |  9 ++++++
f82b107
 kernel/Makefile       |  3 ++
f82b107
 kernel/modsign_uefi.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++
f82b107
 4 files changed, 108 insertions(+)
f82b107
 create mode 100644 kernel/modsign_uefi.c
f82b107
f82b107
diff --git a/include/linux/efi.h b/include/linux/efi.h
a8e5aec
index 64b3e55..76fe526 100644
f82b107
--- a/include/linux/efi.h
f82b107
+++ b/include/linux/efi.h
f82b107
@@ -394,6 +394,12 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
f82b107
 #define EFI_CERT_X509_GUID \
f82b107
     EFI_GUID(  0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
f82b107
 
f82b107
+#define EFI_IMAGE_SECURITY_DATABASE_GUID \
f82b107
+    EFI_GUID(  0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f )
f82b107
+
f82b107
+#define EFI_SHIM_LOCK_GUID \
f82b107
+    EFI_GUID(  0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 )
f82b107
+
f82b107
 typedef struct {
f82b107
 	efi_guid_t guid;
f82b107
 	u64 table;
f82b107
diff --git a/init/Kconfig b/init/Kconfig
a8e5aec
index d972b77..27e3a82 100644
f82b107
--- a/init/Kconfig
f82b107
+++ b/init/Kconfig
f82b107
@@ -1673,6 +1673,15 @@ config MODULE_SIG_BLACKLIST
f82b107
 	  should not pass module signature verification.  If a module is
f82b107
 	  signed with something in this keyring, the load will be rejected.
f82b107
 
f82b107
+config MODULE_SIG_UEFI
f82b107
+	bool "Allow modules signed with certs stored in UEFI"
f82b107
+	depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI
f82b107
+	select EFI_SIGNATURE_LIST_PARSER
f82b107
+	help
f82b107
+	  This will import certificates stored in UEFI and allow modules
f82b107
+	  signed with those to be loaded.  It will also disallow loading
f82b107
+	  of modules stored in the UEFI dbx variable.
f82b107
+
f82b107
 choice
f82b107
 	prompt "Which hash algorithm should modules be signed with?"
f82b107
 	depends on MODULE_SIG
f82b107
diff --git a/kernel/Makefile b/kernel/Makefile
f82b107
index 6c072b6..8848829 100644
f82b107
--- a/kernel/Makefile
f82b107
+++ b/kernel/Makefile
f82b107
@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
f82b107
 obj-$(CONFIG_UID16) += uid16.o
f82b107
 obj-$(CONFIG_MODULES) += module.o
f82b107
 obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o
f82b107
+obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o
f82b107
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
f82b107
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
f82b107
 obj-$(CONFIG_KEXEC) += kexec.o
f82b107
@@ -114,6 +115,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
f82b107
 
f82b107
 $(obj)/configs.o: $(obj)/config_data.h
f82b107
 
f82b107
+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar
f82b107
+
f82b107
 # config_data.h contains the same information as ikconfig.h but gzipped.
f82b107
 # Info from config_data can be extracted from /proc/config*
f82b107
 targets += config_data.gz
f82b107
diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c
f82b107
new file mode 100644
a8e5aec
index 0000000..b9237d7
f82b107
--- /dev/null
f82b107
+++ b/kernel/modsign_uefi.c
f82b107
@@ -0,0 +1,90 @@
f82b107
+#include <linux/kernel.h>
f82b107
+#include <linux/sched.h>
f82b107
+#include <linux/cred.h>
f82b107
+#include <linux/err.h>
f82b107
+#include <linux/efi.h>
f82b107
+#include <keys/asymmetric-type.h>
f82b107
+#include "module-internal.h"
f82b107
+
f82b107
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size)
f82b107
+{
f82b107
+	efi_status_t status;
f82b107
+	unsigned long lsize = 4;
f82b107
+	unsigned long tmpdb[4];
f82b107
+	void *db = NULL;
f82b107
+
f82b107
+	status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
f82b107
+	if (status != EFI_BUFFER_TOO_SMALL) {
f82b107
+		pr_err("Couldn't get size: 0x%lx\n", status);
f82b107
+		return NULL;
f82b107
+	}
f82b107
+
f82b107
+	db = kmalloc(lsize, GFP_KERNEL);
f82b107
+	if (!db) {
f82b107
+		pr_err("Couldn't allocate memory for uefi cert list\n");
f82b107
+		goto out;
f82b107
+	}
f82b107
+
f82b107
+	status = efi.get_variable(name, guid, NULL, &lsize, db);
f82b107
+	if (status != EFI_SUCCESS) {
f82b107
+		kfree(db);
f82b107
+		db = NULL;
f82b107
+		pr_err("Error reading db var: 0x%lx\n", status);
f82b107
+	}
f82b107
+out:
f82b107
+	*size = lsize;
f82b107
+	return db;
f82b107
+}
f82b107
+
f82b107
+/*
f82b107
+ *  * Load the certs contained in the UEFI databases
f82b107
+ *   */
f82b107
+static int __init load_uefi_certs(void)
f82b107
+{
f82b107
+	efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
f82b107
+	efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
f82b107
+	void *db = NULL, *dbx = NULL, *mok = NULL;
f82b107
+	unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
f82b107
+	int rc = 0;
f82b107
+
f82b107
+	/* Check if SB is enabled and just return if not */
a8e5aec
+	if (!efi_enabled(EFI_SECURE_BOOT))
f82b107
+		return 0;
f82b107
+
f82b107
+	/* Get db, MokListRT, and dbx.  They might not exist, so it isn't
f82b107
+	 * an error if we can't get them.
f82b107
+	 */
f82b107
+	db = get_cert_list(L"db", &secure_var, &dbsize);
f82b107
+	if (!db) {
f82b107
+		pr_err("MODSIGN: Couldn't get UEFI db list\n");
f82b107
+	} else {
f82b107
+		rc = parse_efi_signature_list(db, dbsize, modsign_keyring);
f82b107
+		if (rc)
f82b107
+			pr_err("Couldn't parse db signatures: %d\n", rc);
f82b107
+		kfree(db);
f82b107
+	}
f82b107
+
f82b107
+	mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
f82b107
+	if (!mok) {
f82b107
+		pr_info("MODSIGN: Couldn't get UEFI MokListRT\n");
f82b107
+	} else {
f82b107
+		rc = parse_efi_signature_list(mok, moksize, modsign_keyring);
f82b107
+		if (rc)
f82b107
+			pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
f82b107
+		kfree(mok);
f82b107
+	}
f82b107
+
f82b107
+	dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
f82b107
+	if (!dbx) {
f82b107
+		pr_info("MODSIGN: Couldn't get UEFI dbx list\n");
f82b107
+	} else {
f82b107
+		rc = parse_efi_signature_list(dbx, dbxsize,
f82b107
+			modsign_blacklist);
f82b107
+		if (rc)
f82b107
+			pr_err("Couldn't parse dbx signatures: %d\n", rc);
f82b107
+		kfree(dbx);
f82b107
+	}
f82b107
+
f82b107
+	return rc;
f82b107
+}
f82b107
+late_initcall(load_uefi_certs);
f82b107
-- 
b1b2d34
1.8.1.2
f82b107
f82b107
b1b2d34
From 16027d676baed34a9de804dac68d48096a688b39 Mon Sep 17 00:00:00 2001
f82b107
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:40:57 -0400
b1b2d34
Subject: [PATCH 09/19] PCI: Lock down BAR access in secure boot environments
f82b107
f82b107
Any hardware that can potentially generate DMA has to be locked down from
f82b107
userspace in order to avoid it being possible for an attacker to cause
f82b107
arbitrary kernel behaviour. Default to paranoid - in future we can
f82b107
potentially relax this for sufficiently IOMMU-isolated devices.
f82b107
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
f82b107
---
f82b107
 drivers/pci/pci-sysfs.c | 9 +++++++++
f82b107
 drivers/pci/proc.c      | 8 +++++++-
f82b107
 drivers/pci/syscall.c   | 2 +-
f82b107
 3 files changed, 17 insertions(+), 2 deletions(-)
f82b107
f82b107
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
f82b107
index 9c6e9bb..b966089 100644
f82b107
--- a/drivers/pci/pci-sysfs.c
f82b107
+++ b/drivers/pci/pci-sysfs.c
f82b107
@@ -622,6 +622,9 @@ pci_write_config(struct file* filp, struct kobject *kobj,
f82b107
 	loff_t init_off = off;
f82b107
 	u8 *data = (u8*) buf;
f82b107
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	if (off > dev->cfg_size)
f82b107
 		return 0;
f82b107
 	if (off + count > dev->cfg_size) {
f82b107
@@ -928,6 +931,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
f82b107
 	resource_size_t start, end;
f82b107
 	int i;
f82b107
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	for (i = 0; i < PCI_ROM_RESOURCE; i++)
f82b107
 		if (res == &pdev->resource[i])
f82b107
 			break;
f82b107
@@ -1035,6 +1041,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj,
f82b107
 		      struct bin_attribute *attr, char *buf,
f82b107
 		      loff_t off, size_t count)
f82b107
 {
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	return pci_resource_io(filp, kobj, attr, buf, off, count, true);
f82b107
 }
f82b107
 
f82b107
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
f82b107
index 9b8505c..35580bc 100644
f82b107
--- a/drivers/pci/proc.c
f82b107
+++ b/drivers/pci/proc.c
f82b107
@@ -139,6 +139,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
f82b107
 	int size = dp->size;
f82b107
 	int cnt;
f82b107
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	if (pos >= size)
f82b107
 		return 0;
f82b107
 	if (nbytes >= size)
f82b107
@@ -219,6 +222,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
f82b107
 #endif /* HAVE_PCI_MMAP */
f82b107
 	int ret = 0;
f82b107
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	switch (cmd) {
f82b107
 	case PCIIOC_CONTROLLER:
f82b107
 		ret = pci_domain_nr(dev->bus);
f82b107
@@ -259,7 +265,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
f82b107
 	struct pci_filp_private *fpriv = file->private_data;
f82b107
 	int i, ret;
f82b107
 
f82b107
-	if (!capable(CAP_SYS_RAWIO))
f82b107
+	if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL))
f82b107
 		return -EPERM;
f82b107
 
f82b107
 	/* Make sure the caller is mapping a real resource for this device */
f82b107
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
f82b107
index e1c1ec5..97e785f 100644
f82b107
--- a/drivers/pci/syscall.c
f82b107
+++ b/drivers/pci/syscall.c
f82b107
@@ -92,7 +92,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
f82b107
 	u32 dword;
f82b107
 	int err = 0;
f82b107
 
f82b107
-	if (!capable(CAP_SYS_ADMIN))
f82b107
+	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_COMPROMISE_KERNEL))
f82b107
 		return -EPERM;
f82b107
 
f82b107
 	dev = pci_get_bus_and_slot(bus, dfn);
f82b107
-- 
b1b2d34
1.8.1.2
f82b107
f82b107
b1b2d34
From 9ff1537bbe8c22bbf7f992027da43d4fe8da0860 Mon Sep 17 00:00:00 2001
f82b107
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:40:58 -0400
b1b2d34
Subject: [PATCH 10/19] x86: Lock down IO port access in secure boot
f82b107
 environments
f82b107
f82b107
IO port access would permit users to gain access to PCI configuration
f82b107
registers, which in turn (on a lot of hardware) give access to MMIO register
f82b107
space. This would potentially permit root to trigger arbitrary DMA, so lock
f82b107
it down by default.
f82b107
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
f82b107
---
f82b107
 arch/x86/kernel/ioport.c | 4 ++--
f82b107
 drivers/char/mem.c       | 3 +++
f82b107
 2 files changed, 5 insertions(+), 2 deletions(-)
f82b107
f82b107
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
f82b107
index 8c96897..a2578c4 100644
f82b107
--- a/arch/x86/kernel/ioport.c
f82b107
+++ b/arch/x86/kernel/ioport.c
f82b107
@@ -28,7 +28,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
f82b107
 
f82b107
 	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
f82b107
 		return -EINVAL;
f82b107
-	if (turn_on && !capable(CAP_SYS_RAWIO))
f82b107
+	if (turn_on && (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL)))
f82b107
 		return -EPERM;
f82b107
 
f82b107
 	/*
f82b107
@@ -102,7 +102,7 @@ long sys_iopl(unsigned int level, struct pt_regs *regs)
f82b107
 		return -EINVAL;
f82b107
 	/* Trying to gain more privileges? */
f82b107
 	if (level > old) {
f82b107
-		if (!capable(CAP_SYS_RAWIO))
f82b107
+		if (!capable(CAP_SYS_RAWIO) || !capable(CAP_COMPROMISE_KERNEL))
f82b107
 			return -EPERM;
f82b107
 	}
f82b107
 	regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
f82b107
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
f82b107
index c6fa3bc..fc28099 100644
f82b107
--- a/drivers/char/mem.c
f82b107
+++ b/drivers/char/mem.c
f82b107
@@ -597,6 +597,9 @@ static ssize_t write_port(struct file *file, const char __user *buf,
f82b107
 	unsigned long i = *ppos;
f82b107
 	const char __user * tmp = buf;
f82b107
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	if (!access_ok(VERIFY_READ, buf, count))
f82b107
 		return -EFAULT;
f82b107
 	while (count-- > 0 && i < 65536) {
5e72ee3
-- 
b1b2d34
1.8.1.2
4fc17ca
5e72ee3
b1b2d34
From 3b27408b1ced1ec83a3ce27f9d51161dbf7cea9a Mon Sep 17 00:00:00 2001
f82b107
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:40:59 -0400
b1b2d34
Subject: [PATCH 11/19] ACPI: Limit access to custom_method
5e72ee3
f82b107
It must be impossible for even root to get code executed in kernel context
f82b107
under a secure boot environment. custom_method effectively allows arbitrary
f82b107
access to system memory, so it needs to have a capability check here.
5e72ee3
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
5e72ee3
---
f82b107
 drivers/acpi/custom_method.c | 3 +++
f82b107
 1 file changed, 3 insertions(+)
5e72ee3
f82b107
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
f82b107
index 5d42c24..247d58b 100644
f82b107
--- a/drivers/acpi/custom_method.c
f82b107
+++ b/drivers/acpi/custom_method.c
f82b107
@@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
f82b107
 	struct acpi_table_header table;
f82b107
 	acpi_status status;
5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
5e72ee3
+
f82b107
 	if (!(*ppos)) {
f82b107
 		/* parse the table header to get the table length */
f82b107
 		if (count <= sizeof(struct acpi_table_header))
5e72ee3
-- 
b1b2d34
1.8.1.2
4fc17ca
5e72ee3
b1b2d34
From fb618a04089d454b7ade68c00a2b9c7dbac013f9 Mon Sep 17 00:00:00 2001
f82b107
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:41:00 -0400
b1b2d34
Subject: [PATCH 12/19] asus-wmi: Restrict debugfs interface
5e72ee3
f82b107
We have no way of validating what all of the Asus WMI methods do on a
f82b107
given machine, and there's a risk that some will allow hardware state to
f82b107
be manipulated in such a way that arbitrary code can be executed in the
f82b107
kernel. Add a capability check to prevent that.
5e72ee3
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
5e72ee3
---
f82b107
 drivers/platform/x86/asus-wmi.c | 9 +++++++++
f82b107
 1 file changed, 9 insertions(+)
5e72ee3
f82b107
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
f82b107
index f80ae4d..059195f 100644
f82b107
--- a/drivers/platform/x86/asus-wmi.c
f82b107
+++ b/drivers/platform/x86/asus-wmi.c
f82b107
@@ -1521,6 +1521,9 @@ static int show_dsts(struct seq_file *m, void *data)
f82b107
 	int err;
f82b107
 	u32 retval = -1;
5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
5e72ee3
+
f82b107
 	err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
5e72ee3
 
f82b107
 	if (err < 0)
f82b107
@@ -1537,6 +1540,9 @@ static int show_devs(struct seq_file *m, void *data)
f82b107
 	int err;
f82b107
 	u32 retval = -1;
5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
5e72ee3
+
f82b107
 	err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
f82b107
 				    &retval);
f82b107
 
f82b107
@@ -1561,6 +1567,9 @@ static int show_call(struct seq_file *m, void *data)
f82b107
 	union acpi_object *obj;
f82b107
 	acpi_status status;
f82b107
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
5e72ee3
+
f82b107
 	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
f82b107
 				     1, asus->debug.method_id,
f82b107
 				     &input, &output);
f82b107
-- 
b1b2d34
1.8.1.2
f82b107
f82b107
b1b2d34
From e515bbd5410d00835390fd8981aa9029e7b22b73 Mon Sep 17 00:00:00 2001
f82b107
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:41:01 -0400
b1b2d34
Subject: [PATCH 13/19] Restrict /dev/mem and /dev/kmem in secure boot setups
f82b107
f82b107
Allowing users to write to address space makes it possible for the kernel
f82b107
to be subverted. Restrict this when we need to protect the kernel.
f82b107
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
f82b107
---
f82b107
 drivers/char/mem.c | 6 ++++++
f82b107
 1 file changed, 6 insertions(+)
f82b107
f82b107
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
f82b107
index fc28099..b5df7a8 100644
f82b107
--- a/drivers/char/mem.c
f82b107
+++ b/drivers/char/mem.c
f82b107
@@ -158,6 +158,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
f82b107
 	unsigned long copied;
f82b107
 	void *ptr;
5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	if (!valid_phys_addr_range(p, count))
f82b107
 		return -EFAULT;
5e72ee3
 
f82b107
@@ -530,6 +533,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
f82b107
 	char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
f82b107
 	int err = 0;
5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	if (p < (unsigned long) high_memory) {
f82b107
 		unsigned long to_write = min_t(unsigned long, count,
f82b107
 					       (unsigned long)high_memory - p);
f82b107
-- 
b1b2d34
1.8.1.2
f82b107
f82b107
b1b2d34
From fe27dd192ef250abcbaba973a14d43b21d7be497 Mon Sep 17 00:00:00 2001
f82b107
From: Josh Boyer <jwboyer@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:41:04 -0400
b1b2d34
Subject: [PATCH 14/19] acpi: Ignore acpi_rsdp kernel parameter in a secure
f82b107
 boot environment
f82b107
f82b107
This option allows userspace to pass the RSDP address to the kernel.  This
f82b107
could potentially be used to circumvent the secure boot trust model.
f82b107
We ignore the setting if we don't have the CAP_COMPROMISE_KERNEL capability.
f82b107
f82b107
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
f82b107
---
f82b107
 drivers/acpi/osl.c | 2 +-
f82b107
 1 file changed, 1 insertion(+), 1 deletion(-)
f82b107
f82b107
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
a8e5aec
index bd22f86..88251d2 100644
f82b107
--- a/drivers/acpi/osl.c
f82b107
+++ b/drivers/acpi/osl.c
f82b107
@@ -246,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp);
f82b107
 acpi_physical_address __init acpi_os_get_root_pointer(void)
5e72ee3
 {
f82b107
 #ifdef CONFIG_KEXEC
f82b107
-	if (acpi_rsdp)
f82b107
+	if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL))
f82b107
 		return acpi_rsdp;
f82b107
 #endif
5e72ee3
 
f82b107
-- 
b1b2d34
1.8.1.2
f82b107
f82b107
b1b2d34
From c937b2c8e179bfdadb6617c0028f558e4d701e46 Mon Sep 17 00:00:00 2001
f82b107
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Tue, 4 Sep 2012 11:55:13 -0400
b1b2d34
Subject: [PATCH 15/19] kexec: Disable in a secure boot environment
f82b107
f82b107
kexec could be used as a vector for a malicious user to use a signed kernel
f82b107
to circumvent the secure boot trust model. In the long run we'll want to
f82b107
support signed kexec payloads, but for the moment we should just disable
f82b107
loading entirely in that situation.
f82b107
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
f82b107
---
f82b107
 kernel/kexec.c | 2 +-
f82b107
 1 file changed, 1 insertion(+), 1 deletion(-)
f82b107
f82b107
diff --git a/kernel/kexec.c b/kernel/kexec.c
f82b107
index 5e4bd78..dd464e0 100644
f82b107
--- a/kernel/kexec.c
f82b107
+++ b/kernel/kexec.c
f82b107
@@ -943,7 +943,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
f82b107
 	int result;
5e72ee3
 
f82b107
 	/* We only trust the superuser with rebooting the system. */
f82b107
-	if (!capable(CAP_SYS_BOOT))
f82b107
+	if (!capable(CAP_SYS_BOOT) || !capable(CAP_COMPROMISE_KERNEL))
f82b107
 		return -EPERM;
5e72ee3
 
f82b107
 	/*
5e72ee3
-- 
b1b2d34
1.8.1.2
5e72ee3
5e72ee3
b1b2d34
From f08e390045266d53543a55afa16ca4be5a1c6316 Mon Sep 17 00:00:00 2001
5e72ee3
From: Josh Boyer <jwboyer@redhat.com>
f82b107
Date: Fri, 5 Oct 2012 10:12:48 -0400
b1b2d34
Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot
f82b107
 environment
5e72ee3
f82b107
If a machine is booted into a Secure Boot environment, we need to
f82b107
protect the trust model.  This requires that all modules be signed
f82b107
with a key that is in the kernel's _modsign keyring.  The checks for
f82b107
this are already done via the 'sig_enforce' module parameter.  Make
f82b107
this visible within the kernel and force it to be true.
5e72ee3
5e72ee3
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
5e72ee3
---
f82b107
 kernel/cred.c   | 8 ++++++++
f82b107
 kernel/module.c | 4 ++--
f82b107
 2 files changed, 10 insertions(+), 2 deletions(-)
5e72ee3
f82b107
diff --git a/kernel/cred.c b/kernel/cred.c
f82b107
index c3f4e3e..c5554e0 100644
f82b107
--- a/kernel/cred.c
f82b107
+++ b/kernel/cred.c
f82b107
@@ -565,11 +565,19 @@ void __init cred_init(void)
f82b107
 				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
f82b107
 }
5e72ee3
 
f82b107
+#ifdef CONFIG_MODULE_SIG
f82b107
+extern bool sig_enforce;
f82b107
+#endif
4fc17ca
+
f82b107
 void __init secureboot_enable()
f82b107
 {
f82b107
 	pr_info("Secure boot enabled\n");
f82b107
 	cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL);
f82b107
 	cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL);
f82b107
+#ifdef CONFIG_MODULE_SIG
f82b107
+	/* Enable module signature enforcing */
f82b107
+	sig_enforce = true;
f82b107
+#endif
f82b107
 }
5e72ee3
 
f82b107
 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */
f82b107
diff --git a/kernel/module.c b/kernel/module.c
a8e5aec
index eab0827..93a16dc 100644
f82b107
--- a/kernel/module.c
f82b107
+++ b/kernel/module.c
f82b107
@@ -109,9 +109,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
5e72ee3
 
f82b107
 #ifdef CONFIG_MODULE_SIG
f82b107
 #ifdef CONFIG_MODULE_SIG_FORCE
f82b107
-static bool sig_enforce = true;
f82b107
+bool sig_enforce = true;
f82b107
 #else
f82b107
-static bool sig_enforce = false;
f82b107
+bool sig_enforce = false;
5e72ee3
 
f82b107
 static int param_set_bool_enable_only(const char *val,
f82b107
 				      const struct kernel_param *kp)
5e72ee3
-- 
b1b2d34
1.8.1.2
5e72ee3
b07f543
b1b2d34
From 54ba1eec5847d964b1d458a240b50271b9a356a4 Mon Sep 17 00:00:00 2001
5e72ee3
From: Josh Boyer <jwboyer@redhat.com>
5e72ee3
Date: Fri, 26 Oct 2012 14:02:09 -0400
b1b2d34
Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment
5e72ee3
5e72ee3
There is currently no way to verify the resume image when returning
5e72ee3
from hibernate.  This might compromise the secure boot trust model,
5e72ee3
so until we can work with signed hibernate images we disable it in
5e72ee3
a Secure Boot environment.
5e72ee3
5e72ee3
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
5e72ee3
---
de47636
 kernel/power/hibernate.c | 15 ++++++++++++++-
de47636
 kernel/power/main.c      |  7 ++++++-
b07f543
 kernel/power/user.c      |  3 +++
de47636
 3 files changed, 23 insertions(+), 2 deletions(-)
5e72ee3
5e72ee3
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
a8e5aec
index b26f5f1..7f63cb4 100644
5e72ee3
--- a/kernel/power/hibernate.c
5e72ee3
+++ b/kernel/power/hibernate.c
de47636
@@ -28,6 +28,7 @@
de47636
 #include <linux/syscore_ops.h>
de47636
 #include <linux/ctype.h>
de47636
 #include <linux/genhd.h>
de47636
+#include <linux/efi.h>
de47636
 
de47636
 #include "power.h"
de47636
 
de47636
@@ -632,6 +633,10 @@ int hibernate(void)
5e72ee3
 {
5e72ee3
 	int error;
5e72ee3
 
5e72ee3
+	if (!capable(CAP_COMPROMISE_KERNEL)) {
5e72ee3
+		return -EPERM;
5e72ee3
+	}
5e72ee3
+
5e72ee3
 	lock_system_sleep();
5e72ee3
 	/* The snapshot device should not be opened while we're running */
5e72ee3
 	if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
de47636
@@ -723,7 +728,7 @@ static int software_resume(void)
5e72ee3
 	/*
5e72ee3
 	 * If the user said "noresume".. bail out early.
5e72ee3
 	 */
5e72ee3
-	if (noresume)
5e72ee3
+	if (noresume || !capable(CAP_COMPROMISE_KERNEL))
5e72ee3
 		return 0;
5e72ee3
 
5e72ee3
 	/*
de47636
@@ -889,6 +894,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
5e72ee3
 	int i;
5e72ee3
 	char *start = buf;
5e72ee3
 
a8e5aec
+	if (efi_enabled(EFI_SECURE_BOOT)) {
5e72ee3
+		buf += sprintf(buf, "[%s]\n", "disabled");
5e72ee3
+		return buf-start;
5e72ee3
+	}
5e72ee3
+
5e72ee3
 	for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
5e72ee3
 		if (!hibernation_modes[i])
5e72ee3
 			continue;
de47636
@@ -923,6 +933,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
5e72ee3
 	char *p;
5e72ee3
 	int mode = HIBERNATION_INVALID;
5e72ee3
 
5e72ee3
+	if (!capable(CAP_COMPROMISE_KERNEL))
5e72ee3
+		return -EPERM;
5e72ee3
+
5e72ee3
 	p = memchr(buf, '\n', n);
5e72ee3
 	len = p ? p - buf : n;
5e72ee3
 
5e72ee3
diff --git a/kernel/power/main.c b/kernel/power/main.c
a8e5aec
index 1c16f91..4f915fc 100644
5e72ee3
--- a/kernel/power/main.c
5e72ee3
+++ b/kernel/power/main.c
de47636
@@ -15,6 +15,7 @@
de47636
 #include <linux/workqueue.h>
de47636
 #include <linux/debugfs.h>
de47636
 #include <linux/seq_file.h>
de47636
+#include <linux/efi.h>
de47636
 
de47636
 #include "power.h"
de47636
 
de47636
@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
5e72ee3
 	}
5e72ee3
 #endif
5e72ee3
 #ifdef CONFIG_HIBERNATION
5e72ee3
-	s += sprintf(s, "%s\n", "disk");
a8e5aec
+	if (!efi_enabled(EFI_SECURE_BOOT)) {
5e72ee3
+		s += sprintf(s, "%s\n", "disk");
de47636
+	} else {
de47636
+		s += sprintf(s, "\n");
5e72ee3
+	}
5e72ee3
 #else
5e72ee3
 	if (s != buf)
5e72ee3
 		/* convert the last space to a newline */
b07f543
diff --git a/kernel/power/user.c b/kernel/power/user.c
b07f543
index 4ed81e7..b11a0f4 100644
b07f543
--- a/kernel/power/user.c
b07f543
+++ b/kernel/power/user.c
b07f543
@@ -48,6 +48,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
b07f543
 	struct snapshot_data *data;
b07f543
 	int error;
b07f543
 
b07f543
+	if (!capable(CAP_COMPROMISE_KERNEL))
b07f543
+		return -EPERM;
b07f543
+
b07f543
 	lock_system_sleep();
b07f543
 
b07f543
 	if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
5e72ee3
-- 
b1b2d34
1.8.1.2
b1b2d34
5e72ee3
b1b2d34
From 686090054f6c3784218b318c7adcc3c1f0ca5069 Mon Sep 17 00:00:00 2001
b342019
From: Josh Boyer <jwboyer@redhat.com>
b342019
Date: Tue, 5 Feb 2013 19:25:05 -0500
b1b2d34
Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode
b342019
b342019
A user can manually tell the shim boot loader to disable validation of
b342019
images it loads.  When a user does this, it creates a UEFI variable called
b342019
MokSBState that does not have the runtime attribute set.  Given that the
b342019
user explicitly disabled validation, we can honor that and not enable
b342019
secure boot mode if that variable is set.
b342019
b342019
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
b342019
---
b342019
 arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++-
b342019
 1 file changed, 19 insertions(+), 1 deletion(-)
b342019
b342019
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
b342019
index 96bd86b..6e1331c 100644
b342019
--- a/arch/x86/boot/compressed/eboot.c
b342019
+++ b/arch/x86/boot/compressed/eboot.c
b342019
@@ -851,8 +851,9 @@ fail:
b342019
 
b342019
 static int get_secure_boot(efi_system_table_t *_table)
b342019
 {
b342019
-	u8 sb, setup;
b342019
+	u8 sb, setup, moksbstate;
b342019
 	unsigned long datasize = sizeof(sb);
b342019
+	u32 attr;
b342019
 	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
b342019
 	efi_status_t status;
b342019
 
b342019
@@ -876,6 +877,23 @@ static int get_secure_boot(efi_system_table_t *_table)
b342019
 	if (setup == 1)
b342019
 		return 0;
b342019
 
b342019
+	/* See if a user has put shim into insecure_mode.  If so, and the variable
b342019
+	 * doesn't have the runtime attribute set, we might as well honor that.
b342019
+	 */
b342019
+	var_guid = EFI_SHIM_LOCK_GUID;
b342019
+	status = efi_call_phys5(sys_table->runtime->get_variable,
b342019
+				L"MokSBState", &var_guid, &attr, &datasize,
b342019
+				&moksbstate);
b342019
+
b342019
+	/* If it fails, we don't care why.  Default to secure */
b342019
+	if (status != EFI_SUCCESS)
b342019
+		return 1;
b342019
+
b342019
+	if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) {
b342019
+		if (moksbstate == 1)
b342019
+			return 0;
b342019
+	}
b342019
+
b342019
 	return 1;
b342019
 }
b342019
 
b342019
-- 
b1b2d34
1.8.1.2
b1b2d34
b1b2d34
b1b2d34
From df607d2d5061b04f8a686cd74edd72c1f2836d8c Mon Sep 17 00:00:00 2001
b1b2d34
From: Kees Cook <keescook@chromium.org>
b1b2d34
Date: Fri, 8 Feb 2013 11:12:13 -0800
b1b2d34
Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot
79353e6
79353e6
Writing to MSRs should not be allowed unless CAP_COMPROMISE_KERNEL is
79353e6
set since it could lead to execution of arbitrary code in kernel mode.
79353e6
79353e6
Signed-off-by: Kees Cook <keescook@chromium.org>
79353e6
---
b1b2d34
 arch/x86/kernel/msr.c | 7 +++++++
79353e6
 1 file changed, 7 insertions(+)
79353e6
79353e6
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
79353e6
index 4929502..adaab3d 100644
79353e6
--- a/arch/x86/kernel/msr.c
79353e6
+++ b/arch/x86/kernel/msr.c
79353e6
@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
79353e6
 	int err = 0;
79353e6
 	ssize_t bytes = 0;
79353e6
 
79353e6
+	if (!capable(CAP_COMPROMISE_KERNEL))
79353e6
+		return -EPERM;
79353e6
+
79353e6
 	if (count % 8)
79353e6
 		return -EINVAL;	/* Invalid chunk size */
79353e6
 
79353e6
@@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)
79353e6
 			err = -EBADF;
79353e6
 			break;
79353e6
 		}
79353e6
+		if (!capable(CAP_COMPROMISE_KERNEL)) {
79353e6
+			err = -EPERM;
79353e6
+			break;
79353e6
+		}
79353e6
 		if (copy_from_user(&regs, uregs, sizeof regs)) {
79353e6
 			err = -EFAULT;
79353e6
 			break;
79353e6
-- 
b1b2d34
1.8.1.2
79353e6