From 9079547f4808ea5c8cd844bf40d3895994bd175e Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 21 Nov 2016 23:55:55 +0000 Subject: [PATCH 07/32] efi: Add EFI_SECURE_BOOT bit UEFI machines can be booted in Secure Boot mode. Add a EFI_SECURE_BOOT bit that can be passed to efi_enabled() to find out whether secure boot is enabled. This will be used by the SysRq+x handler, registered by the x86 arch, to find out whether secure boot mode is enabled so that it can be disabled. Signed-off-by: Josh Boyer Signed-off-by: David Howells --- arch/x86/kernel/setup.c | 15 +++++++++++++++ include/linux/efi.h | 1 + 2 files changed, 16 insertions(+) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 69780ed..447905e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1182,6 +1182,7 @@ void __init setup_arch(char **cmdline_p) pr_info("Secure boot disabled\n"); break; case efi_secureboot_mode_enabled: + set_bit(EFI_SECURE_BOOT, &efi.flags); pr_info("Secure boot enabled\n"); break; default: diff --git a/include/linux/efi.h b/include/linux/efi.h index 94d34e0..6049600 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1069,6 +1069,7 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_DBG 8 /* Print additional debug info at runtime */ #define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */ #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */ +#define EFI_SECURE_BOOT 11 /* Are we in Secure Boot mode? */ #ifdef CONFIG_EFI /* -- 2.9.3 From eada0243f0b8fc21588a21c564187219dee03e3c Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 25 Nov 2016 11:52:05 +0000 Subject: [PATCH 08/32] efi: Handle secure boot from UEFI-2.6 UEFI-2.6 adds a new variable, DeployedMode. If it exists, this must be 1 if we're to engage lockdown mode. Reported-by: James Bottomley Signed-off-by: David Howells --- drivers/firmware/efi/libstub/secureboot.c | 16 +++++++++++++++- include/linux/efi.h | 4 ++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/efi/libstub/secureboot.c b/drivers/firmware/efi/libstub/secureboot.c index ba6ef71..333b159 100644 --- a/drivers/firmware/efi/libstub/secureboot.c +++ b/drivers/firmware/efi/libstub/secureboot.c @@ -22,6 +22,9 @@ static const efi_char16_t const efi_SecureBoot_name[] = { static const efi_char16_t const efi_SetupMode_name[] = { 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; +static const efi_char16_t const efi_DeployedMode_name[] = { + 'D', 'e', 'p', 'l', 'o', 'y', 'e', 'd', 'M', 'o', 'd', 'e', 0 +}; /* SHIM variables */ static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID; @@ -40,7 +43,7 @@ static efi_char16_t const shim_MokSBState_name[] = { enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg) { u32 attr; - u8 secboot, setupmode, moksbstate; + u8 secboot, setupmode, deployedmode, moksbstate; unsigned long size; efi_status_t status; @@ -57,6 +57,17 @@ enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg) if (secboot == 0 || setupmode == 1) return efi_secureboot_mode_disabled; + /* UEFI-2.6 requires DeployedMode to be 1. */ + if (sys_table_arg->hdr.revision >= EFI_2_60_SYSTEM_TABLE_REVISION) { + size = sizeof(deployedmode); + status = get_efi_var(efi_DeployedMode_name, &efi_variable_guid, + NULL, &size, &deployedmode); + if (status != EFI_SUCCESS) + goto out_efi_err; + if (deployedmode == 0) + return efi_secureboot_mode_disabled; + } + /* * See if a user has put the shim into insecure mode. If so, and if the * variable doesn't have the runtime attribute set, we might as well * honor that. diff --git a/include/linux/efi.h b/include/linux/efi.h index 135ca9c..e1893f5 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -645,6 +645,10 @@ typedef struct { #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) +#define EFI_2_60_SYSTEM_TABLE_REVISION ((2 << 16) | (60)) +#define EFI_2_50_SYSTEM_TABLE_REVISION ((2 << 16) | (50)) +#define EFI_2_40_SYSTEM_TABLE_REVISION ((2 << 16) | (40)) +#define EFI_2_31_SYSTEM_TABLE_REVISION ((2 << 16) | (31)) #define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) #define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) #define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) -- 2.9.3 From 3b0695eda22ad712a2b9be9bb70979d875a37816 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 21 Nov 2016 23:36:17 +0000 Subject: [PATCH 09/32] Add the ability to lock down access to the running kernel image Provide a single call to allow kernel code to determine whether the system should be locked down, thereby disallowing various accesses that might allow the running kernel image to be changed including the loading of modules that aren't validly signed with a key we recognise, fiddling with MSR registers and disallowing hibernation, Signed-off-by: David Howells --- include/linux/kernel.h | 9 +++++++++ include/linux/security.h | 11 +++++++++++ security/Kconfig | 15 +++++++++++++++ security/Makefile | 3 +++ security/lock_down.c | 40 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 security/lock_down.c diff --git a/include/linux/kernel.h b/include/linux/kernel.h index bc6ed52..8ab309d 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -268,6 +268,15 @@ extern int oops_may_print(void); void do_exit(long error_code) __noreturn; void complete_and_exit(struct completion *, long) __noreturn; +#ifdef CONFIG_LOCK_DOWN_KERNEL +extern bool kernel_is_locked_down(void); +#else +static inline bool kernel_is_locked_down(void) +{ + return false; +} +#endif + /* Internal, do not use. */ int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res); int __must_check _kstrtol(const char *s, unsigned int base, long *res); diff --git a/include/linux/security.h b/include/linux/security.h index c2125e9..41a7325 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1685,5 +1685,16 @@ static inline void free_secdata(void *secdata) { } #endif /* CONFIG_SECURITY */ +#ifdef CONFIG_LOCK_DOWN_KERNEL +extern void lock_kernel_down(void); +#ifdef CONFIG_ALLOW_LOCKDOWN_LIFT +extern void lift_kernel_lockdown(void); +#endif +#else +static inline void lock_kernel_down(void) +{ +} +#endif + #endif /* ! __LINUX_SECURITY_H */ diff --git a/security/Kconfig b/security/Kconfig index 118f454..fa1a678 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -158,6 +158,21 @@ config HARDENED_USERCOPY_PAGESPAN been removed. This config is intended to be used only while trying to find such users. +config LOCK_DOWN_KERNEL + bool "Allow the kernel to be 'locked down'" + help + Allow the kernel to be locked down under certain circumstances, for + instance if UEFI secure boot is enabled. Locking down the kernel + turns off various features that might otherwise allow access to the + kernel image (eg. setting MSR registers). + +config ALLOW_LOCKDOWN_LIFT + bool + help + Allow the lockdown on a kernel to be lifted, thereby restoring the + ability of userspace to access the kernel image (eg. by SysRq+x under + x86). + source security/selinux/Kconfig source security/smack/Kconfig source security/tomoyo/Kconfig diff --git a/security/Makefile b/security/Makefile index f2d71cd..8c4a43e 100644 --- a/security/Makefile +++ b/security/Makefile @@ -29,3 +29,6 @@ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o # Object integrity file lists subdir-$(CONFIG_INTEGRITY) += integrity obj-$(CONFIG_INTEGRITY) += integrity/ + +# Allow the kernel to be locked down +obj-$(CONFIG_LOCK_DOWN_KERNEL) += lock_down.o diff --git a/security/lock_down.c b/security/lock_down.c new file mode 100644 index 0000000..5788c60 --- /dev/null +++ b/security/lock_down.c @@ -0,0 +1,40 @@ +/* Lock down the kernel + * + * Copyright (C) 2016 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 +#include + +static __read_mostly bool kernel_locked_down; + +/* + * Put the kernel into lock-down mode. + */ +void lock_kernel_down(void) +{ + kernel_locked_down = true; +} + +/* + * Take the kernel out of lockdown mode. + */ +void lift_kernel_lockdown(void) +{ + kernel_locked_down = false; +} + +/** + * kernel_is_locked_down - Find out if the kernel is locked down + */ +bool kernel_is_locked_down(void) +{ + return kernel_locked_down; +} +EXPORT_SYMBOL(kernel_is_locked_down); -- 2.9.3 From c1cc643f82e1c9efee123eb81befb58e41b87310 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 21 Nov 2016 23:55:55 +0000 Subject: [PATCH 10/32] efi: Lock down the kernel if booted 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 to lock down the kernel - which includes requiring validly signed modules - if the kernel is secure-booted. Signed-off-by: David Howells --- arch/x86/Kconfig | 12 ++++++++++++ arch/x86/kernel/setup.c | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bada636..5b19997 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1786,6 +1786,18 @@ config EFI_MIXED If unsure, say N. +config EFI_SECURE_BOOT_LOCK_DOWN + def_bool n + depends on EFI + prompt "Lock down the kernel 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 and that + userspace is prevented from directly changing the running kernel + image. Say Y here to automatically lock down the kernel 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/kernel/setup.c b/arch/x86/kernel/setup.c index d8972ec..facaeb9 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -69,6 +69,7 @@ #include #include #include +#include #include