Do a couple things here: - Split the mega-patches into individual patches. Should help with rebasing. - Make all patches 'git am' acceptable. There should be no functional or actual code differences from before
187 lines
5.9 KiB
Diff
187 lines
5.9 KiB
Diff
From f06dd05414175619d0083fe4236705755f4692bd Mon Sep 17 00:00:00 2001
|
|
From: Josh Boyer <jwboyer@fedoraproject.org>
|
|
Date: Fri, 26 Oct 2012 12:42:16 -0400
|
|
Subject: [PATCH] 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 system trusted 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 system 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 | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
4 files changed, 110 insertions(+)
|
|
create mode 100644 kernel/modsign_uefi.c
|
|
|
|
diff --git a/include/linux/efi.h b/include/linux/efi.h
|
|
index 41359e548bcb..db9e6118575e 100644
|
|
--- a/include/linux/efi.h
|
|
+++ b/include/linux/efi.h
|
|
@@ -587,6 +587,12 @@ void efi_native_runtime_setup(void);
|
|
#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 223b1a32bbcb..3bad458f1c68 100644
|
|
--- a/init/Kconfig
|
|
+++ b/init/Kconfig
|
|
@@ -1874,6 +1874,15 @@ 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_UEFI
|
|
+ bool "Allow modules signed with certs stored in UEFI"
|
|
+ depends on MODULE_SIG && SYSTEM_BLACKLIST_KEYRING && 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 dc5c77544fd6..95bdf3398880 100644
|
|
--- a/kernel/Makefile
|
|
+++ b/kernel/Makefile
|
|
@@ -45,6 +45,7 @@ obj-$(CONFIG_UID16) += uid16.o
|
|
obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
|
|
obj-$(CONFIG_MODULES) += module.o
|
|
obj-$(CONFIG_MODULE_SIG) += module_signing.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
|
|
@@ -99,6 +100,8 @@ obj-$(CONFIG_TORTURE_TEST) += torture.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 000000000000..94b0eb38a284
|
|
--- /dev/null
|
|
+++ b/kernel/modsign_uefi.c
|
|
@@ -0,0 +1,92 @@
|
|
+#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 <keys/system_keyring.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, system_trusted_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, system_trusted_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,
|
|
+ system_blacklist_keyring);
|
|
+ if (rc)
|
|
+ pr_err("Couldn't parse dbx signatures: %d\n", rc);
|
|
+ kfree(dbx);
|
|
+ }
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+late_initcall(load_uefi_certs);
|
|
--
|
|
1.9.3
|
|
|