183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Matthew Garrett <matthew.garrett@nebula.com>
 | |
| Date: Fri, 9 Aug 2013 18:36:30 -0400
 | |
| Subject: [PATCH] Add option to automatically enforce module signatures when in
 | |
|  Secure Boot mode
 | |
| 
 | |
| UEFI Secure Boot provides a mechanism for ensuring that the firmware will
 | |
| only load signed bootloaders and kernels. Certain use cases may also
 | |
| require that all kernel modules also be signed. Add a configuration option
 | |
| that enforces this automatically when enabled.
 | |
| 
 | |
| Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
 | |
| ---
 | |
|  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 82fbdbc1e0b0..a811210ad486 100644
 | |
| --- a/Documentation/x86/zero-page.txt
 | |
| +++ b/Documentation/x86/zero-page.txt
 | |
| @@ -30,6 +30,8 @@ Offset	Proto	Name		Meaning
 | |
|  1E9/001	ALL	eddbuf_entries	Number of entries in eddbuf (below)
 | |
|  1EA/001	ALL	edd_mbr_sig_buf_entries	Number of entries in edd_mbr_sig_buffer
 | |
|  				(below)
 | |
| +1EB/001	ALL     kbd_status      Numlock is enabled
 | |
| +1EC/001	ALL     secure_boot	Secure boot is enabled in the firmware
 | |
|  1EF/001	ALL	sentinel	Used to detect broken bootloaders
 | |
|  290/040	ALL	edd_mbr_sig_buffer EDD MBR signatures
 | |
|  2D0/A00	ALL	e820_map	E820 memory map table
 | |
| diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
 | |
| index 226d5696e1d1..6a8f880e213f 100644
 | |
| --- a/arch/x86/Kconfig
 | |
| +++ b/arch/x86/Kconfig
 | |
| @@ -1697,6 +1697,16 @@ config EFI_MIXED
 | |
|  
 | |
|  	   If unsure, say N.
 | |
|  
 | |
| +config EFI_SECURE_BOOT_SIG_ENFORCE
 | |
| +        def_bool n
 | |
| +	prompt "Force module signing when UEFI Secure Boot is enabled"
 | |
| +	---help---
 | |
| +	  UEFI Secure Boot provides a mechanism for ensuring that the
 | |
| +	  firmware will only load signed bootloaders and kernels. Certain
 | |
| +	  use cases may also require that all kernel modules also be signed.
 | |
| +	  Say Y here to automatically enable module signature enforcement
 | |
| +	  when a system boots with UEFI Secure Boot enabled.
 | |
| +
 | |
|  config SECCOMP
 | |
|  	def_bool y
 | |
|  	prompt "Enable seccomp to safely compute untrusted bytecode"
 | |
| diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
 | |
| index 48304b89b601..2ff19014117a 100644
 | |
| --- a/arch/x86/boot/compressed/eboot.c
 | |
| +++ b/arch/x86/boot/compressed/eboot.c
 | |
| @@ -12,6 +12,7 @@
 | |
|  #include <asm/efi.h>
 | |
|  #include <asm/setup.h>
 | |
|  #include <asm/desc.h>
 | |
| +#include <asm/bootparam_utils.h>
 | |
|  
 | |
|  #include "../string.h"
 | |
|  #include "eboot.h"
 | |
| @@ -827,6 +828,37 @@ out:
 | |
|  	return status;
 | |
|  }
 | |
|  
 | |
| +static int get_secure_boot(void)
 | |
| +{
 | |
| +	u8 sb, setup;
 | |
| +	unsigned long datasize = sizeof(sb);
 | |
| +	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
 | |
| +	efi_status_t status;
 | |
| +
 | |
| +	status = efi_early->call((unsigned long)sys_table->runtime->get_variable,
 | |
| +				L"SecureBoot", &var_guid, NULL, &datasize, &sb);
 | |
| +
 | |
| +	if (status != EFI_SUCCESS)
 | |
| +		return 0;
 | |
| +
 | |
| +	if (sb == 0)
 | |
| +		return 0;
 | |
| +
 | |
| +
 | |
| +	status = efi_early->call((unsigned long)sys_table->runtime->get_variable,
 | |
| +				L"SetupMode", &var_guid, NULL, &datasize,
 | |
| +				&setup);
 | |
| +
 | |
| +	if (status != EFI_SUCCESS)
 | |
| +		return 0;
 | |
| +
 | |
| +	if (setup == 1)
 | |
| +		return 0;
 | |
| +
 | |
| +	return 1;
 | |
| +}
 | |
| +
 | |
| +
 | |
|  /*
 | |
|   * See if we have Graphics Output Protocol
 | |
|   */
 | |
| @@ -1408,6 +1440,10 @@ struct boot_params *efi_main(struct efi_config *c,
 | |
|  	else
 | |
|  		setup_boot_services32(efi_early);
 | |
|  
 | |
| +	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/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
 | |
| index ab456dc233b5..74ba4083e7ce 100644
 | |
| --- a/arch/x86/include/uapi/asm/bootparam.h
 | |
| +++ b/arch/x86/include/uapi/asm/bootparam.h
 | |
| @@ -134,7 +134,8 @@ struct boot_params {
 | |
|  	__u8  eddbuf_entries;				/* 0x1e9 */
 | |
|  	__u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
 | |
|  	__u8  kbd_status;				/* 0x1eb */
 | |
| -	__u8  _pad5[3];					/* 0x1ec */
 | |
| +	__u8  secure_boot;				/* 0x1ec */
 | |
| +	__u8  _pad5[2];					/* 0x1ed */
 | |
|  	/*
 | |
|  	 * The sentinel is set to a nonzero value (0xff) in header.S.
 | |
|  	 *
 | |
| diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
 | |
| index d74ac33290ae..88dad730e858 100644
 | |
| --- a/arch/x86/kernel/setup.c
 | |
| +++ b/arch/x86/kernel/setup.c
 | |
| @@ -1156,6 +1156,12 @@ void __init setup_arch(char **cmdline_p)
 | |
|  
 | |
|  	io_delay_init();
 | |
|  
 | |
| +#ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE
 | |
| +	if (boot_params.secure_boot) {
 | |
| +		enforce_signed_modules();
 | |
| +	}
 | |
| +#endif
 | |
| +
 | |
|  	/*
 | |
|  	 * Parse the ACPI tables for possible boot-time SMP configuration.
 | |
|  	 */
 | |
| diff --git a/include/linux/module.h b/include/linux/module.h
 | |
| index cdc46a791b9d..0c1edd33a42c 100644
 | |
| --- a/include/linux/module.h
 | |
| +++ b/include/linux/module.h
 | |
| @@ -188,6 +188,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long add);
 | |
|  
 | |
|  struct notifier_block;
 | |
|  
 | |
| +#ifdef CONFIG_MODULE_SIG
 | |
| +extern void enforce_signed_modules(void);
 | |
| +#else
 | |
| +static inline void enforce_signed_modules(void) {};
 | |
| +#endif
 | |
| +
 | |
|  #ifdef CONFIG_MODULES
 | |
|  
 | |
|  extern int modules_disabled; /* for sysctl */
 | |
| diff --git a/kernel/module.c b/kernel/module.c
 | |
| index f43cbdd52546..feb6736fec91 100644
 | |
| --- a/kernel/module.c
 | |
| +++ b/kernel/module.c
 | |
| @@ -3913,6 +3913,13 @@ void module_layout(struct module *mod,
 | |
|  EXPORT_SYMBOL(module_layout);
 | |
|  #endif
 | |
|  
 | |
| +#ifdef CONFIG_MODULE_SIG
 | |
| +void enforce_signed_modules(void)
 | |
| +{
 | |
| +	sig_enforce = true;
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
|  bool secure_modules(void)
 | |
|  {
 | |
|  #ifdef CONFIG_MODULE_SIG
 |