From: Ben Hutchings Date: Tue, 10 Sep 2019 11:54:28 +0100 Subject: efi: Lock down the kernel if booted in secure boot mode Based on an earlier patch by David Howells, who wrote the following description: > 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: Ben Hutchings [Salvatore Bonaccorso: After fixing https://bugs.debian.org/956197 the help text for LOCK_DOWN_IN_EFI_SECURE_BOOT was adjusted to mention that lockdown is triggered in integrity mode (https://bugs.debian.org/1025417)] Signed-off-by: Salvatore Bonaccorso --- arch/x86/kernel/setup.c | 4 ++-- drivers/firmware/efi/secureboot.c | 3 +++ include/linux/security.h | 6 ++++++ security/lockdown/Kconfig | 15 +++++++++++++++ security/lockdown/lockdown.c | 2 +- 5 files changed, 27 insertions(+), 3 deletions(-) --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1031,6 +1031,8 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled(EFI_BOOT)) efi_init(); + efi_set_secure_boot(boot_params.secure_boot); + reserve_ibft_region(); dmi_setup(); @@ -1192,8 +1194,6 @@ void __init setup_arch(char **cmdline_p) /* Allocate bigger log buffer */ setup_log_buf(1); - efi_set_secure_boot(boot_params.secure_boot); - reserve_initrd(); acpi_table_upgrade(); --- a/drivers/firmware/efi/secureboot.c +++ b/drivers/firmware/efi/secureboot.c @@ -15,6 +15,7 @@ #include #include #include +#include /* * Decide what to do when UEFI secure boot mode is enabled. @@ -28,6 +29,10 @@ void __init efi_set_secure_boot(enum efi break; case efi_secureboot_mode_enabled: set_bit(EFI_SECURE_BOOT, &efi.flags); +#ifdef CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT + lock_kernel_down("EFI Secure Boot", + LOCKDOWN_INTEGRITY_MAX); +#endif pr_info("Secure boot enabled\n"); break; default: --- a/include/linux/security.h +++ b/include/linux/security.h @@ -482,6 +482,7 @@ int security_inode_notifysecctx(struct i int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); int security_locked_down(enum lockdown_reason what); +int lock_kernel_down(const char *where, enum lockdown_reason level); #else /* CONFIG_SECURITY */ static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) @@ -1388,6 +1389,11 @@ static inline int security_locked_down(e { return 0; } +static inline int +lock_kernel_down(const char *where, enum lockdown_reason level) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_SECURITY */ #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) --- a/security/lockdown/Kconfig +++ b/security/lockdown/Kconfig @@ -45,3 +45,18 @@ config LOCK_DOWN_KERNEL_FORCE_CONFIDENTI disabled. endchoice + +config LOCK_DOWN_IN_EFI_SECURE_BOOT + bool "Lock down the kernel in EFI Secure Boot mode" + default n + depends on SECURITY_LOCKDOWN_LSM + depends on EFI + select SECURITY_LOCKDOWN_LSM_EARLY + help + UEFI Secure Boot provides a mechanism for ensuring that the firmware + will only load signed bootloaders and kernels. Secure boot mode may + be determined from EFI variables provided by the system firmware if + not indicated by the boot parameters. + + Enabling this option results in kernel lockdown being + triggered in integrity mode if EFI Secure Boot is set. --- a/security/lockdown/lockdown.c +++ b/security/lockdown/lockdown.c @@ -23,7 +23,7 @@ static const enum lockdown_reason lockdo /* * Put the kernel into lock-down mode. */ -static int lock_kernel_down(const char *where, enum lockdown_reason level) +int lock_kernel_down(const char *where, enum lockdown_reason level) { if (kernel_locked_down >= level) return -EPERM;