Rework Secure Boot support to use the secure_modules approach

- Drop pekey
This commit is contained in:
Josh Boyer 2013-08-30 11:32:36 -04:00
parent 6db14169b3
commit c9d9c5a37e
8 changed files with 1556 additions and 7423 deletions

View File

@ -441,14 +441,14 @@ CONFIG_VMWARE_VMCI_VSOCKETS=m
CONFIG_XZ_DEC_X86=y
CONFIG_MPILIB=y
CONFIG_PKCS7_MESSAGE_PARSER=y
CONFIG_PE_FILE_PARSER=y
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_ALL=y
# CONFIG_MODULE_SIG_SHA1 is not set
CONFIG_MODULE_SIG_SHA256=y
# CONFIG_MODULE_SIG_FORCE is not set
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
CONFIG_MODULE_SIG_BLACKLIST=y
CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE=y
CONFIG_EFI_SIGNATURE_LIST_PARSER=y
CONFIG_MODULE_SIG_UEFI=y

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,7 @@ Summary: The Linux kernel
# For non-released -rc kernels, this will be appended after the rcX and
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
#
%global baserelease 1
%global baserelease 4
%global fedora_build %{baserelease}
# base_sublevel is the kernel version we're starting with and patching
@ -647,8 +647,10 @@ Patch800: crash-driver.patch
# crypto/
# secure boot
Patch1000: devel-pekey-secure-boot-20130820.patch
Patch1001: devel-sysrq-secure-boot-20130717.patch
Patch1000: secure-modules.patch
Patch1001: modsign-uefi.patch
Patch1002: sb-hibernate.patch
Patch1003: sysrq-secure-boot.patch
# virt + ksm patches
@ -1371,8 +1373,10 @@ ApplyPatch crash-driver.patch
# crypto/
# secure boot
ApplyPatch devel-pekey-secure-boot-20130820.patch
ApplyPatch devel-sysrq-secure-boot-20130717.patch
ApplyPatch secure-modules.patch
ApplyPatch modsign-uefi.patch
ApplyPatch sb-hibernate.patch
ApplyPatch sysrq-secure-boot.patch
# Assorted Virt Fixes
@ -2243,6 +2247,10 @@ fi
# ||----w |
# || ||
%changelog
* Fri Aug 30 2013 Josh Boyer <jwboyer@fedoraproject.org>
- Rework Secure Boot support to use the secure_modules approach
- Drop pekey
* Thu Aug 29 2013 Josh Boyer <jwboyer@fedoraproject.org> - 3.11.0-0.rc7.git2.1
- Linux v3.11-rc7-24-gc95389b
- Add mei patches that fix various s/r issues (rhbz 994824 989373)

528
modsign-uefi.patch Normal file
View File

@ -0,0 +1,528 @@
From cff9d37c9529fca5ff853f0050c7f0de0e819ea7 Mon Sep 17 00:00:00 2001
From: Dave Howells <dhowells@redhat.com>
Date: Tue, 23 Oct 2012 09:30:54 -0400
Subject: [PATCH 1/4] Add EFI signature data types
Add the data types that are used for containing hashes, keys and certificates
for cryptographic verification.
Signed-off-by: David Howells <dhowells@redhat.com>
---
include/linux/efi.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/include/linux/efi.h b/include/linux/efi.h
index eed2202..1da1b3c 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -389,6 +389,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
#define EFI_FILE_SYSTEM_GUID \
EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+#define EFI_CERT_SHA256_GUID \
+ EFI_GUID( 0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 )
+
+#define EFI_CERT_X509_GUID \
+ EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
+
typedef struct {
efi_guid_t guid;
u64 table;
@@ -524,6 +530,20 @@ typedef struct {
#define EFI_INVALID_TABLE_ADDR (~0UL)
+typedef struct {
+ efi_guid_t signature_owner;
+ u8 signature_data[];
+} efi_signature_data_t;
+
+typedef struct {
+ efi_guid_t signature_type;
+ u32 signature_list_size;
+ u32 signature_header_size;
+ u32 signature_size;
+ u8 signature_header[];
+ /* efi_signature_data_t signatures[][] */
+} efi_signature_list_t;
+
/*
* All runtime access to EFI goes through this structure:
*/
--
1.8.3.1
From 2ce1c1d0d7110c4b06d65e4c8506f6c54aa72628 Mon Sep 17 00:00:00 2001
From: Dave Howells <dhowells@redhat.com>
Date: Tue, 23 Oct 2012 09:36:28 -0400
Subject: [PATCH 2/4] Add an EFI signature blob parser and key loader.
X.509 certificates are loaded into the specified keyring as asymmetric type
keys.
Signed-off-by: David Howells <dhowells@redhat.com>
---
crypto/asymmetric_keys/Kconfig | 8 +++
crypto/asymmetric_keys/Makefile | 1 +
crypto/asymmetric_keys/efi_parser.c | 108 ++++++++++++++++++++++++++++++++++++
include/linux/efi.h | 4 ++
4 files changed, 121 insertions(+)
create mode 100644 crypto/asymmetric_keys/efi_parser.c
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 6d2c2ea..ace9c30 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER
data and provides the ability to instantiate a crypto key from a
public key packet found inside the certificate.
+config EFI_SIGNATURE_LIST_PARSER
+ bool "EFI signature list parser"
+ depends on EFI
+ select X509_CERTIFICATE_PARSER
+ help
+ This option provides support for parsing EFI signature lists for
+ X.509 certificates and turning them into keys.
+
endif # ASYMMETRIC_KEY_TYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index 0727204..cd8388e 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -8,6 +8,7 @@ asymmetric_keys-y := asymmetric_type.o signature.o
obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
+obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o
#
# X.509 Certificate handling
diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c
new file mode 100644
index 0000000..636feb1
--- /dev/null
+++ b/crypto/asymmetric_keys/efi_parser.c
@@ -0,0 +1,108 @@
+/* EFI signature/key/certificate list parser
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "EFI: "fmt
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/err.h>
+#include <linux/efi.h>
+#include <keys/asymmetric-type.h>
+
+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID;
+
+/**
+ * parse_efi_signature_list - Parse an EFI signature list for certificates
+ * @data: The data blob to parse
+ * @size: The size of the data blob
+ * @keyring: The keyring to add extracted keys to
+ */
+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring)
+{
+ unsigned offs = 0;
+ size_t lsize, esize, hsize, elsize;
+
+ pr_devel("-->%s(,%zu)\n", __func__, size);
+
+ while (size > 0) {
+ efi_signature_list_t list;
+ const efi_signature_data_t *elem;
+ key_ref_t key;
+
+ if (size < sizeof(list))
+ return -EBADMSG;
+
+ memcpy(&list, data, sizeof(list));
+ pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
+ offs,
+ list.signature_type.b, list.signature_list_size,
+ list.signature_header_size, list.signature_size);
+
+ lsize = list.signature_list_size;
+ hsize = list.signature_header_size;
+ esize = list.signature_size;
+ elsize = lsize - sizeof(list) - hsize;
+
+ if (lsize > size) {
+ pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
+ __func__, offs);
+ return -EBADMSG;
+ }
+ if (lsize < sizeof(list) ||
+ lsize - sizeof(list) < hsize ||
+ esize < sizeof(*elem) ||
+ elsize < esize ||
+ elsize % esize != 0) {
+ pr_devel("- bad size combo @%x\n", offs);
+ return -EBADMSG;
+ }
+
+ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) {
+ data += lsize;
+ size -= lsize;
+ offs += lsize;
+ continue;
+ }
+
+ data += sizeof(list) + hsize;
+ size -= sizeof(list) + hsize;
+ offs += sizeof(list) + hsize;
+
+ for (; elsize > 0; elsize -= esize) {
+ elem = data;
+
+ pr_devel("ELEM[%04x]\n", offs);
+
+ key = key_create_or_update(
+ make_key_ref(keyring, 1),
+ "asymmetric",
+ NULL,
+ &elem->signature_data,
+ esize - sizeof(*elem),
+ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW,
+ KEY_ALLOC_NOT_IN_QUOTA);
+
+ if (IS_ERR(key))
+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
+ PTR_ERR(key));
+ else
+ pr_notice("Loaded cert '%s' linked to '%s'\n",
+ key_ref_to_ptr(key)->description,
+ keyring->description);
+
+ data += esize;
+ size -= esize;
+ offs += esize;
+ }
+ }
+
+ return 0;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 1da1b3c..42a1d25 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -619,6 +619,10 @@ extern int efi_set_rtc_mmss(const struct timespec *now);
extern void efi_reserve_boot_services(void);
extern struct efi_memory_map memmap;
+struct key;
+extern int __init parse_efi_signature_list(const void *data, size_t size,
+ struct key *keyring);
+
/**
* efi_range_is_wc - check the WC bit on an address range
* @start: starting kvirt address
--
1.8.3.1
From 0e4e8acfd0932bbf6b02112218092c810d9469a5 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Fri, 26 Oct 2012 12:36:24 -0400
Subject: [PATCH 3/4] MODSIGN: Add module certificate blacklist keyring
This adds an additional keyring that is used to store certificates that
are blacklisted. This keyring is searched first when loading signed modules
and if the module's certificate is found, it will refuse to load. This is
useful in cases where third party certificates are used for module signing.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
---
init/Kconfig | 8 ++++++++
kernel/modsign_pubkey.c | 14 ++++++++++++++
kernel/module-internal.h | 3 +++
kernel/module_signing.c | 12 ++++++++++++
4 files changed, 37 insertions(+)
diff --git a/init/Kconfig b/init/Kconfig
index fed81b5..b4fa2d1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1772,6 +1772,14 @@ config MODULE_SIG_ALL
comment "Do not forget to sign required modules with scripts/sign-file"
depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL
+config MODULE_SIG_BLACKLIST
+ bool "Support for blacklisting module signature certificates"
+ depends on MODULE_SIG
+ help
+ This adds support for keeping a blacklist of certificates that
+ should not pass module signature verification. If a module is
+ signed with something in this keyring, the load will be rejected.
+
choice
prompt "Which hash algorithm should modules be signed with?"
depends on MODULE_SIG
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
index 2b6e699..4cd408d 100644
--- a/kernel/modsign_pubkey.c
+++ b/kernel/modsign_pubkey.c
@@ -17,6 +17,9 @@
#include "module-internal.h"
struct key *modsign_keyring;
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
+struct key *modsign_blacklist;
+#endif
extern __initdata const u8 modsign_certificate_list[];
extern __initdata const u8 modsign_certificate_list_end[];
@@ -43,6 +46,17 @@ static __init int module_verify_init(void)
if (IS_ERR(modsign_keyring))
panic("Can't allocate module signing keyring\n");
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
+ modsign_blacklist = keyring_alloc(".modsign_blacklist",
+ KUIDT_INIT(0), KGIDT_INIT(0),
+ current_cred(),
+ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW | KEY_USR_READ,
+ KEY_ALLOC_NOT_IN_QUOTA, NULL);
+ if (IS_ERR(modsign_blacklist))
+ panic("Can't allocate module signing blacklist keyring\n");
+#endif
+
return 0;
}
diff --git a/kernel/module-internal.h b/kernel/module-internal.h
index 24f9247..51a8380 100644
--- a/kernel/module-internal.h
+++ b/kernel/module-internal.h
@@ -10,5 +10,8 @@
*/
extern struct key *modsign_keyring;
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
+extern struct key *modsign_blacklist;
+#endif
extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index f2970bd..5423195 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -157,6 +157,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
pr_debug("Look up: \"%s\"\n", id);
+#ifdef CONFIG_MODULE_SIG_BLACKLIST
+ key = keyring_search(make_key_ref(modsign_blacklist, 1),
+ &key_type_asymmetric, id);
+ if (!IS_ERR(key)) {
+ /* module is signed with a cert in the blacklist. reject */
+ pr_err("Module key '%s' is in blacklist\n", id);
+ key_ref_put(key);
+ kfree(id);
+ return ERR_PTR(-EKEYREJECTED);
+ }
+#endif
+
key = keyring_search(make_key_ref(modsign_keyring, 1),
&key_type_asymmetric, id);
if (IS_ERR(key))
--
1.8.3.1
From c558b46370e850851a94795df67b7c57aecc48ea Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Fri, 26 Oct 2012 12:42:16 -0400
Subject: [PATCH 4/4] MODSIGN: Import certificates from UEFI Secure Boot
Secure Boot stores a list of allowed certificates in the 'db' variable.
This imports those certificates into the module signing keyring. This
allows for a third party signing certificate to be used in conjunction
with signed modules. By importing the public certificate into the 'db'
variable, a user can allow a module signed with that certificate to
load. The shim UEFI bootloader has a similar certificate list stored
in the 'MokListRT' variable. We import those as well.
In the opposite case, Secure Boot maintains a list of disallowed
certificates in the 'dbx' variable. We load those certificates into
the newly introduced module blacklist keyring and forbid any module
signed with those from loading.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
---
include/linux/efi.h | 6 ++++
init/Kconfig | 9 +++++
kernel/Makefile | 3 ++
kernel/modsign_uefi.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 109 insertions(+)
create mode 100644 kernel/modsign_uefi.c
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 42a1d25..d3e6036 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -395,6 +395,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
#define EFI_CERT_X509_GUID \
EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
+#define EFI_IMAGE_SECURITY_DATABASE_GUID \
+ EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f )
+
+#define EFI_SHIM_LOCK_GUID \
+ EFI_GUID( 0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 )
+
typedef struct {
efi_guid_t guid;
u64 table;
diff --git a/init/Kconfig b/init/Kconfig
index b4fa2d1..94ce526 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1780,6 +1780,15 @@ config MODULE_SIG_BLACKLIST
should not pass module signature verification. If a module is
signed with something in this keyring, the load will be rejected.
+config MODULE_SIG_UEFI
+ bool "Allow modules signed with certs stored in UEFI"
+ depends on MODULE_SIG && MODULE_SIG_BLACKLIST && EFI
+ select EFI_SIGNATURE_LIST_PARSER
+ help
+ This will import certificates stored in UEFI and allow modules
+ signed with those to be loaded. It will also disallow loading
+ of modules stored in the UEFI dbx variable.
+
choice
prompt "Which hash algorithm should modules be signed with?"
depends on MODULE_SIG
diff --git a/kernel/Makefile b/kernel/Makefile
index 35ef118..6ca1fea 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o
+obj-$(CONFIG_MODULE_SIG_UEFI) += modsign_uefi.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
@@ -114,6 +115,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
$(obj)/configs.o: $(obj)/config_data.h
+$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar
+
# config_data.h contains the same information as ikconfig.h but gzipped.
# Info from config_data can be extracted from /proc/config*
targets += config_data.gz
diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c
new file mode 100644
index 0000000..7eae5b4
--- /dev/null
+++ b/kernel/modsign_uefi.c
@@ -0,0 +1,91 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
+#include <linux/err.h>
+#include <linux/efi.h>
+#include <linux/slab.h>
+#include <keys/asymmetric-type.h>
+#include "module-internal.h"
+
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, unsigned long *size)
+{
+ efi_status_t status;
+ unsigned long lsize = 4;
+ unsigned long tmpdb[4];
+ void *db = NULL;
+
+ status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
+ if (status != EFI_BUFFER_TOO_SMALL) {
+ pr_err("Couldn't get size: 0x%lx\n", status);
+ return NULL;
+ }
+
+ db = kmalloc(lsize, GFP_KERNEL);
+ if (!db) {
+ pr_err("Couldn't allocate memory for uefi cert list\n");
+ goto out;
+ }
+
+ status = efi.get_variable(name, guid, NULL, &lsize, db);
+ if (status != EFI_SUCCESS) {
+ kfree(db);
+ db = NULL;
+ pr_err("Error reading db var: 0x%lx\n", status);
+ }
+out:
+ *size = lsize;
+ return db;
+}
+
+/*
+ * * Load the certs contained in the UEFI databases
+ * */
+static int __init load_uefi_certs(void)
+{
+ efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
+ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
+ void *db = NULL, *dbx = NULL, *mok = NULL;
+ unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
+ int rc = 0;
+
+ /* Check if SB is enabled and just return if not */
+ if (!efi_enabled(EFI_SECURE_BOOT))
+ return 0;
+
+ /* Get db, MokListRT, and dbx. They might not exist, so it isn't
+ * an error if we can't get them.
+ */
+ db = get_cert_list(L"db", &secure_var, &dbsize);
+ if (!db) {
+ pr_err("MODSIGN: Couldn't get UEFI db list\n");
+ } else {
+ rc = parse_efi_signature_list(db, dbsize, modsign_keyring);
+ if (rc)
+ pr_err("Couldn't parse db signatures: %d\n", rc);
+ kfree(db);
+ }
+
+ mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
+ if (!mok) {
+ pr_info("MODSIGN: Couldn't get UEFI MokListRT\n");
+ } else {
+ rc = parse_efi_signature_list(mok, moksize, modsign_keyring);
+ if (rc)
+ pr_err("Couldn't parse MokListRT signatures: %d\n", rc);
+ kfree(mok);
+ }
+
+ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
+ if (!dbx) {
+ pr_info("MODSIGN: Couldn't get UEFI dbx list\n");
+ } else {
+ rc = parse_efi_signature_list(dbx, dbxsize,
+ modsign_blacklist);
+ if (rc)
+ pr_err("Couldn't parse dbx signatures: %d\n", rc);
+ kfree(dbx);
+ }
+
+ return rc;
+}
+late_initcall(load_uefi_certs);
--
1.8.3.1

123
sb-hibernate.patch Normal file
View File

@ -0,0 +1,123 @@
From 4fe6d11d21b548d6e8272cc8cad5fcc6150ef081 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Fri, 26 Oct 2012 14:02:09 -0400
Subject: [PATCH] hibernate: Disable in a signed modules environment
There is currently no way to verify the resume image when returning
from hibernate. This might compromise the signed modules trust model,
so until we can work with signed hibernate images we disable it in
a secure modules environment.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.com>
---
kernel/power/hibernate.c | 16 +++++++++++++++-
kernel/power/main.c | 7 ++++++-
kernel/power/user.c | 5 +++++
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index b26f5f1..e65228b 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -28,6 +28,8 @@
#include <linux/syscore_ops.h>
#include <linux/ctype.h>
#include <linux/genhd.h>
+#include <linux/efi.h>
+#include <linux/module.h>
#include "power.h"
@@ -632,6 +634,10 @@ int hibernate(void)
{
int error;
+ if (secure_modules()) {
+ return -EPERM;
+ }
+
lock_system_sleep();
/* The snapshot device should not be opened while we're running */
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
@@ -723,7 +729,7 @@ static int software_resume(void)
/*
* If the user said "noresume".. bail out early.
*/
- if (noresume)
+ if (noresume || secure_modules())
return 0;
/*
@@ -889,6 +895,11 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
int i;
char *start = buf;
+ if (efi_enabled(EFI_SECURE_BOOT)) {
+ buf += sprintf(buf, "[%s]\n", "disabled");
+ return buf-start;
+ }
+
for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) {
if (!hibernation_modes[i])
continue;
@@ -923,6 +934,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
char *p;
int mode = HIBERNATION_INVALID;
+ if (secure_modules())
+ return -EPERM;
+
p = memchr(buf, '\n', n);
len = p ? p - buf : n;
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 1d1bf63..300f300 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -15,6 +15,7 @@
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/efi.h>
#include "power.h"
@@ -301,7 +302,11 @@ static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
}
#endif
#ifdef CONFIG_HIBERNATION
- s += sprintf(s, "%s\n", "disk");
+ if (!efi_enabled(EFI_SECURE_BOOT)) {
+ s += sprintf(s, "%s\n", "disk");
+ } else {
+ s += sprintf(s, "\n");
+ }
#else
if (s != buf)
/* convert the last space to a newline */
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 4ed81e7..b714ee6 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -24,6 +24,8 @@
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/freezer.h>
+#include <linux/efi.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
@@ -48,6 +50,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
struct snapshot_data *data;
int error;
+ if (secure_modules())
+ return -EPERM;
+
lock_system_sleep();
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
--
1.8.3.1

File diff suppressed because it is too large Load Diff

850
secure-modules.patch Normal file
View File

@ -0,0 +1,850 @@
From 17832506ee9b52bc8e00c2ec89b49257998171ed Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:02 -0400
Subject: [PATCH 01/13] Add secure_modules() call
Provide a single call to allow kernel code to determine whether the system
has been configured to either disable module loading entirely or to load
only modules signed with a trusted key.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
include/linux/module.h | 7 +++++++
kernel/module.c | 10 ++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/linux/module.h b/include/linux/module.h
index 46f1ea0..0c266b2 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -509,6 +509,8 @@ int unregister_module_notifier(struct notifier_block * nb);
extern void print_modules(void);
+extern bool secure_modules(void);
+
#else /* !CONFIG_MODULES... */
/* Given an address, look for it in the exception tables. */
@@ -619,6 +621,11 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
static inline void print_modules(void)
{
}
+
+static inline bool secure_modules(void)
+{
+ return false;
+}
#endif /* CONFIG_MODULES */
#ifdef CONFIG_SYSFS
diff --git a/kernel/module.c b/kernel/module.c
index 2069158..499ee57 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3852,3 +3852,13 @@ void module_layout(struct module *mod,
}
EXPORT_SYMBOL(module_layout);
#endif
+
+bool secure_modules(void)
+{
+#ifdef CONFIG_MODULE_SIG
+ return (sig_enforce || modules_disabled);
+#else
+ return modules_disabled;
+#endif
+}
+EXPORT_SYMBOL_GPL(secure_modules);
--
1.8.3.1
From e347503648ace6a4b71dfb566365f1aa19657746 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:03 -0400
Subject: [PATCH 02/13] PCI: Lock down BAR access when module security is
enabled
Any hardware that can potentially generate DMA has to be locked down from
userspace in order to avoid it being possible for an attacker to modify
kernel code, allowing them to circumvent disabled module loading or module
signing. Default to paranoid - in future we can potentially relax this for
sufficiently IOMMU-isolated devices.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
drivers/pci/pci-sysfs.c | 10 ++++++++++
drivers/pci/proc.c | 8 +++++++-
drivers/pci/syscall.c | 3 ++-
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index c0dbe1f..cd4e35f 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/vgaarb.h>
#include <linux/pm_runtime.h>
+#include <linux/module.h>
#include "pci.h"
static int sysfs_initialized; /* = 0 */
@@ -624,6 +625,9 @@ pci_write_config(struct file* filp, struct kobject *kobj,
loff_t init_off = off;
u8 *data = (u8*) buf;
+ if (secure_modules())
+ return -EPERM;
+
if (off > dev->cfg_size)
return 0;
if (off + count > dev->cfg_size) {
@@ -930,6 +934,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
resource_size_t start, end;
int i;
+ if (secure_modules())
+ return -EPERM;
+
for (i = 0; i < PCI_ROM_RESOURCE; i++)
if (res == &pdev->resource[i])
break;
@@ -1037,6 +1044,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
+ if (secure_modules())
+ return -EPERM;
+
return pci_resource_io(filp, kobj, attr, buf, off, count, true);
}
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index cdc7836..e3d498b 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -117,6 +117,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
int size = dev->cfg_size;
int cnt;
+ if (secure_modules())
+ return -EPERM;
+
if (pos >= size)
return 0;
if (nbytes >= size)
@@ -196,6 +199,9 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
#endif /* HAVE_PCI_MMAP */
int ret = 0;
+ if (secure_modules())
+ return -EPERM;
+
switch (cmd) {
case PCIIOC_CONTROLLER:
ret = pci_domain_nr(dev->bus);
@@ -234,7 +240,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
struct pci_filp_private *fpriv = file->private_data;
int i, ret;
- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) || secure_modules())
return -EPERM;
/* Make sure the caller is mapping a real resource for this device */
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index e1c1ec5..bffbf71 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/syscalls.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include "pci.h"
@@ -92,7 +93,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
u32 dword;
int err = 0;
- if (!capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN) || secure_modules())
return -EPERM;
dev = pci_get_bus_and_slot(bus, dfn);
--
1.8.3.1
From b846e3958d3f4ff875ec958efba8b681ccbae04e Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:04 -0400
Subject: [PATCH 03/13] x86: Lock down IO port access when module security is
enabled
IO port access would permit users to gain access to PCI configuration
registers, which in turn (on a lot of hardware) give access to MMIO register
space. This would potentially permit root to trigger arbitrary DMA, so lock
it down by default.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
arch/x86/kernel/ioport.c | 5 +++--
drivers/char/mem.c | 4 ++++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 4ddaf66..00b4403 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -15,6 +15,7 @@
#include <linux/thread_info.h>
#include <linux/syscalls.h>
#include <linux/bitmap.h>
+#include <linux/module.h>
#include <asm/syscalls.h>
/*
@@ -28,7 +29,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
return -EINVAL;
- if (turn_on && !capable(CAP_SYS_RAWIO))
+ if (turn_on && (!capable(CAP_SYS_RAWIO) || secure_modules()))
return -EPERM;
/*
@@ -103,7 +104,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
return -EINVAL;
/* Trying to gain more privileges? */
if (level > old) {
- if (!capable(CAP_SYS_RAWIO))
+ if (!capable(CAP_SYS_RAWIO) || secure_modules())
return -EPERM;
}
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index f895a8c..1af8664 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -28,6 +28,7 @@
#include <linux/export.h>
#include <linux/io.h>
#include <linux/aio.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
@@ -563,6 +564,9 @@ static ssize_t write_port(struct file *file, const char __user *buf,
unsigned long i = *ppos;
const char __user *tmp = buf;
+ if (secure_modules())
+ return -EPERM;
+
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
while (count-- > 0 && i < 65536) {
--
1.8.3.1
From 8c11e2cc989eece2d4978cfbc83f9b898f3cd1aa Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:05 -0400
Subject: [PATCH 04/13] ACPI: Limit access to custom_method
custom_method effectively allows arbitrary access to system memory, making
it possible for an attacker to circumvent restrictions on module loading.
Disable it if any such restrictions have been enabled.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
drivers/acpi/custom_method.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c
index 12b62f2..55a013f 100644
--- a/drivers/acpi/custom_method.c
+++ b/drivers/acpi/custom_method.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/debugfs.h>
+#include <linux/module.h>
#include <acpi/acpi_drivers.h>
#include "internal.h"
@@ -29,6 +30,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
struct acpi_table_header table;
acpi_status status;
+ if (secure_modules())
+ return -EPERM;
+
if (!(*ppos)) {
/* parse the table header to get the table length */
if (count <= sizeof(struct acpi_table_header))
--
1.8.3.1
From 968ccfb32df5d5c9673c57641ebf90b25c0df880 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:06 -0400
Subject: [PATCH 05/13] asus-wmi: Restrict debugfs interface when module
loading is restricted
We have no way of validating what all of the Asus WMI methods do on a
given machine, and there's a risk that some will allow hardware state to
be manipulated in such a way that arbitrary code can be executed in the
kernel, circumventing module loading restrictions. Prevent that if any of
these features are enabled.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
drivers/platform/x86/asus-wmi.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 19c313b..db18ef66 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -1618,6 +1618,9 @@ static int show_dsts(struct seq_file *m, void *data)
int err;
u32 retval = -1;
+ if (secure_modules())
+ return -EPERM;
+
err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
if (err < 0)
@@ -1634,6 +1637,9 @@ static int show_devs(struct seq_file *m, void *data)
int err;
u32 retval = -1;
+ if (secure_modules())
+ return -EPERM;
+
err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
&retval);
@@ -1658,6 +1664,9 @@ static int show_call(struct seq_file *m, void *data)
union acpi_object *obj;
acpi_status status;
+ if (secure_modules())
+ return -EPERM;
+
status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
1, asus->debug.method_id,
&input, &output);
--
1.8.3.1
From e492d0a80bb591c34391757f97fc5aa8eb198e4f Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:07 -0400
Subject: [PATCH 06/13] Restrict /dev/mem and /dev/kmem when module loading is
restricted
Allowing users to write to address space makes it possible for the kernel
to be subverted, avoiding module loading restrictions. Prevent this when
any restrictions have been imposed on loading modules.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
drivers/char/mem.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 1af8664..61406c8 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -159,6 +159,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
unsigned long copied;
void *ptr;
+ if (secure_modules())
+ return -EPERM;
+
if (!valid_phys_addr_range(p, count))
return -EFAULT;
@@ -497,6 +500,9 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
int err = 0;
+ if (secure_modules())
+ return -EPERM;
+
if (p < (unsigned long) high_memory) {
unsigned long to_write = min_t(unsigned long, count,
(unsigned long)high_memory - p);
--
1.8.3.1
From 145913d656bfe8216032b38a576ac150699521e5 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@redhat.com>
Date: Mon, 19 Aug 2013 13:26:08 -0400
Subject: [PATCH 07/13] acpi: Ignore acpi_rsdp kernel parameter when module
loading is restricted
This option allows userspace to pass the RSDP address to the kernel, which
makes it possible for a user to circumvent any restrictions imposed on
loading modules. Disable it in that case.
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
---
drivers/acpi/osl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 6ab2c35..e4c4410 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -45,6 +45,7 @@
#include <linux/list.h>
#include <linux/jiffies.h>
#include <linux/semaphore.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -245,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp);
acpi_physical_address __init acpi_os_get_root_pointer(void)
{
#ifdef CONFIG_KEXEC
- if (acpi_rsdp)
+ if (acpi_rsdp && !secure_modules())
return acpi_rsdp;
#endif
--
1.8.3.1
From 012ac79f54ab746114d8276d8858a3df18b10e22 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:10 -0400
Subject: [PATCH 08/13] x86: Restrict MSR access when module loading is
restricted
Writing to MSRs should not be allowed if module loading is restricted,
since it could lead to execution of arbitrary code in kernel mode. Based
on a patch by Kees Cook.
Cc: Kees Cook <keescook@chromium.org>
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
arch/x86/kernel/msr.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 88458fa..d08f7e3 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
int err = 0;
ssize_t bytes = 0;
+ if (secure_modules())
+ return -EPERM;
+
if (count % 8)
return -EINVAL; /* Invalid chunk size */
@@ -150,6 +153,10 @@ static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg)
err = -EBADF;
break;
}
+ if (secure_modules()) {
+ err = -EPERM;
+ break;
+ }
if (copy_from_user(&regs, uregs, sizeof regs)) {
err = -EFAULT;
break;
--
1.8.3.1
From a44d2968968fd667c8cbeba7c043f674d17e7ce7 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:09 -0400
Subject: [PATCH 09/13] kexec: Disable at runtime if the kernel enforces module
loading restrictions
kexec permits the loading and execution of arbitrary code in ring 0, which
is something that module signing enforcement is meant to prevent. It makes
sense to disable kexec in this situation.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
---
kernel/kexec.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 59f7b55..1a7690f 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -32,6 +32,7 @@
#include <linux/vmalloc.h>
#include <linux/swap.h>
#include <linux/syscore_ops.h>
+#include <linux/module.h>
#include <asm/page.h>
#include <asm/uaccess.h>
@@ -1645,6 +1646,9 @@ int kernel_kexec(void)
goto Unlock;
}
+ if (secure_modules())
+ return -EPERM;
+
#ifdef CONFIG_KEXEC_JUMP
if (kexec_image->preserve_context) {
lock_system_sleep();
--
1.8.3.1
From f8f879da5dcc060a990a3b660aa5f340429cc4ed Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Mon, 19 Aug 2013 13:26:11 -0400
Subject: [PATCH 10/13] Add option to automatically enforce module signatures
when in Secure Boot mode
UEFI Secure Boot provides a mechanism for ensuring that the firmware will
only load signed bootloaders and kernels. Certain use cases may also
require that all kernel modules also be signed. Add a configuration option
that enforces this automatically when enabled.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
---
Documentation/x86/zero-page.txt | 2 ++
arch/x86/Kconfig | 10 ++++++++++
arch/x86/boot/compressed/eboot.c | 33 +++++++++++++++++++++++++++++++++
arch/x86/include/asm/bootparam_utils.h | 8 ++++++--
arch/x86/include/uapi/asm/bootparam.h | 3 ++-
arch/x86/kernel/setup.c | 6 ++++++
include/linux/module.h | 6 ++++++
kernel/module.c | 7 +++++++
8 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
index 199f453..ec38acf 100644
--- a/Documentation/x86/zero-page.txt
+++ b/Documentation/x86/zero-page.txt
@@ -30,6 +30,8 @@ Offset Proto Name Meaning
1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below)
1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
(below)
+1EB/001 ALL kbd_status Numlock is enabled
+1EC/001 ALL secure_boot Secure boot is enabled in the firmware
1EF/001 ALL sentinel Used to detect broken bootloaders
290/040 ALL edd_mbr_sig_buffer EDD MBR signatures
2D0/A00 ALL e820_map E820 memory map table
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b32ebf9..6a6c19b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1581,6 +1581,16 @@ config EFI_STUB
See Documentation/x86/efi-stub.txt for more information.
+config EFI_SECURE_BOOT_SIG_ENFORCE
+ def_bool n
+ prompt "Force module signing when UEFI Secure Boot is enabled"
+ ---help---
+ UEFI Secure Boot provides a mechanism for ensuring that the
+ firmware will only load signed bootloaders and kernels. Certain
+ use cases may also require that all kernel modules also be signed.
+ Say Y here to automatically enable module signature enforcement
+ when a system boots with UEFI Secure Boot enabled.
+
config SECCOMP
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b7388a4..145294d 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -861,6 +861,37 @@ fail:
return status;
}
+static int get_secure_boot(efi_system_table_t *_table)
+{
+ u8 sb, setup;
+ unsigned long datasize = sizeof(sb);
+ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
+ efi_status_t status;
+
+ status = efi_call_phys5(sys_table->runtime->get_variable,
+ L"SecureBoot", &var_guid, NULL, &datasize, &sb);
+
+ if (status != EFI_SUCCESS)
+ return 0;
+
+ if (sb == 0)
+ return 0;
+
+
+ status = efi_call_phys5(sys_table->runtime->get_variable,
+ L"SetupMode", &var_guid, NULL, &datasize,
+ &setup);
+
+ if (status != EFI_SUCCESS)
+ return 0;
+
+ if (setup == 1)
+ return 0;
+
+ return 1;
+}
+
+
/*
* Because the x86 boot code expects to be passed a boot_params we
* need to create one ourselves (usually the bootloader would create
@@ -1169,6 +1200,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
+ boot_params->secure_boot = get_secure_boot(sys_table);
+
setup_graphics(boot_params);
setup_efi_pci(boot_params);
diff --git a/arch/x86/include/asm/bootparam_utils.h b/arch/x86/include/asm/bootparam_utils.h
index 4a8cb8d..25f9cf1 100644
--- a/arch/x86/include/asm/bootparam_utils.h
+++ b/arch/x86/include/asm/bootparam_utils.h
@@ -38,9 +38,13 @@ static void sanitize_boot_params(struct boot_params *boot_params)
memset(&boot_params->ext_ramdisk_image, 0,
(char *)&boot_params->efi_info -
(char *)&boot_params->ext_ramdisk_image);
- memset(&boot_params->kbd_status, 0,
+ memset(&boot_params->kbd_status, 0, sizeof(boot_params->kbd_status));
+ /* don't clear boot_params->secure_boot. we set that ourselves
+ * earlier.
+ */
+ memset(&boot_params->_pad5[0], 0,
(char *)&boot_params->hdr -
- (char *)&boot_params->kbd_status);
+ (char *)&boot_params->_pad5[0]);
memset(&boot_params->_pad7[0], 0,
(char *)&boot_params->edd_mbr_sig_buffer[0] -
(char *)&boot_params->_pad7[0]);
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index c15ddaf..d35da96 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -131,7 +131,8 @@ struct boot_params {
__u8 eddbuf_entries; /* 0x1e9 */
__u8 edd_mbr_sig_buf_entries; /* 0x1ea */
__u8 kbd_status; /* 0x1eb */
- __u8 _pad5[3]; /* 0x1ec */
+ __u8 secure_boot; /* 0x1ec */
+ __u8 _pad5[2]; /* 0x1ec */
/*
* The sentinel is set to a nonzero value (0xff) in header.S.
*
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index f8ec578..deeb7bc 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1129,6 +1129,12 @@ void __init setup_arch(char **cmdline_p)
io_delay_init();
+#ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE
+ if (boot_params.secure_boot) {
+ enforce_signed_modules();
+ }
+#endif
+
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
diff --git a/include/linux/module.h b/include/linux/module.h
index 0c266b2..5a6374a 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -184,6 +184,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long add);
struct notifier_block;
+#ifdef CONFIG_MODULE_SIG
+extern void enforce_signed_modules(void);
+#else
+static inline void enforce_signed_modules(void) {};
+#endif
+
#ifdef CONFIG_MODULES
extern int modules_disabled; /* for sysctl */
diff --git a/kernel/module.c b/kernel/module.c
index 499ee57..bc7c987 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3853,6 +3853,13 @@ void module_layout(struct module *mod,
EXPORT_SYMBOL(module_layout);
#endif
+#ifdef CONFIG_MODULE_SIG
+void enforce_signed_modules(void)
+{
+ sig_enforce = true;
+}
+#endif
+
bool secure_modules(void)
{
#ifdef CONFIG_MODULE_SIG
--
1.8.3.1
From b1604407fff69b17b598af03888a9efda0d58f2b Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@redhat.com>
Date: Tue, 5 Feb 2013 19:25:05 -0500
Subject: [PATCH 11/13] efi: Disable secure boot if shim is in insecure mode
A user can manually tell the shim boot loader to disable validation of
images it loads. When a user does this, it creates a UEFI variable called
MokSBState that does not have the runtime attribute set. Given that the
user explicitly disabled validation, we can honor that and not enable
secure boot mode if that variable is set.
Signed-off-by: Josh Boyer <jwboyer@redhat.com>
---
arch/x86/boot/compressed/eboot.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 145294d..545d4a6 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -863,8 +863,9 @@ fail:
static int get_secure_boot(efi_system_table_t *_table)
{
- u8 sb, setup;
+ u8 sb, setup, moksbstate;
unsigned long datasize = sizeof(sb);
+ u32 attr;
efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
efi_status_t status;
@@ -888,6 +889,23 @@ static int get_secure_boot(efi_system_table_t *_table)
if (setup == 1)
return 0;
+ /* See if a user has put shim into insecure_mode. If so, and the variable
+ * doesn't have the runtime attribute set, we might as well honor that.
+ */
+ var_guid = EFI_SHIM_LOCK_GUID;
+ status = efi_call_phys5(sys_table->runtime->get_variable,
+ L"MokSBState", &var_guid, &attr, &datasize,
+ &moksbstate);
+
+ /* If it fails, we don't care why. Default to secure */
+ if (status != EFI_SUCCESS)
+ return 1;
+
+ if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS)) {
+ if (moksbstate == 1)
+ return 0;
+ }
+
return 1;
}
--
1.8.3.1
From 4d8b5cab923a2df15e1f33b3f0511366f9f98756 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Tue, 27 Aug 2013 13:28:43 -0400
Subject: [PATCH 12/13] efi: Make EFI_SECURE_BOOT_SIG_ENFORCE depend on EFI
The functionality of the config option is dependent upon the platform being
UEFI based. Reflect this in the config deps.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
---
arch/x86/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6a6c19b..10498ec 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1582,7 +1582,8 @@ config EFI_STUB
See Documentation/x86/efi-stub.txt for more information.
config EFI_SECURE_BOOT_SIG_ENFORCE
- def_bool n
+ def_bool n
+ depends on EFI
prompt "Force module signing when UEFI Secure Boot is enabled"
---help---
UEFI Secure Boot provides a mechanism for ensuring that the
--
1.8.3.1
From a87ca6498b8a9f8e3c1d7e6ef7ef4e233ec8639d Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Tue, 27 Aug 2013 13:33:03 -0400
Subject: [PATCH 13/13] efi: Add EFI_SECURE_BOOT bit
UEFI machines can be booted in Secure Boot mode. Add a EFI_SECURE_BOOT bit
for use with efi_enabled.
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
---
arch/x86/kernel/setup.c | 2 ++
include/linux/efi.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index deeb7bc..08dc16e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1131,7 +1131,9 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE
if (boot_params.secure_boot) {
+ set_bit(EFI_SECURE_BOOT, &x86_efi_facility);
enforce_signed_modules();
+ pr_info("Secure boot enabled\n");
}
#endif
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5f8f176..eed2202 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -634,6 +634,7 @@ extern int __init efi_setup_pcdp_console(char *);
#define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */
#define EFI_MEMMAP 4 /* Can we use EFI memory map? */
#define EFI_64BIT 5 /* Is the firmware 64-bit? */
+#define EFI_SECURE_BOOT 6 /* Are we in Secure Boot mode? */
#ifdef CONFIG_EFI
# ifdef CONFIG_X86
--
1.8.3.1

View File

@ -1,5 +1,20 @@
From 71aac34ed679daa0bf772051eb40412b5bd95da3 Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@redhat.com>
Date: Fri, 30 Aug 2013 09:28:51 -0400
Subject: [PATCH] Add sysrq option to disable secure boot mode
---
arch/x86/kernel/setup.c | 35 +++++++++++++++++++++++++++++++++++
drivers/input/misc/uinput.c | 1 +
drivers/tty/sysrq.c | 19 +++++++++++++------
include/linux/input.h | 5 +++++
include/linux/sysrq.h | 8 +++++++-
kernel/debug/kdb/kdb_main.c | 2 +-
kernel/module.c | 4 ++--
7 files changed, 64 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 167ca34..2a06699 100644
index 08dc16e..6971f8e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -70,6 +70,11 @@
@ -14,53 +29,25 @@ index 167ca34..2a06699 100644
#include <video/edid.h>
#include <asm/mtrr.h>
@@ -1252,3 +1257,61 @@ void __init i386_reserve_resources(void)
@@ -1253,3 +1258,33 @@ void __init i386_reserve_resources(void)
}
#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_MODULE_SIG
+extern bool sig_enforce;
+#endif
+
+int sb_enabled;
+
+void __init secureboot_enable()
+{
+ pr_info("Secure boot enabled\n");
+ cap_lower(init_cred.cap_bset, CAP_COMPROMISE_KERNEL);
+ cap_lower(init_cred.cap_permitted, CAP_COMPROMISE_KERNEL);
+#ifdef CONFIG_MODULE_SIG
+ /* Enable module signature enforcing */
+ sig_enforce = true;
+#endif
+ sb_enabled = 1;
+}
+
+/* Dummy Secure Boot enable option to fake out UEFI SB=1 */
+static int __init secureboot_enable_opt(char *str)
+{
+ int sb_enable = !!simple_strtol(str, NULL, 0);
+ if (sb_enable)
+ secureboot_enable();
+ return 1;
+}
+__setup("secureboot_enable=", secureboot_enable_opt);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+extern int sb_enabled;
+static void sysrq_handle_secure_boot(int key)
+{
+ if (!sb_enabled)
+ if (!efi_enabled(EFI_SECURE_BOOT))
+ return;
+
+ pr_info("Secure boot disabled\n");
+ cap_raise(init_cred.cap_bset, CAP_COMPROMISE_KERNEL);
+ cap_raise(init_cred.cap_permitted, CAP_COMPROMISE_KERNEL);
+#ifdef CONFIG_MODULE_SIG
+ sig_enforce = fips_enabled;
+#endif
+ sb_enabled = 0;
+}
+static struct sysrq_key_op secure_boot_sysrq_op = {
+ .handler = sysrq_handle_secure_boot,
@ -70,7 +57,7 @@ index 167ca34..2a06699 100644
+};
+static int __init secure_boot_sysrq(void)
+{
+ if (sb_enabled)
+ if (efi_enabled(EFI_SECURE_BOOT))
+ register_sysrq_key('x', &secure_boot_sysrq_op);
+ return 0;
+}
@ -222,42 +209,6 @@ index 7faf933..87ae634 100644
int register_sysrq_key(int key, struct sysrq_key_op *op);
int unregister_sysrq_key(int key, struct sysrq_key_op *op);
struct sysrq_key_op *__sysrq_get_key_op(int key);
diff --git a/kernel/cred.c b/kernel/cred.c
index c5554e0..e0573a4 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -565,31 +565,6 @@ void __init cred_init(void)
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
}
-#ifdef CONFIG_MODULE_SIG
-extern bool sig_enforce;
-#endif
-
-void __init secureboot_enable()
-{
- pr_info("Secure boot enabled\n");
- cap_lower((&init_cred)->cap_bset, CAP_COMPROMISE_KERNEL);
- cap_lower((&init_cred)->cap_permitted, CAP_COMPROMISE_KERNEL);
-#ifdef CONFIG_MODULE_SIG
- /* Enable module signature enforcing */
- sig_enforce = true;
-#endif
-}
-
-/* Dummy Secure Boot enable option to fake out UEFI SB=1 */
-static int __init secureboot_enable_opt(char *str)
-{
- int sb_enable = !!simple_strtol(str, NULL, 0);
- if (sb_enable)
- secureboot_enable();
- return 1;
-}
-__setup("secureboot_enable=", secureboot_enable_opt);
-
/**
* prepare_kernel_cred - Prepare a set of credentials for a kernel service
* @daemon: A userspace daemon to be used as a reference
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index 00eb8f7..54fbbcc 100644
--- a/kernel/debug/kdb/kdb_main.c
@ -271,3 +222,22 @@ index 00eb8f7..54fbbcc 100644
kdb_trap_printk--;
return 0;
diff --git a/kernel/module.c b/kernel/module.c
index bc7c987..5e4e2c2 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -109,9 +109,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
#ifdef CONFIG_MODULE_SIG
#ifdef CONFIG_MODULE_SIG_FORCE
-static bool sig_enforce = true;
+bool sig_enforce = true;
#else
-static bool sig_enforce = false;
+bool sig_enforce = false;
static int param_set_bool_enable_only(const char *val,
const struct kernel_param *kp)
--
1.8.3.1