Josh Boyer b1b2d34
From 0c5837031a4e996877930fd023a5877dd1d615ba Mon Sep 17 00:00:00 2001
Josh Boyer 306dfcc
From: Matthew Garrett <mjg@redhat.com>
Josh Boyer f0f4ff2
Date: Thu, 20 Sep 2012 10:40:56 -0400
Josh Boyer b1b2d34
Subject: [PATCH 01/19] Secure boot: Add new capability
Josh Boyer 306dfcc
Josh Boyer 306dfcc
Secure boot adds certain policy requirements, including that root must not
Josh Boyer 306dfcc
be able to do anything that could cause the kernel to execute arbitrary code.
Josh Boyer 306dfcc
The simplest way to handle this would seem to be to add a new capability
Josh Boyer 306dfcc
and gate various functionality on that. We'll then strip it from the initial
Josh Boyer 306dfcc
capability set if required.
Josh Boyer 306dfcc
Josh Boyer 306dfcc
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Josh Boyer 306dfcc
---
be7ac52
 include/uapi/linux/capability.h | 6 +++++-
Josh Boyer 306dfcc
 1 file changed, 5 insertions(+), 1 deletion(-)
Josh Boyer 306dfcc
Josh Boyer 4fc17ca
diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h
Josh Boyer 4fc17ca
index ba478fa..7109e65 100644
be7ac52
--- a/include/uapi/linux/capability.h
be7ac52
+++ b/include/uapi/linux/capability.h
Josh Boyer 4fc17ca
@@ -343,7 +343,11 @@ struct vfs_cap_data {
Josh Boyer 306dfcc
 
Josh Boyer 306dfcc
 #define CAP_BLOCK_SUSPEND    36
Josh Boyer 306dfcc
 
Josh Boyer 306dfcc
-#define CAP_LAST_CAP         CAP_BLOCK_SUSPEND
Josh Boyer f0f4ff2
+/* Allow things that trivially permit root to modify the running kernel */
Josh Boyer 306dfcc
+
Josh Boyer f0f4ff2
+#define CAP_COMPROMISE_KERNEL  37
Josh Boyer 306dfcc
+
Josh Boyer f0f4ff2
+#define CAP_LAST_CAP         CAP_COMPROMISE_KERNEL
Josh Boyer 306dfcc
 
Josh Boyer 306dfcc
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
Josh Boyer 306dfcc
 
Josh Boyer 306dfcc
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 306dfcc
Josh Boyer 306dfcc
Josh Boyer 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
Josh Boyer b1b2d34
Subject: [PATCH 02/19] SELinux: define mapping for new Secure Boot capability
Josh Boyer 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.
Josh Boyer 306dfcc
f82b107
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
Josh Boyer 306dfcc
---
f82b107
 security/selinux/include/classmap.h | 4 ++--
f82b107
 1 file changed, 2 insertions(+), 2 deletions(-)
Josh Boyer 306dfcc
f82b107
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
Josh Boyer 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",
Josh Boyer 47a1ebc
 	  { COMMON_SOCK_PERMS, "attach_queue", NULL } },
Josh Boyer 306dfcc
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 306dfcc
Josh Boyer 306dfcc
Josh Boyer 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
Josh Boyer b1b2d34
Subject: [PATCH 03/19] Secure boot: Add a dummy kernel parameter that will
f82b107
 switch on Secure Boot mode
Josh Boyer 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.
Josh Boyer 306dfcc
f82b107
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
Josh Boyer 306dfcc
---
f82b107
 Documentation/kernel-parameters.txt |  7 +++++++
f82b107
 kernel/cred.c                       | 17 +++++++++++++++++
f82b107
 2 files changed, 24 insertions(+)
Josh Boyer 306dfcc
f82b107
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
Josh Boyer 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.
Josh Boyer 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
 }
Josh Boyer 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
+}
Josh Boyer 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
Josh Boyer 306dfcc
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 306dfcc
Josh Boyer 306dfcc
Josh Boyer b1b2d34
From 49c76a665e8a09da48cbe271ea40266ca1a226c0 Mon Sep 17 00:00:00 2001
Josh Boyer 306dfcc
From: Matthew Garrett <mjg@redhat.com>
f82b107
Date: Thu, 20 Sep 2012 10:41:03 -0400
Josh Boyer b1b2d34
Subject: [PATCH 04/19] efi: Enable secure boot lockdown automatically when
f82b107
 enabled in firmware
Josh Boyer 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
Josh Boyer a8e5aec
down.  We also indicate the machine is in secure boot mode by adding the
Josh Boyer a8e5aec
EFI_SECURE_BOOT bit for use with efi_enabled.
Josh Boyer 306dfcc
Josh Boyer 306dfcc
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Josh Boyer a8e5aec
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
Josh Boyer 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 ++-
Josh Boyer b1b2d34
 arch/x86/kernel/setup.c               |  7 +++++++
f82b107
 include/linux/cred.h                  |  2 ++
Josh Boyer a8e5aec
 include/linux/efi.h                   |  1 +
Josh Boyer b1b2d34
 6 files changed, 46 insertions(+), 1 deletion(-)
Josh Boyer 306dfcc
f82b107
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
Josh Boyer 47a1ebc
index 199f453..ff651d3 100644
f82b107
--- a/Documentation/x86/zero-page.txt
f82b107
+++ b/Documentation/x86/zero-page.txt
Josh Boyer 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
Josh Boyer 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
Josh Boyer 47a1ebc
index f8fa411..96bd86b 100644
f82b107
--- a/arch/x86/boot/compressed/eboot.c
f82b107
+++ b/arch/x86/boot/compressed/eboot.c
Josh Boyer 47a1ebc
@@ -849,6 +849,36 @@ fail:
f82b107
 	return status;
f82b107
 }
Josh Boyer 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;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	status = efi_call_phys5(sys_table->runtime->get_variable,
Josh Boyer 306dfcc
+				L"SecureBoot", &var_guid, NULL, &datasize, &sb);
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	if (status != EFI_SUCCESS)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	if (sb == 0)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	status = efi_call_phys5(sys_table->runtime->get_variable,
Josh Boyer 306dfcc
+				L"SetupMode", &var_guid, NULL, &datasize,
Josh Boyer 306dfcc
+				&setup);
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	if (status != EFI_SUCCESS)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	if (setup == 1)
Josh Boyer 306dfcc
+		return 0;
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
+	return 1;
Josh Boyer 306dfcc
+}
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
 /*
Josh Boyer 306dfcc
  * Because the x86 boot code expects to be passed a boot_params we
Josh Boyer 306dfcc
  * need to create one ourselves (usually the bootloader would create
Josh Boyer 47a1ebc
@@ -1143,6 +1173,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
Josh Boyer 306dfcc
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
Josh Boyer 306dfcc
 		goto fail;
Josh Boyer 306dfcc
 
Josh Boyer 306dfcc
+	boot_params->secure_boot = get_secure_boot(sys_table);
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
 	setup_graphics(boot_params);
Josh Boyer 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
Josh Boyer 47a1ebc
index c15ddaf..85d7685 100644
f82b107
--- a/arch/x86/include/uapi/asm/bootparam.h
f82b107
+++ b/arch/x86/include/uapi/asm/bootparam.h
Josh Boyer 47a1ebc
@@ -131,7 +131,8 @@ struct boot_params {
Josh Boyer 306dfcc
 	__u8  eddbuf_entries;				/* 0x1e9 */
Josh Boyer 306dfcc
 	__u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
Josh Boyer 306dfcc
 	__u8  kbd_status;				/* 0x1eb */
Josh Boyer 47a1ebc
-	__u8  _pad5[3];					/* 0x1ec */
Josh Boyer 306dfcc
+	__u8  secure_boot;				/* 0x1ec */
Josh Boyer 47a1ebc
+	__u8  _pad5[2];					/* 0x1ed */
Josh Boyer 47a1ebc
 	/*
Josh Boyer 47a1ebc
 	 * The sentinel is set to a nonzero value (0xff) in header.S.
Josh Boyer 47a1ebc
 	 *
Josh Boyer 306dfcc
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
Josh Boyer b1b2d34
index 8b24289..d74b441 100644
Josh Boyer 306dfcc
--- a/arch/x86/kernel/setup.c
Josh Boyer 306dfcc
+++ b/arch/x86/kernel/setup.c
Josh Boyer b1b2d34
@@ -1042,6 +1042,13 @@ void __init setup_arch(char **cmdline_p)
Josh Boyer 306dfcc
 
Josh Boyer 306dfcc
 	io_delay_init();
Josh Boyer 306dfcc
 
Josh Boyer a8e5aec
+	if (boot_params.secure_boot) {
Josh Boyer b1b2d34
+#ifdef CONFIG_EFI
Josh Boyer a8e5aec
+		set_bit(EFI_SECURE_BOOT, &x86_efi_facility);
Josh Boyer b1b2d34
+#endif
Josh Boyer 306dfcc
+		secureboot_enable();
Josh Boyer a8e5aec
+	}
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
 	/*
Josh Boyer 306dfcc
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
Josh Boyer 306dfcc
 	 */
Josh Boyer 306dfcc
diff --git a/include/linux/cred.h b/include/linux/cred.h
Josh Boyer 95c6648
index 04421e8..9e69542 100644
Josh Boyer 306dfcc
--- a/include/linux/cred.h
Josh Boyer 306dfcc
+++ b/include/linux/cred.h
Josh Boyer 95c6648
@@ -156,6 +156,8 @@ extern int set_security_override_from_ctx(struct cred *, const char *);
Josh Boyer 306dfcc
 extern int set_create_files_as(struct cred *, struct inode *);
Josh Boyer 306dfcc
 extern void __init cred_init(void);
Josh Boyer 306dfcc
 
Josh Boyer 306dfcc
+extern void secureboot_enable(void);
Josh Boyer 306dfcc
+
Josh Boyer 306dfcc
 /*
Josh Boyer 306dfcc
  * check for validity of credentials
Josh Boyer 306dfcc
  */
f82b107
diff --git a/include/linux/efi.h b/include/linux/efi.h
Josh Boyer a8e5aec
index 7a9498a..1ae16b6 100644
f82b107
--- a/include/linux/efi.h
f82b107
+++ b/include/linux/efi.h
Josh Boyer a8e5aec
@@ -627,6 +627,7 @@ extern int __init efi_setup_pcdp_console(char *);
Josh Boyer a8e5aec
 #define EFI_RUNTIME_SERVICES	3	/* Can we use runtime services? */
Josh Boyer a8e5aec
 #define EFI_MEMMAP		4	/* Can we use EFI memory map? */
Josh Boyer a8e5aec
 #define EFI_64BIT		5	/* Is the firmware 64-bit? */
Josh Boyer a8e5aec
+#define EFI_SECURE_BOOT	6	/* Are we in Secure Boot mode? */
Josh Boyer 306dfcc
 
Josh Boyer a8e5aec
 #ifdef CONFIG_EFI
Josh Boyer a8e5aec
 # ifdef CONFIG_X86
Josh Boyer 306dfcc
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer f0f4ff2
Josh Boyer f0f4ff2
Josh Boyer b1b2d34
From d4d1b3ad3e1a553c807b4ecafcbde4bf816e4db2 Mon Sep 17 00:00:00 2001
Josh Boyer 5e72ee3
From: Dave Howells <dhowells@redhat.com>
Josh Boyer 5e72ee3
Date: Tue, 23 Oct 2012 09:30:54 -0400
Josh Boyer 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.
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer 5e72ee3
---
Josh Boyer 5e72ee3
 include/linux/efi.h | 20 ++++++++++++++++++++
Josh Boyer 5e72ee3
 1 file changed, 20 insertions(+)
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
diff --git a/include/linux/efi.h b/include/linux/efi.h
Josh Boyer a8e5aec
index 1ae16b6..de7021d 100644
Josh Boyer 5e72ee3
--- a/include/linux/efi.h
Josh Boyer 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,
Josh Boyer 5e72ee3
 #define EFI_FILE_SYSTEM_GUID \
Josh Boyer 5e72ee3
     EFI_GUID(  0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
+#define EFI_CERT_SHA256_GUID \
Josh Boyer 5e72ee3
+    EFI_GUID(  0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 )
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+#define EFI_CERT_X509_GUID \
Josh Boyer 5e72ee3
+    EFI_GUID(  0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
 typedef struct {
Josh Boyer 5e72ee3
 	efi_guid_t guid;
Josh Boyer 5e72ee3
 	u64 table;
f82b107
@@ -523,6 +529,20 @@ typedef struct {
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
 #define EFI_INVALID_TABLE_ADDR		(~0UL)
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
+typedef struct  {
Josh Boyer 5e72ee3
+	efi_guid_t signature_owner;
Josh Boyer 5e72ee3
+	u8 signature_data[];
Josh Boyer 5e72ee3
+} efi_signature_data_t;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+typedef struct {
Josh Boyer 5e72ee3
+	efi_guid_t signature_type;
Josh Boyer 5e72ee3
+	u32 signature_list_size;
Josh Boyer 5e72ee3
+	u32 signature_header_size;
Josh Boyer 5e72ee3
+	u32 signature_size;
Josh Boyer 5e72ee3
+	u8 signature_header[];
Josh Boyer 5e72ee3
+	/* efi_signature_data_t signatures[][] */
Josh Boyer 5e72ee3
+} efi_signature_list_t;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
 /*
Josh Boyer 5e72ee3
  * All runtime access to EFI goes through this structure:
Josh Boyer 5e72ee3
  */
Josh Boyer 5e72ee3
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
Josh Boyer b1b2d34
From 3cffca89eadf7e0f0a266c370f8034f33723831a Mon Sep 17 00:00:00 2001
Josh Boyer 5e72ee3
From: Dave Howells <dhowells@redhat.com>
Josh Boyer 5e72ee3
Date: Tue, 23 Oct 2012 09:36:28 -0400
Josh Boyer 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.
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
Signed-off-by: David Howells <dhowells@redhat.com>
Josh Boyer 5e72ee3
---
Josh Boyer 95c6648
 crypto/asymmetric_keys/Kconfig      |   8 +++
Josh Boyer 5e72ee3
 crypto/asymmetric_keys/Makefile     |   1 +
Josh Boyer 95c6648
 crypto/asymmetric_keys/efi_parser.c | 108 ++++++++++++++++++++++++++++++++++++
Josh Boyer 5e72ee3
 include/linux/efi.h                 |   4 ++
Josh Boyer 95c6648
 4 files changed, 121 insertions(+)
Josh Boyer 5e72ee3
 create mode 100644 crypto/asymmetric_keys/efi_parser.c
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
Josh Boyer 95c6648
index 6d2c2ea..ace9c30 100644
Josh Boyer 5e72ee3
--- a/crypto/asymmetric_keys/Kconfig
Josh Boyer 5e72ee3
+++ b/crypto/asymmetric_keys/Kconfig
Josh Boyer 95c6648
@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER
Josh Boyer 5e72ee3
 	  data and provides the ability to instantiate a crypto key from a
Josh Boyer 5e72ee3
 	  public key packet found inside the certificate.
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
+config EFI_SIGNATURE_LIST_PARSER
Josh Boyer 5e72ee3
+	bool "EFI signature list parser"
Josh Boyer 95c6648
+	depends on EFI
Josh Boyer 5e72ee3
+	select X509_CERTIFICATE_PARSER
Josh Boyer 5e72ee3
+	help
Josh Boyer 5e72ee3
+	  This option provides support for parsing EFI signature lists for
Josh Boyer 5e72ee3
+	  X.509 certificates and turning them into keys.
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
 endif # ASYMMETRIC_KEY_TYPE
Josh Boyer 5e72ee3
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
Josh Boyer 5e72ee3
index 0727204..cd8388e 100644
Josh Boyer 5e72ee3
--- a/crypto/asymmetric_keys/Makefile
Josh Boyer 5e72ee3
+++ b/crypto/asymmetric_keys/Makefile
Josh Boyer 5e72ee3
@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
 obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
Josh Boyer 5e72ee3
 obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
Josh Boyer 5e72ee3
+obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
 #
Josh Boyer 5e72ee3
 # X.509 Certificate handling
Josh Boyer 5e72ee3
diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c
Josh Boyer 5e72ee3
new file mode 100644
Josh Boyer 95c6648
index 0000000..636feb1
Josh Boyer 5e72ee3
--- /dev/null
Josh Boyer 5e72ee3
+++ b/crypto/asymmetric_keys/efi_parser.c
Josh Boyer 95c6648
@@ -0,0 +1,108 @@
Josh Boyer 5e72ee3
+/* EFI signature/key/certificate list parser
Josh Boyer 5e72ee3
+ *
Josh Boyer 5e72ee3
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
Josh Boyer 5e72ee3
+ * Written by David Howells (dhowells@redhat.com)
Josh Boyer 5e72ee3
+ *
Josh Boyer 5e72ee3
+ * This program is free software; you can redistribute it and/or
Josh Boyer 5e72ee3
+ * modify it under the terms of the GNU General Public Licence
Josh Boyer 5e72ee3
+ * as published by the Free Software Foundation; either version
Josh Boyer 5e72ee3
+ * 2 of the Licence, or (at your option) any later version.
Josh Boyer 5e72ee3
+ */
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+#define pr_fmt(fmt) "EFI: "fmt
Josh Boyer 5e72ee3
+#include <linux/module.h>
Josh Boyer 5e72ee3
+#include <linux/printk.h>
Josh Boyer 5e72ee3
+#include <linux/err.h>
Josh Boyer 5e72ee3
+#include <linux/efi.h>
Josh Boyer 5e72ee3
+#include <keys/asymmetric-type.h>
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+/**
Josh Boyer 5e72ee3
+ * parse_efi_signature_list - Parse an EFI signature list for certificates
Josh Boyer 5e72ee3
+ * @data: The data blob to parse
Josh Boyer 5e72ee3
+ * @size: The size of the data blob
Josh Boyer 5e72ee3
+ * @keyring: The keyring to add extracted keys to
Josh Boyer 5e72ee3
+ */
Josh Boyer 5e72ee3
+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring)
Josh Boyer 5e72ee3
+{
Josh Boyer 5e72ee3
+	unsigned offs = 0;
Josh Boyer 5e72ee3
+	size_t lsize, esize, hsize, elsize;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+	pr_devel("-->%s(,%zu)\n", __func__, size);
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+	while (size > 0) {
Josh Boyer 5e72ee3
+		efi_signature_list_t list;
Josh Boyer 5e72ee3
+		const efi_signature_data_t *elem;
Josh Boyer 5e72ee3
+		key_ref_t key;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+		if (size < sizeof(list))
Josh Boyer 5e72ee3
+			return -EBADMSG;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+		memcpy(&list, data, sizeof(list));
Josh Boyer 5e72ee3
+		pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
Josh Boyer 5e72ee3
+			 offs,
Josh Boyer 5e72ee3
+			 list.signature_type.b, list.signature_list_size,
Josh Boyer 5e72ee3
+			 list.signature_header_size, list.signature_size);
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+		lsize = list.signature_list_size;
Josh Boyer 5e72ee3
+		hsize = list.signature_header_size;
Josh Boyer 5e72ee3
+		esize = list.signature_size;
Josh Boyer 5e72ee3
+		elsize = lsize - sizeof(list) - hsize;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+		if (lsize > size) {
Josh Boyer 5e72ee3
+			pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
Josh Boyer 5e72ee3
+				 __func__, offs);
Josh Boyer 5e72ee3
+			return -EBADMSG;
Josh Boyer 5e72ee3
+		}
Josh Boyer 5e72ee3
+		if (lsize < sizeof(list) ||
Josh Boyer 5e72ee3
+		    lsize - sizeof(list) < hsize ||
Josh Boyer 5e72ee3
+		    esize < sizeof(*elem) ||
Josh Boyer 5e72ee3
+		    elsize < esize ||
Josh Boyer 5e72ee3
+		    elsize % esize != 0) {
Josh Boyer 5e72ee3
+			pr_devel("- bad size combo @%x\n", offs);
f82b107
+			return -EBADMSG;
Josh Boyer 5e72ee3
+		}
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+		if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) {
Josh Boyer 5e72ee3
+			data += lsize;
Josh Boyer 5e72ee3
+			size -= lsize;
Josh Boyer 5e72ee3
+			offs += lsize;
Josh Boyer 5e72ee3
+			continue;
Josh Boyer 5e72ee3
+		}
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+		data += sizeof(list) + hsize;
Josh Boyer 5e72ee3
+		size -= sizeof(list) + hsize;
Josh Boyer 5e72ee3
+		offs += sizeof(list) + hsize;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+		for (; elsize > 0; elsize -= esize) {
Josh Boyer 5e72ee3
+			elem = data;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+			pr_devel("ELEM[%04x]\n", offs);
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+			key = key_create_or_update(
Josh Boyer 5e72ee3
+				make_key_ref(keyring, 1),
Josh Boyer 5e72ee3
+				"asymmetric",
Josh Boyer 5e72ee3
+				NULL,
Josh Boyer 5e72ee3
+				&elem->signature_data,
Josh Boyer 5e72ee3
+				esize - sizeof(*elem),
Josh Boyer 5e72ee3
+				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
Josh Boyer 5e72ee3
+				KEY_USR_VIEW,
Josh Boyer 5e72ee3
+				KEY_ALLOC_NOT_IN_QUOTA);
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+			if (IS_ERR(key))
Josh Boyer 5e72ee3
+				pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
Josh Boyer 5e72ee3
+				       PTR_ERR(key));
Josh Boyer 5e72ee3
+			else
Josh Boyer 95c6648
+				pr_notice("Loaded cert '%s' linked to '%s'\n",
Josh Boyer 95c6648
+					  key_ref_to_ptr(key)->description,
Josh Boyer 95c6648
+					  keyring->description);
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+			data += esize;
Josh Boyer 5e72ee3
+			size -= esize;
Josh Boyer 5e72ee3
+			offs += esize;
Josh Boyer 5e72ee3
+		}
Josh Boyer 5e72ee3
+	}
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
+	return 0;
Josh Boyer 5e72ee3
+}
Josh Boyer 5e72ee3
diff --git a/include/linux/efi.h b/include/linux/efi.h
Josh Boyer a8e5aec
index de7021d..64b3e55 100644
Josh Boyer 5e72ee3
--- a/include/linux/efi.h
Josh Boyer 5e72ee3
+++ b/include/linux/efi.h
f82b107
@@ -612,6 +612,10 @@ extern int efi_set_rtc_mmss(unsigned long nowtime);
Josh Boyer 5e72ee3
 extern void efi_reserve_boot_services(void);
Josh Boyer 5e72ee3
 extern struct efi_memory_map memmap;
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
+struct key;
Josh Boyer 5e72ee3
+extern int __init parse_efi_signature_list(const void *data, size_t size,
Josh Boyer 5e72ee3
+					   struct key *keyring);
Josh Boyer 5e72ee3
+
f82b107
 /**
f82b107
  * efi_range_is_wc - check the WC bit on an address range
f82b107
  * @start: starting kvirt address
f82b107
-- 
Josh Boyer b1b2d34
1.8.1.2
f82b107
f82b107
Josh Boyer 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
Josh Boyer 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 +++
Josh Boyer 95c6648
 kernel/module_signing.c  | 12 ++++++++++++
Josh Boyer 95c6648
 4 files changed, 37 insertions(+)
f82b107
f82b107
diff --git a/init/Kconfig b/init/Kconfig
Josh Boyer 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
Josh Boyer 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
Josh Boyer 95c6648
+	key = keyring_search(make_key_ref(modsign_blacklist, 1),
f82b107
+				   &key_type_asymmetric, id);
Josh Boyer 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);
Josh Boyer 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
-- 
Josh Boyer b1b2d34
1.8.1.2
f82b107
f82b107
Josh Boyer 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
Josh Boyer 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
Josh Boyer 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
Josh Boyer 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
Josh Boyer 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 */
Josh Boyer 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
-- 
Josh Boyer b1b2d34
1.8.1.2
f82b107
f82b107
Josh Boyer 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
Josh Boyer 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
-- 
Josh Boyer b1b2d34
1.8.1.2
f82b107
f82b107
Josh Boyer 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
Josh Boyer 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) {
Josh Boyer 5e72ee3
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 4fc17ca
Josh Boyer 5e72ee3
Josh Boyer 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
Josh Boyer b1b2d34
Subject: [PATCH 11/19] ACPI: Limit access to custom_method
Josh Boyer 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.
Josh Boyer 5e72ee3
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Josh Boyer 5e72ee3
---
f82b107
 drivers/acpi/custom_method.c | 3 +++
f82b107
 1 file changed, 3 insertions(+)
Josh Boyer 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;
Josh Boyer 5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
Josh Boyer 5e72ee3
+
f82b107
 	if (!(*ppos)) {
f82b107
 		/* parse the table header to get the table length */
f82b107
 		if (count <= sizeof(struct acpi_table_header))
Josh Boyer 5e72ee3
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 4fc17ca
Josh Boyer 5e72ee3
Josh Boyer 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
Josh Boyer b1b2d34
Subject: [PATCH 12/19] asus-wmi: Restrict debugfs interface
Josh Boyer 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.
Josh Boyer 5e72ee3
f82b107
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Josh Boyer 5e72ee3
---
f82b107
 drivers/platform/x86/asus-wmi.c | 9 +++++++++
f82b107
 1 file changed, 9 insertions(+)
Josh Boyer 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;
Josh Boyer 5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
Josh Boyer 5e72ee3
+
f82b107
 	err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
Josh Boyer 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;
Josh Boyer 5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
Josh Boyer 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;
Josh Boyer 5e72ee3
+
f82b107
 	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
f82b107
 				     1, asus->debug.method_id,
f82b107
 				     &input, &output);
f82b107
-- 
Josh Boyer b1b2d34
1.8.1.2
f82b107
f82b107
Josh Boyer 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
Josh Boyer 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;
Josh Boyer 5e72ee3
 
f82b107
+	if (!capable(CAP_COMPROMISE_KERNEL))
f82b107
+		return -EPERM;
f82b107
+
f82b107
 	if (!valid_phys_addr_range(p, count))
f82b107
 		return -EFAULT;
Josh Boyer 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;
Josh Boyer 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
-- 
Josh Boyer b1b2d34
1.8.1.2
f82b107
f82b107
Josh Boyer 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
Josh Boyer 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
Josh Boyer 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)
Josh Boyer 5e72ee3
 {
f82b107
 #ifdef CONFIG_KEXEC
f82b107
-	if (acpi_rsdp)
f82b107
+	if (acpi_rsdp && capable(CAP_COMPROMISE_KERNEL))
f82b107
 		return acpi_rsdp;
f82b107
 #endif
Josh Boyer 5e72ee3
 
f82b107
-- 
Josh Boyer b1b2d34
1.8.1.2
f82b107
f82b107
Josh Boyer 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
Josh Boyer 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;
Josh Boyer 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;
Josh Boyer 5e72ee3
 
f82b107
 	/*
Josh Boyer 5e72ee3
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
Josh Boyer b1b2d34
From f08e390045266d53543a55afa16ca4be5a1c6316 Mon Sep 17 00:00:00 2001
Josh Boyer 5e72ee3
From: Josh Boyer <jwboyer@redhat.com>
f82b107
Date: Fri, 5 Oct 2012 10:12:48 -0400
Josh Boyer b1b2d34
Subject: [PATCH 16/19] MODSIGN: Always enforce module signing in a Secure Boot
f82b107
 environment
Josh Boyer 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.
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
Josh Boyer 5e72ee3
---
f82b107
 kernel/cred.c   | 8 ++++++++
f82b107
 kernel/module.c | 4 ++--
f82b107
 2 files changed, 10 insertions(+), 2 deletions(-)
Josh Boyer 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
 }
Josh Boyer 5e72ee3
 
f82b107
+#ifdef CONFIG_MODULE_SIG
f82b107
+extern bool sig_enforce;
f82b107
+#endif
Josh Boyer 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
 }
Josh Boyer 5e72ee3
 
f82b107
 /* Dummy Secure Boot enable option to fake out UEFI SB=1 */
f82b107
diff --git a/kernel/module.c b/kernel/module.c
Josh Boyer 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 */
Josh Boyer 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;
Josh Boyer 5e72ee3
 
f82b107
 static int param_set_bool_enable_only(const char *val,
f82b107
 				      const struct kernel_param *kp)
Josh Boyer 5e72ee3
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 5e72ee3
Josh Boyer b07f543
Josh Boyer b1b2d34
From 54ba1eec5847d964b1d458a240b50271b9a356a4 Mon Sep 17 00:00:00 2001
Josh Boyer 5e72ee3
From: Josh Boyer <jwboyer@redhat.com>
Josh Boyer 5e72ee3
Date: Fri, 26 Oct 2012 14:02:09 -0400
Josh Boyer b1b2d34
Subject: [PATCH 17/19] hibernate: Disable in a Secure Boot environment
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
There is currently no way to verify the resume image when returning
Josh Boyer 5e72ee3
from hibernate.  This might compromise the secure boot trust model,
Josh Boyer 5e72ee3
so until we can work with signed hibernate images we disable it in
Josh Boyer 5e72ee3
a Secure Boot environment.
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
Josh Boyer 5e72ee3
---
Josh Boyer de47636
 kernel/power/hibernate.c | 15 ++++++++++++++-
Josh Boyer de47636
 kernel/power/main.c      |  7 ++++++-
Josh Boyer b07f543
 kernel/power/user.c      |  3 +++
Josh Boyer de47636
 3 files changed, 23 insertions(+), 2 deletions(-)
Josh Boyer 5e72ee3
Josh Boyer 5e72ee3
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
Josh Boyer a8e5aec
index b26f5f1..7f63cb4 100644
Josh Boyer 5e72ee3
--- a/kernel/power/hibernate.c
Josh Boyer 5e72ee3
+++ b/kernel/power/hibernate.c
Josh Boyer de47636
@@ -28,6 +28,7 @@
Josh Boyer de47636
 #include <linux/syscore_ops.h>
Josh Boyer de47636
 #include <linux/ctype.h>
Josh Boyer de47636
 #include <linux/genhd.h>
Josh Boyer de47636
+#include <linux/efi.h>
Josh Boyer de47636
 
Josh Boyer de47636
 #include "power.h"
Josh Boyer de47636
 
Josh Boyer de47636
@@ -632,6 +633,10 @@ int hibernate(void)
Josh Boyer 5e72ee3
 {
Josh Boyer 5e72ee3
 	int error;
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
+	if (!capable(CAP_COMPROMISE_KERNEL)) {
Josh Boyer 5e72ee3
+		return -EPERM;
Josh Boyer 5e72ee3
+	}
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
 	lock_system_sleep();
Josh Boyer 5e72ee3
 	/* The snapshot device should not be opened while we're running */
Josh Boyer 5e72ee3
 	if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
Josh Boyer de47636
@@ -723,7 +728,7 @@ static int software_resume(void)
Josh Boyer 5e72ee3
 	/*
Josh Boyer 5e72ee3
 	 * If the user said "noresume".. bail out early.
Josh Boyer 5e72ee3
 	 */
Josh Boyer 5e72ee3
-	if (noresume)
Josh Boyer 5e72ee3
+	if (noresume || !capable(CAP_COMPROMISE_KERNEL))
Josh Boyer 5e72ee3
 		return 0;
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
 	/*
Josh Boyer de47636
@@ -889,6 +894,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
Josh Boyer 5e72ee3
 	int i;
Josh Boyer 5e72ee3
 	char *start = buf;
Josh Boyer 5e72ee3
 
Josh Boyer a8e5aec
+	if (efi_enabled(EFI_SECURE_BOOT)) {
Josh Boyer 5e72ee3
+		buf += sprintf(buf, "[%s]\n", "disabled");
Josh Boyer 5e72ee3
+		return buf-start;
Josh Boyer 5e72ee3
+	}
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
 	for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
Josh Boyer 5e72ee3
 		if (!hibernation_modes[i])
Josh Boyer 5e72ee3
 			continue;
Josh Boyer de47636
@@ -923,6 +933,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
Josh Boyer 5e72ee3
 	char *p;
Josh Boyer 5e72ee3
 	int mode = HIBERNATION_INVALID;
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
+	if (!capable(CAP_COMPROMISE_KERNEL))
Josh Boyer 5e72ee3
+		return -EPERM;
Josh Boyer 5e72ee3
+
Josh Boyer 5e72ee3
 	p = memchr(buf, '\n', n);
Josh Boyer 5e72ee3
 	len = p ? p - buf : n;
Josh Boyer 5e72ee3
 
Josh Boyer 5e72ee3
diff --git a/kernel/power/main.c b/kernel/power/main.c
Josh Boyer a8e5aec
index 1c16f91..4f915fc 100644
Josh Boyer 5e72ee3
--- a/kernel/power/main.c
Josh Boyer 5e72ee3
+++ b/kernel/power/main.c
Josh Boyer de47636
@@ -15,6 +15,7 @@
Josh Boyer de47636
 #include <linux/workqueue.h>
Josh Boyer de47636
 #include <linux/debugfs.h>
Josh Boyer de47636
 #include <linux/seq_file.h>
Josh Boyer de47636
+#include <linux/efi.h>
Josh Boyer de47636
 
Josh Boyer de47636
 #include "power.h"
Josh Boyer de47636
 
Josh Boyer de47636
@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
Josh Boyer 5e72ee3
 	}
Josh Boyer 5e72ee3
 #endif
Josh Boyer 5e72ee3
 #ifdef CONFIG_HIBERNATION
Josh Boyer 5e72ee3
-	s += sprintf(s, "%s\n", "disk");
Josh Boyer a8e5aec
+	if (!efi_enabled(EFI_SECURE_BOOT)) {
Josh Boyer 5e72ee3
+		s += sprintf(s, "%s\n", "disk");
Josh Boyer de47636
+	} else {
Josh Boyer de47636
+		s += sprintf(s, "\n");
Josh Boyer 5e72ee3
+	}
Josh Boyer 5e72ee3
 #else
Josh Boyer 5e72ee3
 	if (s != buf)
Josh Boyer 5e72ee3
 		/* convert the last space to a newline */
Josh Boyer b07f543
diff --git a/kernel/power/user.c b/kernel/power/user.c
Josh Boyer b07f543
index 4ed81e7..b11a0f4 100644
Josh Boyer b07f543
--- a/kernel/power/user.c
Josh Boyer b07f543
+++ b/kernel/power/user.c
Josh Boyer b07f543
@@ -48,6 +48,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
Josh Boyer b07f543
 	struct snapshot_data *data;
Josh Boyer b07f543
 	int error;
Josh Boyer b07f543
 
Josh Boyer b07f543
+	if (!capable(CAP_COMPROMISE_KERNEL))
Josh Boyer b07f543
+		return -EPERM;
Josh Boyer b07f543
+
Josh Boyer b07f543
 	lock_system_sleep();
Josh Boyer b07f543
 
Josh Boyer b07f543
 	if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
Josh Boyer 5e72ee3
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer b1b2d34
Josh Boyer 5e72ee3
Josh Boyer b1b2d34
From 686090054f6c3784218b318c7adcc3c1f0ca5069 Mon Sep 17 00:00:00 2001
Josh Boyer b342019
From: Josh Boyer <jwboyer@redhat.com>
Josh Boyer b342019
Date: Tue, 5 Feb 2013 19:25:05 -0500
Josh Boyer b1b2d34
Subject: [PATCH 18/19] efi: Disable secure boot if shim is in insecure mode
Josh Boyer b342019
Josh Boyer b342019
A user can manually tell the shim boot loader to disable validation of
Josh Boyer b342019
images it loads.  When a user does this, it creates a UEFI variable called
Josh Boyer b342019
MokSBState that does not have the runtime attribute set.  Given that the
Josh Boyer b342019
user explicitly disabled validation, we can honor that and not enable
Josh Boyer b342019
secure boot mode if that variable is set.
Josh Boyer b342019
Josh Boyer b342019
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
Josh Boyer b342019
---
Josh Boyer b342019
 arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++-
Josh Boyer b342019
 1 file changed, 19 insertions(+), 1 deletion(-)
Josh Boyer b342019
Josh Boyer b342019
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
Josh Boyer b342019
index 96bd86b..6e1331c 100644
Josh Boyer b342019
--- a/arch/x86/boot/compressed/eboot.c
Josh Boyer b342019
+++ b/arch/x86/boot/compressed/eboot.c
Josh Boyer b342019
@@ -851,8 +851,9 @@ fail:
Josh Boyer b342019
 
Josh Boyer b342019
 static int get_secure_boot(efi_system_table_t *_table)
Josh Boyer b342019
 {
Josh Boyer b342019
-	u8 sb, setup;
Josh Boyer b342019
+	u8 sb, setup, moksbstate;
Josh Boyer b342019
 	unsigned long datasize = sizeof(sb);
Josh Boyer b342019
+	u32 attr;
Josh Boyer b342019
 	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
Josh Boyer b342019
 	efi_status_t status;
Josh Boyer b342019
 
Josh Boyer b342019
@@ -876,6 +877,23 @@ static int get_secure_boot(efi_system_table_t *_table)
Josh Boyer b342019
 	if (setup == 1)
Josh Boyer b342019
 		return 0;
Josh Boyer b342019
 
Josh Boyer b342019
+	/* See if a user has put shim into insecure_mode.  If so, and the variable
Josh Boyer b342019
+	 * doesn't have the runtime attribute set, we might as well honor that.
Josh Boyer b342019
+	 */
Josh Boyer b342019
+	var_guid = EFI_SHIM_LOCK_GUID;
Josh Boyer b342019
+	status = efi_call_phys5(sys_table->runtime->get_variable,
Josh Boyer b342019
+				L"MokSBState", &var_guid, &attr, &datasize,
Josh Boyer b342019
+				&moksbstate);
Josh Boyer b342019
+
Josh Boyer b342019
+	/* If it fails, we don't care why.  Default to secure */
Josh Boyer b342019
+	if (status != EFI_SUCCESS)
Josh Boyer b342019
+		return 1;
Josh Boyer b342019
+
Josh Boyer b342019
+	if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) {
Josh Boyer b342019
+		if (moksbstate == 1)
Josh Boyer b342019
+			return 0;
Josh Boyer b342019
+	}
Josh Boyer b342019
+
Josh Boyer b342019
 	return 1;
Josh Boyer b342019
 }
Josh Boyer b342019
 
Josh Boyer b342019
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer b1b2d34
Josh Boyer b1b2d34
Josh Boyer b1b2d34
From df607d2d5061b04f8a686cd74edd72c1f2836d8c Mon Sep 17 00:00:00 2001
Josh Boyer b1b2d34
From: Kees Cook <keescook@chromium.org>
Josh Boyer b1b2d34
Date: Fri, 8 Feb 2013 11:12:13 -0800
Josh Boyer b1b2d34
Subject: [PATCH 19/19] x86: Lock down MSR writing in secure boot
Josh Boyer 79353e6
Josh Boyer 79353e6
Writing to MSRs should not be allowed unless CAP_COMPROMISE_KERNEL is
Josh Boyer 79353e6
set since it could lead to execution of arbitrary code in kernel mode.
Josh Boyer 79353e6
Josh Boyer 79353e6
Signed-off-by: Kees Cook <keescook@chromium.org>
Josh Boyer 79353e6
---
Josh Boyer b1b2d34
 arch/x86/kernel/msr.c | 7 +++++++
Josh Boyer 79353e6
 1 file changed, 7 insertions(+)
Josh Boyer 79353e6
Josh Boyer 79353e6
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
Josh Boyer 79353e6
index 4929502..adaab3d 100644
Josh Boyer 79353e6
--- a/arch/x86/kernel/msr.c
Josh Boyer 79353e6
+++ b/arch/x86/kernel/msr.c
Josh Boyer 79353e6
@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
Josh Boyer 79353e6
 	int err = 0;
Josh Boyer 79353e6
 	ssize_t bytes = 0;
Josh Boyer 79353e6
 
Josh Boyer 79353e6
+	if (!capable(CAP_COMPROMISE_KERNEL))
Josh Boyer 79353e6
+		return -EPERM;
Josh Boyer 79353e6
+
Josh Boyer 79353e6
 	if (count % 8)
Josh Boyer 79353e6
 		return -EINVAL;	/* Invalid chunk size */
Josh Boyer 79353e6
 
Josh Boyer 79353e6
@@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)
Josh Boyer 79353e6
 			err = -EBADF;
Josh Boyer 79353e6
 			break;
Josh Boyer 79353e6
 		}
Josh Boyer 79353e6
+		if (!capable(CAP_COMPROMISE_KERNEL)) {
Josh Boyer 79353e6
+			err = -EPERM;
Josh Boyer 79353e6
+			break;
Josh Boyer 79353e6
+		}
Josh Boyer 79353e6
 		if (copy_from_user(&regs, uregs, sizeof regs)) {
Josh Boyer 79353e6
 			err = -EFAULT;
Josh Boyer 79353e6
 			break;
Josh Boyer 79353e6
-- 
Josh Boyer b1b2d34
1.8.1.2
Josh Boyer 79353e6