Rework Secure Boot support to use the secure_modules approach
- Drop pekey
This commit is contained in:
parent
6db14169b3
commit
c9d9c5a37e
@ -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
18
kernel.spec
18
kernel.spec
@ -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
528
modsign-uefi.patch
Normal 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
123
sb-hibernate.patch
Normal 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
850
secure-modules.patch
Normal 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(®s, 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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user