From 9f4ac2c2dcee7fd1b708f5f0b3d6c5832638fb57 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 21 Nov 2016 23:55:55 +0000 Subject: [PATCH 01/25] 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 | 1 + include/linux/efi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 3486d04988000b..319995f5834562 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1190,6 +1190,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 8269bcb8ccf796..7952dd3ffa7378 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1081,6 +1081,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 /* From f7364eee64c715ffe9266d8ea55d52154becf879 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 21 Nov 2016 23:36:17 +0000 Subject: [PATCH 02/25] 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 bd6d96cf80b17c..65692c80aa1a3f 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -277,6 +277,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 b6ea1dc9cc9d2b..834b355fa298fd 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1764,5 +1764,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 e8e449444e658b..1a84ed33c09a33 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -205,6 +205,21 @@ config STATIC_USERMODEHELPER_PATH If you wish for all usermode helper programs to be disabled, specify an empty string here (i.e. ""). +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 f2d71cdb8e19b1..8c4a43e3d4e030 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 00000000000000..5788c60ff4e17b --- /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); From c3b1b1051e324f57e37254563bb7364a350efeb1 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 21 Nov 2016 23:55:55 +0000 Subject: [PATCH 03/25] 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 323cb065be5eda..8e41d54d649892 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1836,6 +1836,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 319995f5834562..d0128aef43ce84 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -69,6 +69,7 @@ #include #include #include +#include #include #include