- Enable CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE (rhbz 1339281) - Fixup SB patchset to work with upstream changes
		
			
				
	
	
		
			232 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From ba2b209daf984514229626803472e0b055832345 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>
 | |
| ---
 | |
|  certs/system_keyring.c        | 13 ++++++
 | |
|  include/keys/system_keyring.h |  1 +
 | |
|  include/linux/efi.h           |  6 +++
 | |
|  init/Kconfig                  |  9 ++++
 | |
|  kernel/Makefile               |  3 ++
 | |
|  kernel/modsign_uefi.c         | 99 +++++++++++++++++++++++++++++++++++++++++++
 | |
|  6 files changed, 131 insertions(+)
 | |
|  create mode 100644 kernel/modsign_uefi.c
 | |
| 
 | |
| diff --git a/certs/system_keyring.c b/certs/system_keyring.c
 | |
| index 787eeead2f57..4d9123ed5c07 100644
 | |
| --- a/certs/system_keyring.c
 | |
| +++ b/certs/system_keyring.c
 | |
| @@ -30,6 +30,19 @@ extern __initconst const u8 system_certificate_list[];
 | |
|  extern __initconst const unsigned long system_certificate_list_size;
 | |
|  
 | |
|  /**
 | |
| + * get_system_keyring - Return a pointer to the system keyring
 | |
| + *
 | |
| + */
 | |
| +struct key *get_system_keyring(void)
 | |
| +{
 | |
| +	struct key *system_keyring = NULL;
 | |
| +
 | |
| +	system_keyring = builtin_trusted_keys;
 | |
| +	return system_keyring;
 | |
| +}
 | |
| +EXPORT_SYMBOL_GPL(get_system_keyring);
 | |
| +
 | |
| +/**
 | |
|   * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
 | |
|   *
 | |
|   * Restrict the addition of keys into a keyring based on the key-to-be-added
 | |
| diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
 | |
| index 5bc291a3d261..56ff5715ab67 100644
 | |
| --- a/include/keys/system_keyring.h
 | |
| +++ b/include/keys/system_keyring.h
 | |
| @@ -36,6 +36,7 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
 | |
|  #ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
 | |
|  extern struct key *system_blacklist_keyring;
 | |
|  #endif
 | |
| +extern struct key *get_system_keyring(void);
 | |
|  
 | |
|  #ifdef CONFIG_IMA_BLACKLIST_KEYRING
 | |
|  extern struct key *ima_blacklist_keyring;
 | |
| diff --git a/include/linux/efi.h b/include/linux/efi.h
 | |
| index ff1877145aa4..2483de19c719 100644
 | |
| --- a/include/linux/efi.h
 | |
| +++ b/include/linux/efi.h
 | |
| @@ -658,6 +658,12 @@ typedef struct {
 | |
|  	u64 table;
 | |
|  } efi_config_table_64_t;
 | |
|  
 | |
| +#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;
 | |
|  	u32 table;
 | |
| diff --git a/init/Kconfig b/init/Kconfig
 | |
| index e5449d5aeff9..5408c96f6604 100644
 | |
| --- a/init/Kconfig
 | |
| +++ b/init/Kconfig
 | |
| @@ -1979,6 +1979,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 e2ec54e2b952..8dab549985d8 100644
 | |
| --- a/kernel/Makefile
 | |
| +++ b/kernel/Makefile
 | |
| @@ -57,6 +57,7 @@ endif
 | |
|  obj-$(CONFIG_UID16) += uid16.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_CORE) += kexec_core.o
 | |
| @@ -113,6 +114,8 @@ obj-$(CONFIG_MEMBARRIER) += membarrier.o
 | |
|  
 | |
|  obj-$(CONFIG_HAS_IOMEM) += memremap.o
 | |
|  
 | |
| +$(obj)/modsign_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 | |
| +
 | |
|  $(obj)/configs.o: $(obj)/config_data.h
 | |
|  
 | |
|  # config_data.h contains the same information as ikconfig.h but gzipped.
 | |
| diff --git a/kernel/modsign_uefi.c b/kernel/modsign_uefi.c
 | |
| new file mode 100644
 | |
| index 000000000000..fe4a6f2bf10a
 | |
| --- /dev/null
 | |
| +++ b/kernel/modsign_uefi.c
 | |
| @@ -0,0 +1,99 @@
 | |
| +#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;
 | |
| +	struct key *keyring = NULL;
 | |
| +
 | |
| +	/* Check if SB is enabled and just return if not */
 | |
| +	if (!efi_enabled(EFI_SECURE_BOOT))
 | |
| +		return 0;
 | |
| +
 | |
| +	keyring = get_system_keyring();
 | |
| +	if (!keyring) {
 | |
| +		pr_err("MODSIGN: Couldn't get system keyring\n");
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +
 | |
| +	/* 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, 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, 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);
 | |
| -- 
 | |
| 2.5.5
 | |
| 
 |