diff options
-rw-r--r-- | config-x86-generic | 3 | ||||
-rw-r--r-- | kernel.spec | 7 | ||||
-rw-r--r-- | keys-x509-improv.patch | 1580 | ||||
-rw-r--r-- | modsign-uefi.patch | 200 | ||||
-rw-r--r-- | sb-hibernate.patch | 23 | ||||
-rw-r--r-- | secure-modules.patch | 284 |
6 files changed, 1852 insertions, 245 deletions
diff --git a/config-x86-generic b/config-x86-generic index 33fd36906..3c3a0dd03 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -441,12 +441,13 @@ CONFIG_VMWARE_VMCI_VSOCKETS=m CONFIG_XZ_DEC_X86=y CONFIG_MPILIB=y +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_BLACKLIST_KEYRING=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_MODULE_SIG_BLACKLIST=y CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE=y CONFIG_EFI_SIGNATURE_LIST_PARSER=y diff --git a/kernel.spec b/kernel.spec index 31ee5da01..5e85bac41 100644 --- a/kernel.spec +++ b/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 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -651,6 +651,7 @@ Patch800: crash-driver.patch # keys Patch900: keys-expand-keyring.patch Patch901: keys-krb-support.patch +Patch902: keys-x509-improv.patch # secure boot Patch1000: secure-modules.patch @@ -1394,6 +1395,7 @@ ApplyPatch crash-driver.patch # keys ApplyPatch keys-expand-keyring.patch ApplyPatch keys-krb-support.patch +ApplyPatch keys-x509-improv.patch # secure boot ApplyPatch secure-modules.patch @@ -2280,6 +2282,9 @@ fi # ||----w | # || || %changelog +* Tue Sep 03 2013 Josh Boyer <jwboyer@fedoraproject.org> - 3.11.0-3 +- Add system_keyring patches back in + * Tue Sep 03 2013 Kyle McMartin <kyle@redhat.com> - Pull in some Calxeda highbank fixes that are destined for 3.12 - Add a %with_extra twiddle to disable building kernel-modules-extra diff --git a/keys-x509-improv.patch b/keys-x509-improv.patch new file mode 100644 index 000000000..b3341cf50 --- /dev/null +++ b/keys-x509-improv.patch @@ -0,0 +1,1580 @@ +From abaac4978b6719e7ae12babb6be5e35184b61cde Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:07:13 +0100 +Subject: [PATCH 01/14] KEYS: Load *.x509 files into kernel keyring + +Load all the files matching the pattern "*.x509" that are to be found in kernel +base source dir and base build dir into the module signing keyring. + +The "extra_certificates" file is then redundant. + +Signed-off-by: David Howells <dhowells@redhat.com> +--- + kernel/Makefile | 35 +++++++++++++++++++++++++++++------ + kernel/modsign_certificate.S | 3 +-- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/kernel/Makefile b/kernel/Makefile +index 470839d..4a2ee4e 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -141,17 +141,40 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE + $(call if_changed,bc) + + ifeq ($(CONFIG_MODULE_SIG),y) ++############################################################################### + # +-# Pull the signing certificate and any extra certificates into the kernel ++# Roll all the X.509 certificates that we can find together and pull ++# them into the kernel. + # ++############################################################################### ++X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) ++X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 ++X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y)) ++ ++ifeq ($(X509_CERTIFICATES),) ++$(warning *** No X.509 certificates found ***) ++endif ++ ++ifneq ($(wildcard $(obj)/.x509.list),) ++ifneq ($(shell cat $(obj)/.x509.list),$(X509_CERTIFICATES)) ++$(info X.509 certificate list changed) ++$(shell rm $(obj)/.x509.list) ++endif ++endif ++ ++kernel/modsign_certificate.o: $(obj)/x509_certificate_list + +-quiet_cmd_touch = TOUCH $@ +- cmd_touch = touch $@ ++quiet_cmd_x509certs = CERTS $@ ++ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ ++targets += $(obj)/x509_certificate_list ++$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list ++ $(call if_changed,x509certs) + +-extra_certificates: +- $(call cmd,touch) ++targets += $(obj)/.x509.list ++$(obj)/.x509.list: ++ @echo $(X509_CERTIFICATES) >$@ + +-kernel/modsign_certificate.o: signing_key.x509 extra_certificates ++clean-files := x509_certificate_list .x509.list + + ############################################################################### + # +diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S +index 4a9a86d..6fe03c7 100644 +--- a/kernel/modsign_certificate.S ++++ b/kernel/modsign_certificate.S +@@ -7,6 +7,5 @@ + .section ".init.data","aw" + + GLOBAL(modsign_certificate_list) +- .incbin "signing_key.x509" +- .incbin "extra_certificates" ++ .incbin "kernel/x509_certificate_list" + GLOBAL(modsign_certificate_list_end) +-- +1.8.3.1 + + + +From 2d6ac2896c3b4b48be96b7dbdfda1668609e35aa Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:07:30 +0100 +Subject: [PATCH 03/14] KEYS: Separate the kernel signature checking keyring + from module signing + +Separate the kernel signature checking keyring from module signing so that it +can be used by code other than the module-signing code. + +Signed-off-by: David Howells <dhowells@redhat.com> +--- + include/keys/system_keyring.h | 23 ++++++++++ + init/Kconfig | 13 ++++++ + kernel/Makefile | 17 ++++--- + kernel/modsign_certificate.S | 11 ----- + kernel/modsign_pubkey.c | 104 ------------------------------------------ + kernel/module-internal.h | 2 - + kernel/module_signing.c | 3 +- + kernel/system_certificates.S | 11 +++++ + kernel/system_keyring.c | 103 +++++++++++++++++++++++++++++++++++++++++ + 9 files changed, 163 insertions(+), 124 deletions(-) + create mode 100644 include/keys/system_keyring.h + delete mode 100644 kernel/modsign_certificate.S + delete mode 100644 kernel/modsign_pubkey.c + create mode 100644 kernel/system_certificates.S + create mode 100644 kernel/system_keyring.c + +diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h +new file mode 100644 +index 0000000..8dabc39 +--- /dev/null ++++ b/include/keys/system_keyring.h +@@ -0,0 +1,23 @@ ++/* System keyring containing trusted public keys. ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++#ifndef _KEYS_SYSTEM_KEYRING_H ++#define _KEYS_SYSTEM_KEYRING_H ++ ++#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING ++ ++#include <linux/key.h> ++ ++extern struct key *system_trusted_keyring; ++ ++#endif ++ ++#endif /* _KEYS_SYSTEM_KEYRING_H */ +diff --git a/init/Kconfig b/init/Kconfig +index 247084b..6abf0e0 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1664,6 +1664,18 @@ config BASE_SMALL + default 0 if BASE_FULL + default 1 if !BASE_FULL + ++config SYSTEM_TRUSTED_KEYRING ++ bool "Provide system-wide ring of trusted keys" ++ depends on KEYS ++ help ++ Provide a system keyring to which trusted keys can be added. Keys in ++ the keyring are considered to be trusted. Keys may be added at will ++ by the kernel from compiled-in data and from hardware key stores, but ++ userspace may only add extra keys if those keys can be verified by ++ keys already in the keyring. ++ ++ Keys in this keyring are used by module signature checking. ++ + menuconfig MODULES + bool "Enable loadable module support" + help +@@ -1736,6 +1748,7 @@ config MODULE_SRCVERSION_ALL + config MODULE_SIG + bool "Module signature verification" + depends on MODULES ++ select SYSTEM_TRUSTED_KEYRING + select KEYS + select CRYPTO + select ASYMMETRIC_KEY_TYPE +diff --git a/kernel/Makefile b/kernel/Makefile +index 7bd1565..68f7182 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -52,8 +52,9 @@ obj-$(CONFIG_SMP) += spinlock.o + obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + 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 modsign_pubkey.o modsign_certificate.o ++obj-$(CONFIG_MODULE_SIG) += module_signing.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -140,13 +141,14 @@ targets += timeconst.h + $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE + $(call if_changed,bc) + +-ifeq ($(CONFIG_MODULE_SIG),y) + ############################################################################### + # +-# Roll all the X.509 certificates that we can find together and pull +-# them into the kernel. ++# Roll all the X.509 certificates that we can find together and pull them into ++# the kernel so that they get loaded into the system trusted keyring during ++# boot. + # + ############################################################################### ++ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) + X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509) + X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509 + X509_CERTIFICATES := $(sort $(realpath $(X509_CERTIFICATES-y))) +@@ -162,10 +164,11 @@ $(shell rm $(obj)/.x509.list) + endif + endif + +-kernel/modsign_certificate.o: $(obj)/x509_certificate_list ++kernel/system_certificates.o: $(obj)/x509_certificate_list + + quiet_cmd_x509certs = CERTS $@ +- cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ ++ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)") ++ + targets += $(obj)/x509_certificate_list + $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list + $(call if_changed,x509certs) +@@ -175,7 +178,9 @@ $(obj)/.x509.list: + @echo $(X509_CERTIFICATES) >$@ + + clean-files := x509_certificate_list .x509.list ++endif + ++ifeq ($(CONFIG_MODULE_SIG),y) + ############################################################################### + # + # If module signing is requested, say by allyesconfig, but a key has not been +diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S +deleted file mode 100644 +index 6fe03c7..0000000 +--- a/kernel/modsign_certificate.S ++++ /dev/null +@@ -1,11 +0,0 @@ +-#include <linux/export.h> +- +-#define GLOBAL(name) \ +- .globl VMLINUX_SYMBOL(name); \ +- VMLINUX_SYMBOL(name): +- +- .section ".init.data","aw" +- +-GLOBAL(modsign_certificate_list) +- .incbin "kernel/x509_certificate_list" +-GLOBAL(modsign_certificate_list_end) +diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c +deleted file mode 100644 +index 2b6e699..0000000 +--- a/kernel/modsign_pubkey.c ++++ /dev/null +@@ -1,104 +0,0 @@ +-/* Public keys for module signature verification +- * +- * 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. +- */ +- +-#include <linux/kernel.h> +-#include <linux/sched.h> +-#include <linux/cred.h> +-#include <linux/err.h> +-#include <keys/asymmetric-type.h> +-#include "module-internal.h" +- +-struct key *modsign_keyring; +- +-extern __initdata const u8 modsign_certificate_list[]; +-extern __initdata const u8 modsign_certificate_list_end[]; +- +-/* +- * We need to make sure ccache doesn't cache the .o file as it doesn't notice +- * if modsign.pub changes. +- */ +-static __initdata const char annoy_ccache[] = __TIME__ "foo"; +- +-/* +- * Load the compiled-in keys +- */ +-static __init int module_verify_init(void) +-{ +- pr_notice("Initialise module verification\n"); +- +- modsign_keyring = keyring_alloc(".module_sign", +- 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_keyring)) +- panic("Can't allocate module signing keyring\n"); +- +- return 0; +-} +- +-/* +- * Must be initialised before we try and load the keys into the keyring. +- */ +-device_initcall(module_verify_init); +- +-/* +- * Load the compiled-in keys +- */ +-static __init int load_module_signing_keys(void) +-{ +- key_ref_t key; +- const u8 *p, *end; +- size_t plen; +- +- pr_notice("Loading module verification certificates\n"); +- +- end = modsign_certificate_list_end; +- p = modsign_certificate_list; +- while (p < end) { +- /* Each cert begins with an ASN.1 SEQUENCE tag and must be more +- * than 256 bytes in size. +- */ +- if (end - p < 4) +- goto dodgy_cert; +- if (p[0] != 0x30 && +- p[1] != 0x82) +- goto dodgy_cert; +- plen = (p[2] << 8) | p[3]; +- plen += 4; +- if (plen > end - p) +- goto dodgy_cert; +- +- key = key_create_or_update(make_key_ref(modsign_keyring, 1), +- "asymmetric", +- NULL, +- p, +- plen, +- (KEY_POS_ALL & ~KEY_POS_SETATTR) | +- KEY_USR_VIEW, +- KEY_ALLOC_NOT_IN_QUOTA); +- if (IS_ERR(key)) +- pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", +- PTR_ERR(key)); +- else +- pr_notice("MODSIGN: Loaded cert '%s'\n", +- key_ref_to_ptr(key)->description); +- p += plen; +- } +- +- return 0; +- +-dodgy_cert: +- pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); +- return 0; +-} +-late_initcall(load_module_signing_keys); +diff --git a/kernel/module-internal.h b/kernel/module-internal.h +index 24f9247..915e123 100644 +--- a/kernel/module-internal.h ++++ b/kernel/module-internal.h +@@ -9,6 +9,4 @@ + * 2 of the Licence, or (at your option) any later version. + */ + +-extern struct key *modsign_keyring; +- + 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..0034e36 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -14,6 +14,7 @@ + #include <crypto/public_key.h> + #include <crypto/hash.h> + #include <keys/asymmetric-type.h> ++#include <keys/system_keyring.h> + #include "module-internal.h" + + /* +@@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, + + pr_debug("Look up: \"%s\"\n", id); + +- key = keyring_search(make_key_ref(modsign_keyring, 1), ++ key = keyring_search(make_key_ref(system_trusted_keyring, 1), + &key_type_asymmetric, id); + if (IS_ERR(key)) + pr_warn("Request for unknown module key '%s' err %ld\n", +diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S +new file mode 100644 +index 0000000..5cffe86 +--- /dev/null ++++ b/kernel/system_certificates.S +@@ -0,0 +1,11 @@ ++#include <linux/export.h> ++ ++#define GLOBAL(name) \ ++ .globl VMLINUX_SYMBOL(name); \ ++ VMLINUX_SYMBOL(name): ++ ++ .section ".init.data","aw" ++ ++GLOBAL(system_certificate_list) ++ .incbin "kernel/x509_certificate_list" ++GLOBAL(system_certificate_list_end) +diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c +new file mode 100644 +index 0000000..cd5cd3f +--- /dev/null ++++ b/kernel/system_keyring.c +@@ -0,0 +1,103 @@ ++/* System trusted keyring for trusted public keys ++ * ++ * 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. ++ */ ++ ++#include <linux/export.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/cred.h> ++#include <linux/err.h> ++#include <keys/asymmetric-type.h> ++#include <keys/system_keyring.h> ++#include "module-internal.h" ++ ++struct key *system_trusted_keyring; ++EXPORT_SYMBOL_GPL(system_trusted_keyring); ++ ++extern __initdata const u8 system_certificate_list[]; ++extern __initdata const u8 system_certificate_list_end[]; ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int system_trusted_keyring_init(void) ++{ ++ pr_notice("Initialise system trusted keyring\n"); ++ ++ system_trusted_keyring = ++ keyring_alloc(".system_keyring", ++ 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(system_trusted_keyring)) ++ panic("Can't allocate system trusted keyring\n"); ++ ++ return 0; ++} ++ ++/* ++ * Must be initialised before we try and load the keys into the keyring. ++ */ ++device_initcall(system_trusted_keyring_init); ++ ++/* ++ * Load the compiled-in list of X.509 certificates. ++ */ ++static __init int load_system_certificate_list(void) ++{ ++ key_ref_t key; ++ const u8 *p, *end; ++ size_t plen; ++ ++ pr_notice("Loading compiled-in X.509 certificates\n"); ++ ++ end = system_certificate_list_end; ++ p = system_certificate_list; ++ while (p < end) { ++ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more ++ * than 256 bytes in size. ++ */ ++ if (end - p < 4) ++ goto dodgy_cert; ++ if (p[0] != 0x30 && ++ p[1] != 0x82) ++ goto dodgy_cert; ++ plen = (p[2] << 8) | p[3]; ++ plen += 4; ++ if (plen > end - p) ++ goto dodgy_cert; ++ ++ key = key_create_or_update(make_key_ref(system_trusted_keyring, 1), ++ "asymmetric", ++ NULL, ++ p, ++ plen, ++ (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 X.509 cert '%s'\n", ++ key_ref_to_ptr(key)->description); ++ key_ref_put(key); ++ } ++ p += plen; ++ } ++ ++ return 0; ++ ++dodgy_cert: ++ pr_err("Problem parsing in-kernel X.509 certificate list\n"); ++ return 0; ++} ++late_initcall(load_system_certificate_list); +-- +1.8.3.1 + + +From 6f90d07a776d7babf30a3322dafd66c8c25db681 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:07:37 +0100 +Subject: [PATCH 04/14] KEYS: Add a 'trusted' flag and a 'trusted only' flag + +Add KEY_FLAG_TRUSTED to indicate that a key either comes from a trusted source +or had a cryptographic signature chain that led back to a trusted key the +kernel already possessed. + +Add KEY_FLAGS_TRUSTED_ONLY to indicate that a keyring will only accept links to +keys marked with KEY_FLAGS_TRUSTED. + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +--- + include/linux/key-type.h | 1 + + include/linux/key.h | 3 +++ + kernel/system_keyring.c | 4 +++- + security/keys/key.c | 8 ++++++++ + security/keys/keyring.c | 4 ++++ + 5 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/include/linux/key-type.h b/include/linux/key-type.h +index f58737b..a74c3a8 100644 +--- a/include/linux/key-type.h ++++ b/include/linux/key-type.h +@@ -45,6 +45,7 @@ struct key_preparsed_payload { + const void *data; /* Raw data */ + size_t datalen; /* Raw datalen */ + size_t quotalen; /* Quota length for proposed payload */ ++ bool trusted; /* True if key is trusted */ + }; + + typedef int (*request_key_actor_t)(struct key_construction *key, +diff --git a/include/linux/key.h b/include/linux/key.h +index 010dbb6..80d6774 100644 +--- a/include/linux/key.h ++++ b/include/linux/key.h +@@ -168,6 +168,8 @@ struct key { + #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ + #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ + #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ ++#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ ++#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ + + /* the key type and key description string + * - the desc is used to match a key against search criteria +@@ -218,6 +220,7 @@ extern struct key *key_alloc(struct key_type *type, + #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ + #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ + #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ ++#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ + + extern void key_revoke(struct key *key); + extern void key_invalidate(struct key *key); +diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c +index cd5cd3f..4ca7072 100644 +--- a/kernel/system_keyring.c ++++ b/kernel/system_keyring.c +@@ -40,6 +40,7 @@ static __init int system_trusted_keyring_init(void) + if (IS_ERR(system_trusted_keyring)) + panic("Can't allocate system trusted keyring\n"); + ++ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); + return 0; + } + +@@ -82,7 +83,8 @@ static __init int load_system_certificate_list(void) + plen, + (KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW, +- KEY_ALLOC_NOT_IN_QUOTA); ++ KEY_ALLOC_NOT_IN_QUOTA | ++ KEY_ALLOC_TRUSTED); + if (IS_ERR(key)) { + pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", + PTR_ERR(key)); +diff --git a/security/keys/key.c b/security/keys/key.c +index a819b5c..d331ea9 100644 +--- a/security/keys/key.c ++++ b/security/keys/key.c +@@ -300,6 +300,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, + + if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) + key->flags |= 1 << KEY_FLAG_IN_QUOTA; ++ if (flags & KEY_ALLOC_TRUSTED) ++ key->flags |= 1 << KEY_FLAG_TRUSTED; + + memset(&key->type_data, 0, sizeof(key->type_data)); + +@@ -813,6 +815,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + prep.data = payload; + prep.datalen = plen; + prep.quotalen = index_key.type->def_datalen; ++ prep.trusted = flags & KEY_ALLOC_TRUSTED; + if (index_key.type->preparse) { + ret = index_key.type->preparse(&prep); + if (ret < 0) { +@@ -827,6 +830,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, + } + index_key.desc_len = strlen(index_key.description); + ++ key_ref = ERR_PTR(-EPERM); ++ if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags)) ++ goto error_free_prep; ++ flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0; ++ + ret = __key_link_begin(keyring, &index_key, &edit); + if (ret < 0) { + key_ref = ERR_PTR(ret); +diff --git a/security/keys/keyring.c b/security/keys/keyring.c +index f7cdea2..9b6f6e0 100644 +--- a/security/keys/keyring.c ++++ b/security/keys/keyring.c +@@ -1183,6 +1183,10 @@ int key_link(struct key *keyring, struct key *key) + key_check(keyring); + key_check(key); + ++ if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) && ++ !test_bit(KEY_FLAG_TRUSTED, &key->flags)) ++ return -EPERM; ++ + ret = __key_link_begin(keyring, &key->index_key, &edit); + if (ret == 0) { + kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage)); +-- +1.8.3.1 + + +From 559cc3ad765e1b443bc89965be9ef9ff3caabdcc Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:15:10 +0100 +Subject: [PATCH 05/14] KEYS: Rename public key parameter name arrays + +Rename the arrays of public key parameters (public key algorithm names, hash +algorithm names and ID type names) so that the array name ends in "_name". + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + crypto/asymmetric_keys/public_key.c | 14 +++++++------- + crypto/asymmetric_keys/x509_public_key.c | 8 ++++---- + include/crypto/public_key.h | 6 +++--- + kernel/module_signing.c | 4 ++-- + 4 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index cb2e291..b313df1 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -22,13 +22,13 @@ + + MODULE_LICENSE("GPL"); + +-const char *const pkey_algo[PKEY_ALGO__LAST] = { ++const char *const pkey_algo_name[PKEY_ALGO__LAST] = { + [PKEY_ALGO_DSA] = "DSA", + [PKEY_ALGO_RSA] = "RSA", + }; +-EXPORT_SYMBOL_GPL(pkey_algo); ++EXPORT_SYMBOL_GPL(pkey_algo_name); + +-const char *const pkey_hash_algo[PKEY_HASH__LAST] = { ++const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { + [PKEY_HASH_MD4] = "md4", + [PKEY_HASH_MD5] = "md5", + [PKEY_HASH_SHA1] = "sha1", +@@ -38,13 +38,13 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = { + [PKEY_HASH_SHA512] = "sha512", + [PKEY_HASH_SHA224] = "sha224", + }; +-EXPORT_SYMBOL_GPL(pkey_hash_algo); ++EXPORT_SYMBOL_GPL(pkey_hash_algo_name); + +-const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { ++const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { + [PKEY_ID_PGP] = "PGP", + [PKEY_ID_X509] = "X509", + }; +-EXPORT_SYMBOL_GPL(pkey_id_type); ++EXPORT_SYMBOL_GPL(pkey_id_type_name); + + /* + * Provide a part of a description of the key for /proc/keys. +@@ -56,7 +56,7 @@ static void public_key_describe(const struct key *asymmetric_key, + + if (key) + seq_printf(m, "%s.%s", +- pkey_id_type[key->id_type], key->algo->name); ++ pkey_id_type_name[key->id_type], key->algo->name); + } + + /* +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 06007f0..afbbc36 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -49,7 +49,7 @@ static int x509_check_signature(const struct public_key *pub, + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ +- tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); + +@@ -117,7 +117,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); +- pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); ++ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); + pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, + cert->valid_from.tm_mday, cert->valid_from.tm_hour, +@@ -127,8 +127,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + cert->valid_to.tm_mday, cert->valid_to.tm_hour, + cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Signature: %s + %s\n", +- pkey_algo[cert->sig_pkey_algo], +- pkey_hash_algo[cert->sig_hash_algo]); ++ pkey_algo_name[cert->sig_pkey_algo], ++ pkey_hash_algo_name[cert->sig_hash_algo]); + + if (!cert->fingerprint || !cert->authority) { + pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index f5b0224..619d570 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -22,7 +22,7 @@ enum pkey_algo { + PKEY_ALGO__LAST + }; + +-extern const char *const pkey_algo[PKEY_ALGO__LAST]; ++extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; + + enum pkey_hash_algo { + PKEY_HASH_MD4, +@@ -36,7 +36,7 @@ enum pkey_hash_algo { + PKEY_HASH__LAST + }; + +-extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; ++extern const char *const pkey_hash_algo_name[PKEY_HASH__LAST]; + + enum pkey_id_type { + PKEY_ID_PGP, /* OpenPGP generated key ID */ +@@ -44,7 +44,7 @@ enum pkey_id_type { + PKEY_ID_TYPE__LAST + }; + +-extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; ++extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST]; + + /* + * Cryptographic data for the public-key subtype of the asymmetric key type. +diff --git a/kernel/module_signing.c b/kernel/module_signing.c +index 0034e36..0b6b870 100644 +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -55,7 +55,7 @@ static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ +- tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[hash], 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); + +@@ -218,7 +218,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen) + return -ENOPKG; + + if (ms.hash >= PKEY_HASH__LAST || +- !pkey_hash_algo[ms.hash]) ++ !pkey_hash_algo_name[ms.hash]) + return -ENOPKG; + + key = request_asymmetric_key(sig, ms.signer_len, +-- +1.8.3.1 + + +From a0aab2065bbdd0bc56ae6d7767e1df7c58b8997f Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:15:18 +0100 +Subject: [PATCH 06/14] KEYS: Move the algorithm pointer array from x509 to + public_key.c + +Move the public-key algorithm pointer array from x509_public_key.c to +public_key.c as it isn't X.509 specific. + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + crypto/asymmetric_keys/public_key.c | 8 ++++++++ + crypto/asymmetric_keys/x509_public_key.c | 11 +---------- + include/crypto/public_key.h | 1 + + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index b313df1..796ce08 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -28,6 +28,14 @@ const char *const pkey_algo_name[PKEY_ALGO__LAST] = { + }; + EXPORT_SYMBOL_GPL(pkey_algo_name); + ++const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { ++#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ ++ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) ++ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, ++#endif ++}; ++EXPORT_SYMBOL_GPL(pkey_algo); ++ + const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = { + [PKEY_HASH_MD4] = "md4", + [PKEY_HASH_MD5] = "md5", +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index afbbc36..fe38628 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -23,15 +23,6 @@ + #include "public_key.h" + #include "x509_parser.h" + +-static const +-struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { +- [PKEY_ALGO_DSA] = NULL, +-#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ +- defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) +- [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, +-#endif +-}; +- + /* + * Check the signature on a certificate using the provided public key + */ +@@ -174,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; ++ cert->pub->algo = pkey_algo[cert->pkey_algo]; + cert->pub->id_type = PKEY_ID_X509; + + /* Check the signature on the key */ +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 619d570..46bde25 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -23,6 +23,7 @@ enum pkey_algo { + }; + + extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; ++extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST]; + + enum pkey_hash_algo { + PKEY_HASH_MD4, +-- +1.8.3.1 + + +From 7009b65ddc1d8bf62dc017795265b9cf331a4d70 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:15:24 +0100 +Subject: [PATCH 07/14] KEYS: Store public key algo ID in public_key struct + +Store public key algo ID in public_key struct for reference purposes. This +allows it to be removed from the x509_certificate struct and used to find a +default in public_key_verify_signature(). + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + crypto/asymmetric_keys/x509_cert_parser.c | 5 +++-- + crypto/asymmetric_keys/x509_parser.h | 1 - + crypto/asymmetric_keys/x509_public_key.c | 4 ++-- + include/crypto/public_key.h | 1 + + 4 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index facbf26..8cc253d 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -343,8 +343,9 @@ int x509_extract_key_data(void *context, size_t hdrlen, + if (ctx->last_oid != OID_rsaEncryption) + return -ENOPKG; + +- /* There seems to be an extraneous 0 byte on the front of the data */ +- ctx->cert->pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA; ++ ++ /* Discard the BIT STRING metadata */ + ctx->key = value + 1; + ctx->key_size = vlen - 1; + return 0; +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index f86dc5f..e583ad0 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -20,7 +20,6 @@ struct x509_certificate { + char *authority; /* Authority key fingerprint as hex */ + struct tm valid_from; + struct tm valid_to; +- enum pkey_algo pkey_algo : 8; /* Public key algorithm */ + enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ + enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ + const void *tbs; /* Signed data */ +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index fe38628..fac574c 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -108,7 +108,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); +- pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]); ++ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); + pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, + cert->valid_from.tm_mday, cert->valid_from.tm_hour, +@@ -165,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- cert->pub->algo = pkey_algo[cert->pkey_algo]; ++ cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; + cert->pub->id_type = PKEY_ID_X509; + + /* Check the signature on the key */ +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 46bde25..05778df 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -60,6 +60,7 @@ struct public_key { + #define PKEY_CAN_DECRYPT 0x02 + #define PKEY_CAN_SIGN 0x04 + #define PKEY_CAN_VERIFY 0x08 ++ enum pkey_algo pkey_algo : 8; + enum pkey_id_type id_type : 8; + union { + MPI mpi[5]; +-- +1.8.3.1 + + +From cad6ff6b429f31611ccb231cfe6adcb69d891352 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:15:30 +0100 +Subject: [PATCH 08/14] KEYS: Split public_key_verify_signature() and make + available + +Modify public_key_verify_signature() so that it now takes a public_key struct +rather than a key struct and supply a wrapper that takes a key struct. The +wrapper is then used by the asymmetric key subtype and the modified function is +used by X.509 self-signature checking and can be used by other things also. + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + crypto/asymmetric_keys/public_key.c | 40 +++++++++++++++++++++++++------- + crypto/asymmetric_keys/public_key.h | 6 +++++ + crypto/asymmetric_keys/x509_public_key.c | 2 +- + 3 files changed, 39 insertions(+), 9 deletions(-) + +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index 796ce08..49ac8d8 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -86,21 +86,45 @@ EXPORT_SYMBOL_GPL(public_key_destroy); + /* + * Verify a signature using a public key. + */ +-static int public_key_verify_signature(const struct key *key, +- const struct public_key_signature *sig) ++int public_key_verify_signature(const struct public_key *pk, ++ const struct public_key_signature *sig) + { +- const struct public_key *pk = key->payload.data; ++ const struct public_key_algorithm *algo; ++ ++ BUG_ON(!pk); ++ BUG_ON(!pk->mpi[0]); ++ BUG_ON(!pk->mpi[1]); ++ BUG_ON(!sig); ++ BUG_ON(!sig->digest); ++ BUG_ON(!sig->mpi[0]); ++ ++ algo = pk->algo; ++ if (!algo) { ++ if (pk->pkey_algo >= PKEY_ALGO__LAST) ++ return -ENOPKG; ++ algo = pkey_algo[pk->pkey_algo]; ++ if (!algo) ++ return -ENOPKG; ++ } + +- if (!pk->algo->verify_signature) ++ if (!algo->verify_signature) + return -ENOTSUPP; + +- if (sig->nr_mpi != pk->algo->n_sig_mpi) { ++ if (sig->nr_mpi != algo->n_sig_mpi) { + pr_debug("Signature has %u MPI not %u\n", +- sig->nr_mpi, pk->algo->n_sig_mpi); ++ sig->nr_mpi, algo->n_sig_mpi); + return -EINVAL; + } + +- return pk->algo->verify_signature(pk, sig); ++ return algo->verify_signature(pk, sig); ++} ++EXPORT_SYMBOL_GPL(public_key_verify_signature); ++ ++static int public_key_verify_signature_2(const struct key *key, ++ const struct public_key_signature *sig) ++{ ++ const struct public_key *pk = key->payload.data; ++ return public_key_verify_signature(pk, sig); + } + + /* +@@ -111,6 +135,6 @@ struct asymmetric_key_subtype public_key_subtype = { + .name = "public_key", + .describe = public_key_describe, + .destroy = public_key_destroy, +- .verify_signature = public_key_verify_signature, ++ .verify_signature = public_key_verify_signature_2, + }; + EXPORT_SYMBOL_GPL(public_key_subtype); +diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h +index 5e5e356..5c37a22 100644 +--- a/crypto/asymmetric_keys/public_key.h ++++ b/crypto/asymmetric_keys/public_key.h +@@ -28,3 +28,9 @@ struct public_key_algorithm { + }; + + extern const struct public_key_algorithm RSA_public_key_algorithm; ++ ++/* ++ * public_key.c ++ */ ++extern int public_key_verify_signature(const struct public_key *pk, ++ const struct public_key_signature *sig); +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index fac574c..8cb2f70 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -76,7 +76,7 @@ static int x509_check_signature(const struct public_key *pub, + if (ret < 0) + goto error_mpi; + +- ret = pub->algo->verify_signature(pub, sig); ++ ret = public_key_verify_signature(pub, sig); + + pr_debug("Cert Verification: %d\n", ret); + +-- +1.8.3.1 + + +From 87854340605a64fcc54109ea415d9e54c45e8533 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:15:37 +0100 +Subject: [PATCH 09/14] KEYS: Store public key algo ID in public_key_signature + struct + +Store public key algorithm ID in public_key_signature struct for reference +purposes. This allows a public_key_signature struct to be embedded in +struct x509_certificate and other places more easily. + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + include/crypto/public_key.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h +index 05778df..b34fda4 100644 +--- a/include/crypto/public_key.h ++++ b/include/crypto/public_key.h +@@ -90,6 +90,7 @@ struct public_key_signature { + u8 *digest; + u8 digest_size; /* Number of bytes in digest */ + u8 nr_mpi; /* Occupancy of mpi[] */ ++ enum pkey_algo pkey_algo : 8; + enum pkey_hash_algo pkey_hash_algo : 8; + union { + MPI mpi[2]; +-- +1.8.3.1 + + +From ae4684a05d87123de310b69c616922dc993694ca Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:16:34 +0100 +Subject: [PATCH 10/14] X.509: struct x509_certificate needs struct tm + declaring + +struct x509_certificate needs struct tm declaring by #inclusion of linux/time.h +prior to its definition. + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + crypto/asymmetric_keys/x509_parser.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index e583ad0..2d01182 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -9,6 +9,7 @@ + * 2 of the Licence, or (at your option) any later version. + */ + ++#include <linux/time.h> + #include <crypto/public_key.h> + + struct x509_certificate { +-- +1.8.3.1 + + +From dacde6f44ebe5a5c89bd1a25b35b1b63c139b375 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:18:02 +0100 +Subject: [PATCH 11/14] X.509: Embed public_key_signature struct and create + filler function + +Embed a public_key_signature struct in struct x509_certificate, eliminating +now unnecessary fields, and split x509_check_signature() to create a filler +function for it that attaches a digest of the signed data and an MPI that +represents the signature data. x509_free_certificate() is then modified to +deal with these. + +Whilst we're at it, export both x509_check_signature() and the new +x509_get_sig_params(). + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + crypto/asymmetric_keys/x509_cert_parser.c | 30 +++++------ + crypto/asymmetric_keys/x509_parser.h | 16 ++++-- + crypto/asymmetric_keys/x509_public_key.c | 83 +++++++++++++++++-------------- + 3 files changed, 74 insertions(+), 55 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 8cc253d..144201c 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -47,6 +47,8 @@ void x509_free_certificate(struct x509_certificate *cert) + kfree(cert->subject); + kfree(cert->fingerprint); + kfree(cert->authority); ++ kfree(cert->sig.digest); ++ mpi_free(cert->sig.rsa.s); + kfree(cert); + } + } +@@ -152,33 +154,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, + return -ENOPKG; /* Unsupported combination */ + + case OID_md4WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_MD5; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_MD5; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha1WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA1; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha256WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA256; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha384WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA384; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha512WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA512; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + + case OID_sha224WithRSAEncryption: +- ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; +- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; ++ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA224; ++ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + break; + } + +@@ -203,8 +205,8 @@ int x509_note_signature(void *context, size_t hdrlen, + return -EINVAL; + } + +- ctx->cert->sig = value; +- ctx->cert->sig_size = vlen; ++ ctx->cert->raw_sig = value; ++ ctx->cert->raw_sig_size = vlen; + return 0; + } + +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index 2d01182..87d9cc2 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -21,12 +21,11 @@ struct x509_certificate { + char *authority; /* Authority key fingerprint as hex */ + struct tm valid_from; + struct tm valid_to; +- enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ +- enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ + const void *tbs; /* Signed data */ +- size_t tbs_size; /* Size of signed data */ +- const void *sig; /* Signature data */ +- size_t sig_size; /* Size of sigature */ ++ unsigned tbs_size; /* Size of signed data */ ++ unsigned raw_sig_size; /* Size of sigature */ ++ const void *raw_sig; /* Signature data */ ++ struct public_key_signature sig; /* Signature parameters */ + }; + + /* +@@ -34,3 +33,10 @@ struct x509_certificate { + */ + extern void x509_free_certificate(struct x509_certificate *cert); + extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); ++ ++/* ++ * x509_public_key.c ++ */ ++extern int x509_get_sig_params(struct x509_certificate *cert); ++extern int x509_check_signature(const struct public_key *pub, ++ struct x509_certificate *cert); +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 8cb2f70..b7c81d8 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -24,72 +24,83 @@ + #include "x509_parser.h" + + /* +- * Check the signature on a certificate using the provided public key ++ * Set up the signature parameters in an X.509 certificate. This involves ++ * digesting the signed data and extracting the signature. + */ +-static int x509_check_signature(const struct public_key *pub, +- const struct x509_certificate *cert) ++int x509_get_sig_params(struct x509_certificate *cert) + { +- struct public_key_signature *sig; + struct crypto_shash *tfm; + struct shash_desc *desc; + size_t digest_size, desc_size; ++ void *digest; + int ret; + + pr_devel("==>%s()\n", __func__); +- ++ ++ if (cert->sig.rsa.s) ++ return 0; ++ ++ cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); ++ if (!cert->sig.rsa.s) ++ return -ENOMEM; ++ cert->sig.nr_mpi = 1; ++ + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ +- tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0); ++ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + digest_size = crypto_shash_digestsize(tfm); + +- /* We allocate the hash operational data storage on the end of our +- * context data. ++ /* We allocate the hash operational data storage on the end of the ++ * digest storage space. + */ + ret = -ENOMEM; +- sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); +- if (!sig) +- goto error_no_sig; ++ digest = kzalloc(digest_size + desc_size, GFP_KERNEL); ++ if (!digest) ++ goto error; + +- sig->pkey_hash_algo = cert->sig_hash_algo; +- sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; +- sig->digest_size = digest_size; ++ cert->sig.digest = digest; ++ cert->sig.digest_size = digest_size; + +- desc = (void *)sig + sizeof(*sig); +- desc->tfm = tfm; +- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; ++ desc = digest + digest_size; ++ desc->tfm = tfm; ++ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + ret = crypto_shash_init(desc); + if (ret < 0) + goto error; ++ might_sleep(); ++ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest); ++error: ++ crypto_free_shash(tfm); ++ pr_devel("<==%s() = %d\n", __func__, ret); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(x509_get_sig_params); + +- ret = -ENOMEM; +- sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); +- if (!sig->rsa.s) +- goto error; ++/* ++ * Check the signature on a certificate using the provided public key ++ */ ++int x509_check_signature(const struct public_key *pub, ++ struct x509_certificate *cert) ++{ ++ int ret; + +- ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); +- if (ret < 0) +- goto error_mpi; ++ pr_devel("==>%s()\n", __func__); + +- ret = public_key_verify_signature(pub, sig); ++ ret = x509_get_sig_params(cert); ++ if (ret < 0) ++ return ret; + ++ ret = public_key_verify_signature(pub, &cert->sig); + pr_debug("Cert Verification: %d\n", ret); +- +-error_mpi: +- mpi_free(sig->rsa.s); +-error: +- kfree(sig); +-error_no_sig: +- crypto_free_shash(tfm); +- +- pr_devel("<==%s() = %d\n", __func__, ret); + return ret; + } ++EXPORT_SYMBOL_GPL(x509_check_signature); + + /* + * Attempt to parse a data blob for a key as an X509 certificate. +@@ -118,8 +129,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + cert->valid_to.tm_mday, cert->valid_to.tm_hour, + cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Signature: %s + %s\n", +- pkey_algo_name[cert->sig_pkey_algo], +- pkey_hash_algo_name[cert->sig_hash_algo]); ++ pkey_algo_name[cert->sig.pkey_algo], ++ pkey_hash_algo_name[cert->sig.pkey_hash_algo]); + + if (!cert->fingerprint || !cert->authority) { + pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", +-- +1.8.3.1 + + +From 650fdcb141f65f3a03dc7eba1179c823fd1a3a54 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:18:15 +0100 +Subject: [PATCH 12/14] X.509: Check the algorithm IDs obtained from parsing an + X.509 certificate + +Check that the algorithm IDs obtained from the ASN.1 parse by OID lookup +corresponds to algorithms that are available to us. + +Reported-by: Kees Cook <keescook@chromium.org> +Signed-off-by: David Howells <dhowells@redhat.com> +--- + crypto/asymmetric_keys/x509_public_key.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index b7c81d8..eb368d4 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -119,6 +119,17 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); ++ ++ if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || ++ cert->sig.pkey_algo >= PKEY_ALGO__LAST || ++ cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || ++ !pkey_algo[cert->pub->pkey_algo] || ++ !pkey_algo[cert->sig.pkey_algo] || ++ !pkey_hash_algo_name[cert->sig.pkey_hash_algo]) { ++ ret = -ENOPKG; ++ goto error_free_cert; ++ } ++ + pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); + pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", + cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, +-- +1.8.3.1 + + +From 8671bdd55802c4b93b9205b6ecd02c7e351ac5c5 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Fri, 30 Aug 2013 16:18:31 +0100 +Subject: [PATCH 13/14] X.509: Handle certificates that lack an + authorityKeyIdentifier field + +Handle certificates that lack an authorityKeyIdentifier field by assuming +they're self-signed and checking their signatures against themselves. + +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Josh Boyer <jwboyer@redhat.com> +--- + crypto/asymmetric_keys/x509_public_key.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index eb368d4..0f55e3b 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -143,8 +143,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + pkey_algo_name[cert->sig.pkey_algo], + pkey_hash_algo_name[cert->sig.pkey_hash_algo]); + +- if (!cert->fingerprint || !cert->authority) { +- pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", ++ if (!cert->fingerprint) { ++ pr_warn("Cert for '%s' must have a SubjKeyId extension\n", + cert->subject); + ret = -EKEYREJECTED; + goto error_free_cert; +@@ -190,8 +190,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; + cert->pub->id_type = PKEY_ID_X509; + +- /* Check the signature on the key */ +- if (strcmp(cert->fingerprint, cert->authority) == 0) { ++ /* Check the signature on the key if it appears to be self-signed */ ++ if (!cert->authority || ++ strcmp(cert->fingerprint, cert->authority) == 0) { + ret = x509_check_signature(cert->pub, cert); + if (ret < 0) + goto error_free_cert; +-- +1.8.3.1 + + +From e2d665556f4b60ce76e880a62f98c81622271e71 Mon Sep 17 00:00:00 2001 +From: David Howells <dhowells@redhat.com> +Date: Tue, 18 Jun 2013 17:40:44 +0100 +Subject: [PATCH 14/14] X.509: Remove certificate date checks + +Remove the certificate date checks that are performed when a certificate is +parsed. There are two checks: a valid from and a valid to. The first check is +causing a lot of problems with system clocks that don't keep good time and the +second places an implicit expiry date upon the kernel when used for module +signing, so do we really need them? + +Signed-off-by: David Howells <dhowells@redhat.com> +cc: David Woodhouse <dwmw2@infradead.org> +cc: Rusty Russell <rusty@rustcorp.com.au> +cc: Josh Boyer <jwboyer@redhat.com> +cc: Alexander Holler <holler@ahsoftware.de> +cc: stable@vger.kernel.org +--- + crypto/asymmetric_keys/x509_public_key.c | 38 -------------------------------- + 1 file changed, 38 deletions(-) + +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 0f55e3b..c1540e8 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -108,7 +108,6 @@ EXPORT_SYMBOL_GPL(x509_check_signature); + static int x509_key_preparse(struct key_preparsed_payload *prep) + { + struct x509_certificate *cert; +- struct tm now; + size_t srlen, sulen; + char *desc = NULL; + int ret; +@@ -150,43 +149,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- time_to_tm(CURRENT_TIME.tv_sec, 0, &now); +- pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", +- now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, +- now.tm_hour, now.tm_min, now.tm_sec); +- if (now.tm_year < cert->valid_from.tm_year || +- (now.tm_year == cert->valid_from.tm_year && +- (now.tm_mon < cert->valid_from.tm_mon || +- (now.tm_mon == cert->valid_from.tm_mon && +- (now.tm_mday < cert->valid_from.tm_mday || +- (now.tm_mday == cert->valid_from.tm_mday && +- (now.tm_hour < cert->valid_from.tm_hour || +- (now.tm_hour == cert->valid_from.tm_hour && +- (now.tm_min < cert->valid_from.tm_min || +- (now.tm_min == cert->valid_from.tm_min && +- (now.tm_sec < cert->valid_from.tm_sec +- ))))))))))) { +- pr_warn("Cert %s is not yet valid\n", cert->fingerprint); +- ret = -EKEYREJECTED; +- goto error_free_cert; +- } +- if (now.tm_year > cert->valid_to.tm_year || +- (now.tm_year == cert->valid_to.tm_year && +- (now.tm_mon > cert->valid_to.tm_mon || +- (now.tm_mon == cert->valid_to.tm_mon && +- (now.tm_mday > cert->valid_to.tm_mday || +- (now.tm_mday == cert->valid_to.tm_mday && +- (now.tm_hour > cert->valid_to.tm_hour || +- (now.tm_hour == cert->valid_to.tm_hour && +- (now.tm_min > cert->valid_to.tm_min || +- (now.tm_min == cert->valid_to.tm_min && +- (now.tm_sec > cert->valid_to.tm_sec +- ))))))))))) { +- pr_warn("Cert %s has expired\n", cert->fingerprint); +- ret = -EKEYEXPIRED; +- goto error_free_cert; +- } +- + cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; + cert->pub->id_type = PKEY_ID_X509; + +-- +1.8.3.1 + diff --git a/modsign-uefi.patch b/modsign-uefi.patch index 3c043f658..c705260dc 100644 --- a/modsign-uefi.patch +++ b/modsign-uefi.patch @@ -1,4 +1,4 @@ -From cff9d37c9529fca5ff853f0050c7f0de0e819ea7 Mon Sep 17 00:00:00 2001 +From 725d7e7fb9ca1065102e640cf8af606169e63075 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 @@ -53,7 +53,7 @@ index eed2202..1da1b3c 100644 1.8.3.1 -From 2ce1c1d0d7110c4b06d65e4c8506f6c54aa72628 Mon Sep 17 00:00:00 2001 +From f204253a34b477c5d68df711326a694b58e51c76 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. @@ -65,9 +65,9 @@ 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 ++++++++++++++++++++++++++++++++++++ + crypto/asymmetric_keys/efi_parser.c | 109 ++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 4 ++ - 4 files changed, 121 insertions(+) + 4 files changed, 122 insertions(+) create mode 100644 crypto/asymmetric_keys/efi_parser.c diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig @@ -101,10 +101,10 @@ index 0727204..cd8388e 100644 # 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 +index 0000000..424896a --- /dev/null +++ b/crypto/asymmetric_keys/efi_parser.c -@@ -0,0 +1,108 @@ +@@ -0,0 +1,109 @@ +/* EFI signature/key/certificate list parser + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. @@ -195,7 +195,8 @@ index 0000000..636feb1 + esize - sizeof(*elem), + (KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); ++ KEY_ALLOC_NOT_IN_QUOTA | ++ KEY_ALLOC_TRUSTED); + + if (IS_ERR(key)) + pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", @@ -232,10 +233,10 @@ index 1da1b3c..42a1d25 100644 1.8.3.1 -From 0e4e8acfd0932bbf6b02112218092c810d9469a5 Mon Sep 17 00:00:00 2001 +From cebc8870a8f0b97b2585a07d9957ead0f21cdc8a 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 +Subject: [PATCH 3/4] KEYS: Add a system 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 @@ -244,86 +245,57 @@ 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(+) + include/keys/system_keyring.h | 4 ++++ + init/Kconfig | 9 +++++++++ + kernel/module_signing.c | 12 ++++++++++++ + kernel/system_keyring.c | 17 +++++++++++++++++ + 4 files changed, 42 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" +diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h +index 8dabc39..e466de1 100644 +--- a/include/keys/system_keyring.h ++++ b/include/keys/system_keyring.h +@@ -18,6 +18,10 @@ - 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"); + extern struct key *system_trusted_keyring; -+#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"); ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++extern struct key *system_blacklist_keyring; +#endif + - return 0; - } + #endif -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 @@ - */ + #endif /* _KEYS_SYSTEM_KEYRING_H */ +diff --git a/init/Kconfig b/init/Kconfig +index 9f3cfdc..547f617 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1676,6 +1676,15 @@ config SYSTEM_TRUSTED_KEYRING - extern struct key *modsign_keyring; -+#ifdef CONFIG_MODULE_SIG_BLACKLIST -+extern struct key *modsign_blacklist; -+#endif + Keys in this keyring are used by module signature checking. - extern int mod_verify_sig(const void *mod, unsigned long *_modlen); ++config SYSTEM_BLACKLIST_KEYRING ++ bool "Provide system-wide ring of blacklisted keys" ++ depends on KEYS ++ help ++ Provide a system keyring to which blacklisted keys can be added. Keys ++ in the keyring are considered entirely untrusted. Keys in this keyring ++ are used by the module signature checking to reject loading of modules ++ signed with a blacklisted key. ++ + menuconfig MODULES + bool "Enable loadable module support" + help diff --git a/kernel/module_signing.c b/kernel/module_signing.c -index f2970bd..5423195 100644 +index 0b6b870..0a29b40 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, +@@ -158,6 +158,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), ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++ key = keyring_search(make_key_ref(system_blacklist_keyring, 1), + &key_type_asymmetric, id); + if (!IS_ERR(key)) { + /* module is signed with a cert in the blacklist. reject */ @@ -334,20 +306,55 @@ index f2970bd..5423195 100644 + } +#endif + - key = keyring_search(make_key_ref(modsign_keyring, 1), + key = keyring_search(make_key_ref(system_trusted_keyring, 1), &key_type_asymmetric, id); if (IS_ERR(key)) +diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c +index 4ca7072..b19cc6e 100644 +--- a/kernel/system_keyring.c ++++ b/kernel/system_keyring.c +@@ -20,6 +20,9 @@ + + struct key *system_trusted_keyring; + EXPORT_SYMBOL_GPL(system_trusted_keyring); ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++struct key *system_blacklist_keyring; ++#endif + + extern __initdata const u8 system_certificate_list[]; + extern __initdata const u8 system_certificate_list_end[]; +@@ -41,6 +44,20 @@ static __init int system_trusted_keyring_init(void) + panic("Can't allocate system trusted keyring\n"); + + set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); ++ ++#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING ++ system_blacklist_keyring = keyring_alloc(".system_blacklist_keyring", ++ 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(system_blacklist_keyring)) ++ panic("Can't allocate system blacklist keyring\n"); ++ ++ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_blacklist_keyring->flags); ++#endif ++ + return 0; + } + -- 1.8.3.1 -From c558b46370e850851a94795df67b7c57aecc48ea Mon Sep 17 00:00:00 2001 +From aa4f39ac51f8b9f589c13766e5e32a5b7794ed68 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 +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 @@ -356,7 +363,7 @@ 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 +the newly introduced system blacklist keyring and forbid any module signed with those from loading. Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org> @@ -364,8 +371,8 @@ 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(+) + 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 @@ -386,16 +393,16 @@ index 42a1d25..d3e6036 100644 efi_guid_t guid; u64 table; diff --git a/init/Kconfig b/init/Kconfig -index b4fa2d1..94ce526 100644 +index 547f617..8e943bf 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. +@@ -1794,6 +1794,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 && MODULE_SIG_BLACKLIST && EFI ++ depends on MODULE_SIG && SYSTEM_BLACKLIST_KEYRING && EFI + select EFI_SIGNATURE_LIST_PARSER + help + This will import certificates stored in UEFI and allow modules @@ -406,18 +413,18 @@ index b4fa2d1..94ce526 100644 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 +index 1ff5e3b..f9b9998 100644 --- a/kernel/Makefile +++ b/kernel/Makefile -@@ -55,6 +55,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o +@@ -56,6 +56,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 modsign_pubkey.o modsign_certificate.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 -@@ -114,6 +115,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o +@@ -115,6 +116,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o $(obj)/configs.o: $(obj)/config_data.h @@ -428,10 +435,10 @@ index 35ef118..6ca1fea 100644 targets += config_data.gz diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c new file mode 100644 -index 0000000..7eae5b4 +index 0000000..94b0eb3 --- /dev/null +++ b/kernel/modsign_uefi.c -@@ -0,0 +1,91 @@ +@@ -0,0 +1,92 @@ +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/cred.h> @@ -439,6 +446,7 @@ index 0000000..7eae5b4 +#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) @@ -493,7 +501,7 @@ index 0000000..7eae5b4 + if (!db) { + pr_err("MODSIGN: Couldn't get UEFI db list\n"); + } else { -+ rc = parse_efi_signature_list(db, dbsize, modsign_keyring); ++ rc = parse_efi_signature_list(db, dbsize, system_trusted_keyring); + if (rc) + pr_err("Couldn't parse db signatures: %d\n", rc); + kfree(db); @@ -503,7 +511,7 @@ index 0000000..7eae5b4 + if (!mok) { + pr_info("MODSIGN: Couldn't get UEFI MokListRT\n"); + } else { -+ rc = parse_efi_signature_list(mok, moksize, modsign_keyring); ++ rc = parse_efi_signature_list(mok, moksize, system_trusted_keyring); + if (rc) + pr_err("Couldn't parse MokListRT signatures: %d\n", rc); + kfree(mok); @@ -514,7 +522,7 @@ index 0000000..7eae5b4 + pr_info("MODSIGN: Couldn't get UEFI dbx list\n"); + } else { + rc = parse_efi_signature_list(dbx, dbxsize, -+ modsign_blacklist); ++ system_blacklist_keyring); + if (rc) + pr_err("Couldn't parse dbx signatures: %d\n", rc); + kfree(dbx); diff --git a/sb-hibernate.patch b/sb-hibernate.patch index 966024b9b..447237c60 100644 --- a/sb-hibernate.patch +++ b/sb-hibernate.patch @@ -1,4 +1,4 @@ -From 4fe6d11d21b548d6e8272cc8cad5fcc6150ef081 Mon Sep 17 00:00:00 2001 +From ffe1ee94d526900ce1e5191cdd38934477dd209a 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 @@ -12,8 +12,8 @@ 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(-) + kernel/power/user.c | 1 + + 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index b26f5f1..e65228b 100644 @@ -96,28 +96,17 @@ index 1d1bf63..300f300 100644 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 +index 15cb72f..fa85ed5 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c -@@ -24,6 +24,8 @@ - #include <linux/console.h> +@@ -25,6 +25,7 @@ #include <linux/cpu.h> #include <linux/freezer.h> + #include <linux/module.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 diff --git a/secure-modules.patch b/secure-modules.patch index d9beaa29f..9d01b9356 100644 --- a/secure-modules.patch +++ b/secure-modules.patch @@ -1,7 +1,7 @@ -From 17832506ee9b52bc8e00c2ec89b49257998171ed Mon Sep 17 00:00:00 2001 +From 8dea807503a1ba88d9e27595daae7f86ec968711 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 +Date: Fri, 9 Aug 2013 17:58:15 -0400 +Subject: [PATCH 01/14] 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 @@ -39,7 +39,7 @@ index 46f1ea0..0c266b2 100644 #ifdef CONFIG_SYSFS diff --git a/kernel/module.c b/kernel/module.c -index 2069158..499ee57 100644 +index 2069158..0e94acf 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3852,3 +3852,13 @@ void module_layout(struct module *mod, @@ -55,15 +55,15 @@ index 2069158..499ee57 100644 + return modules_disabled; +#endif +} -+EXPORT_SYMBOL_GPL(secure_modules); ++EXPORT_SYMBOL(secure_modules); -- 1.8.3.1 -From e347503648ace6a4b71dfb566365f1aa19657746 Mon Sep 17 00:00:00 2001 +From 9b7b3f6283bf784e4ea1c34e52646b12971b2823 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 +Date: Thu, 8 Mar 2012 10:10:38 -0500 +Subject: [PATCH 02/14] PCI: Lock down BAR access when module security is enabled Any hardware that can potentially generate DMA has to be locked down from @@ -179,10 +179,10 @@ index e1c1ec5..bffbf71 100644 1.8.3.1 -From b846e3958d3f4ff875ec958efba8b681ccbae04e Mon Sep 17 00:00:00 2001 +From aac2425a2664c09c2a369e1eec6e7a5bc2713cb1 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 +Date: Thu, 8 Mar 2012 10:35:59 -0500 +Subject: [PATCH 03/14] x86: Lock down IO port access when module security is enabled IO port access would permit users to gain access to PCI configuration @@ -252,10 +252,10 @@ index f895a8c..1af8664 100644 1.8.3.1 -From 8c11e2cc989eece2d4978cfbc83f9b898f3cd1aa Mon Sep 17 00:00:00 2001 +From e7f9789c7eedf291972666befee726ff8e7126f6 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 +Date: Fri, 9 Mar 2012 08:39:37 -0500 +Subject: [PATCH 04/14] 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. @@ -263,22 +263,14 @@ 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(+) + drivers/acpi/custom_method.c | 3 +++ + 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c -index 12b62f2..55a013f 100644 +index 12b62f2..50647b3 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, +@@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, struct acpi_table_header table; acpi_status status; @@ -292,10 +284,10 @@ index 12b62f2..55a013f 100644 1.8.3.1 -From 968ccfb32df5d5c9673c57641ebf90b25c0df880 Mon Sep 17 00:00:00 2001 +From d81cd6628c821d47bd086354cbc57b1474f3c1a8 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 +Date: Fri, 9 Mar 2012 08:46:50 -0500 +Subject: [PATCH 05/14] 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 @@ -347,10 +339,10 @@ index 19c313b..db18ef66 100644 1.8.3.1 -From e492d0a80bb591c34391757f97fc5aa8eb198e4f Mon Sep 17 00:00:00 2001 +From df75e984729ef50bb691b4d15472529fcd81580b 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 +Date: Fri, 9 Mar 2012 09:28:15 -0500 +Subject: [PATCH 06/14] Restrict /dev/mem and /dev/kmem when module loading is restricted Allowing users to write to address space makes it possible for the kernel @@ -390,10 +382,10 @@ index 1af8664..61406c8 100644 1.8.3.1 -From 145913d656bfe8216032b38a576ac150699521e5 Mon Sep 17 00:00:00 2001 +From 78955913cc46cc5e5c7f2c71c1b07a5c18e06456 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 +Date: Mon, 25 Jun 2012 19:57:30 -0400 +Subject: [PATCH 07/14] acpi: Ignore acpi_rsdp kernel parameter when module loading is restricted This option allows userspace to pass the RSDP address to the kernel, which @@ -430,10 +422,95 @@ index 6ab2c35..e4c4410 100644 1.8.3.1 -From 012ac79f54ab746114d8276d8858a3df18b10e22 Mon Sep 17 00:00:00 2001 +From 23aae9143fbece326b3a26bf5ba48956c99cabe4 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett <matthew.garrett@nebula.com> +Date: Fri, 9 Aug 2013 03:33:56 -0400 +Subject: [PATCH 08/14] 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 | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/kernel/kexec.c b/kernel/kexec.c +index 59f7b55..3e2b63a 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> +@@ -943,6 +944,13 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, + return -EPERM; + + /* ++ * kexec can be used to circumvent module loading restrictions, so ++ * prevent loading in that case ++ */ ++ if (secure_modules()) ++ return -EPERM; ++ ++ /* + * Verify we have a legal set of flags + * This leaves us room for future extensions. + */ +-- +1.8.3.1 + + +From 218cd49aa2d6a085c5c4edc0396200864f0b54ad Mon Sep 17 00:00:00 2001 +From: Matthew Garrett <matthew.garrett@nebula.com> +Date: Tue, 3 Sep 2013 11:23:29 -0400 +Subject: [PATCH 09/14] uswsusp: Disable when module loading is restricted + +uswsusp allows a user process to dump and then restore kernel state, which +makes it possible to avoid module loading restrictions. Prevent this when +any restrictions have been imposed on loading modules. + +Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com> +--- + kernel/power/user.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/power/user.c b/kernel/power/user.c +index 4ed81e7..15cb72f 100644 +--- a/kernel/power/user.c ++++ b/kernel/power/user.c +@@ -24,6 +24,7 @@ + #include <linux/console.h> + #include <linux/cpu.h> + #include <linux/freezer.h> ++#include <linux/module.h> + + #include <asm/uaccess.h> + +@@ -48,6 +49,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 + + +From beeaac053d4ae57dc65be1da8b46e5d4bc6542b8 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 +Date: Fri, 8 Feb 2013 11:12:13 -0800 +Subject: [PATCH 10/14] x86: Restrict MSR access when module loading is restricted Writing to MSRs should not be allowed if module loading is restricted, @@ -475,51 +552,10 @@ index 88458fa..d08f7e3 100644 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 b4331711c52aff0a6a9cef0f4b52fe261874d6f2 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 +Date: Fri, 9 Aug 2013 18:36:30 -0400 +Subject: [PATCH 11/14] Add option to automatically enforce module signatures when in Secure Boot mode UEFI Secure Boot provides a mechanism for ensuring that the firmware will @@ -528,17 +564,15 @@ 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(-) + Documentation/x86/zero-page.txt | 2 ++ + arch/x86/Kconfig | 10 ++++++++++ + arch/x86/boot/compressed/eboot.c | 36 +++++++++++++++++++++++++++++++++++ + arch/x86/include/uapi/asm/bootparam.h | 3 ++- + arch/x86/kernel/setup.c | 6 ++++++ + include/linux/module.h | 6 ++++++ + kernel/module.c | 7 +++++++ + 7 files changed, 69 insertions(+), 1 deletion(-) diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt index 199f453..ec38acf 100644 @@ -575,14 +609,22 @@ index b32ebf9..6a6c19b 100644 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 +index b7388a4..53bfe4f 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -861,6 +861,37 @@ fail: +@@ -12,6 +12,7 @@ + #include <asm/efi.h> + #include <asm/setup.h> + #include <asm/desc.h> ++#include <asm/bootparam_utils.h> + + #undef memcpy /* Use memcpy from misc.c */ + +@@ -861,6 +862,37 @@ fail: return status; } -+static int get_secure_boot(efi_system_table_t *_table) ++static int get_secure_boot(void) +{ + u8 sb, setup; + unsigned long datasize = sizeof(sb); @@ -616,37 +658,19 @@ index b7388a4..145294d 100644 /* * 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, +@@ -1169,6 +1201,10 @@ 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); ++ sanitize_boot_params(boot_params); ++ ++ boot_params->secure_boot = get_secure_boot(); + 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 +index c15ddaf..85d7685 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -131,7 +131,8 @@ struct boot_params { @@ -655,7 +679,7 @@ index c15ddaf..d35da96 100644 __u8 kbd_status; /* 0x1eb */ - __u8 _pad5[3]; /* 0x1ec */ + __u8 secure_boot; /* 0x1ec */ -+ __u8 _pad5[2]; /* 0x1ec */ ++ __u8 _pad5[2]; /* 0x1ed */ /* * The sentinel is set to a nonzero value (0xff) in header.S. * @@ -694,7 +718,7 @@ index 0c266b2..5a6374a 100644 extern int modules_disabled; /* for sysctl */ diff --git a/kernel/module.c b/kernel/module.c -index 499ee57..bc7c987 100644 +index 0e94acf..974139b 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3853,6 +3853,13 @@ void module_layout(struct module *mod, @@ -715,10 +739,10 @@ index 499ee57..bc7c987 100644 1.8.3.1 -From b1604407fff69b17b598af03888a9efda0d58f2b Mon Sep 17 00:00:00 2001 +From bb28516d346e6511f1e012321c48eb142763e539 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 +Subject: [PATCH 12/14] 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 @@ -732,12 +756,12 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com> 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 +index 53bfe4f..946028b 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c -@@ -863,8 +863,9 @@ fail: +@@ -864,8 +864,9 @@ fail: - static int get_secure_boot(efi_system_table_t *_table) + static int get_secure_boot(void) { - u8 sb, setup; + u8 sb, setup, moksbstate; @@ -746,7 +770,7 @@ index 145294d..545d4a6 100644 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) +@@ -889,6 +890,23 @@ static int get_secure_boot(void) if (setup == 1) return 0; @@ -774,10 +798,10 @@ index 145294d..545d4a6 100644 1.8.3.1 -From 4d8b5cab923a2df15e1f33b3f0511366f9f98756 Mon Sep 17 00:00:00 2001 +From 4c8824bac8d4284e66c39c365ba84151f2d78e87 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 +Subject: [PATCH 13/14] 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. @@ -805,10 +829,10 @@ index 6a6c19b..10498ec 100644 1.8.3.1 -From a87ca6498b8a9f8e3c1d7e6ef7ef4e233ec8639d Mon Sep 17 00:00:00 2001 +From 871b0ed1847c3c5413a4ca72ecf18735858f7708 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 +Subject: [PATCH 14/14] 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. |