From 536c343918fd884048ddebb571a4b10cc748cdca Mon Sep 17 00:00:00 2001 From: Linn Crosetto Date: Tue, 30 Aug 2016 11:54:38 -0600 Subject: [PATCH 1/4] arm64: add kernel config option to lock down when in Secure Boot mode Add a kernel configuration option to lock down the kernel, to restrict userspace's ability to modify the running kernel when UEFI Secure Boot is enabled. Based on the x86 patch by Matthew Garrett. Determine the state of Secure Boot in the EFI stub and pass this to the kernel using the FDT. Signed-off-by: Linn Crosetto [bwh: Forward-ported to 4.10: adjust context] [Lukas Wunner: Forward-ported to 4.11: drop parts applied upstream] [bwh: Forward-ported to 4.15 and lockdown patch set: - Pass result of efi_get_secureboot() in stub through to efi_set_secure_boot() in main kernel - Use lockdown API and naming] [bwh: Forward-ported to 4.19.3: adjust context in update_fdt()] [dannf: Moved init_lockdown() call after uefi_init(), fixing SB detection] [bwh: Drop call to init_lockdown(), as efi_set_secure_boot() now calls this] [bwh: Forward-ported to 5.6: efi_get_secureboot() no longer takes a sys_table parameter] [bwh: Forward-ported to 5.7: EFI initialisation from FDT was rewritten, so: - Add Secure Boot mode to the parameter enumeration in fdtparams.c - Add a parameter to efi_get_fdt_params() to return the Secure Boot mode - Since Xen does not have a property name defined for Secure Boot mode, change efi_get_fdt_prop() to handle a missing property name by clearing the output variable] [Salvatore Bonaccorso: Forward-ported to 5.10: f30f242fb131 ("efi: Rename arm-init to efi-init common for all arch") renamed arm-init.c to efi-init.c] --- drivers/firmware/efi/efi-init.c | 5 ++++- drivers/firmware/efi/fdtparams.c | 12 +++++++++++- drivers/firmware/efi/libstub/fdt.c | 6 ++++++ include/linux/efi.h | 3 ++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c index 59b0d7197b685..e63f8a82d9f43 100644 --- a/drivers/firmware/efi/efi-init.c +++ b/drivers/firmware/efi/efi-init.c @@ -204,9 +204,10 @@ void __init efi_init(void) { struct efi_memory_map_data data; u64 efi_system_table; + u32 secure_boot; /* Grab UEFI information placed in FDT by stub */ - efi_system_table = efi_get_fdt_params(&data); + efi_system_table = efi_get_fdt_params(&data, &secure_boot); if (!efi_system_table) return; @@ -228,6 +229,8 @@ void __init efi_init(void) return; } + efi_set_secure_boot(secure_boot); + reserve_regions(); /* * For memblock manipulation, the cap should come after the memblock_add(). diff --git a/drivers/firmware/efi/fdtparams.c b/drivers/firmware/efi/fdtparams.c index 0ec83ba580972..81a0ac408cf58 100644 --- a/drivers/firmware/efi/fdtparams.c +++ b/drivers/firmware/efi/fdtparams.c @@ -16,6 +16,7 @@ enum { MMSIZE, DCSIZE, DCVERS, + SBMODE, PARAMCOUNT }; @@ -26,6 +27,7 @@ static __initconst const char name[][22] = { [MMSIZE] = "MemMap Size ", [DCSIZE] = "MemMap Desc. Size ", [DCVERS] = "MemMap Desc. Version ", + [SBMODE] = "Secure Boot Enabled ", }; static __initconst const struct { @@ -43,6 +45,7 @@ static __initconst const struct { [MMSIZE] = "xen,uefi-mmap-size", [DCSIZE] = "xen,uefi-mmap-desc-size", [DCVERS] = "xen,uefi-mmap-desc-ver", + [SBMODE] = "", } }, { #endif @@ -53,6 +56,7 @@ static __initconst const struct { [MMSIZE] = "linux,uefi-mmap-size", [DCSIZE] = "linux,uefi-mmap-desc-size", [DCVERS] = "linux,uefi-mmap-desc-ver", + [SBMODE] = "linux,uefi-secure-boot", } } }; @@ -64,6 +68,11 @@ static int __init efi_get_fdt_prop(const void *fdt, int node, const char *pname, int len; u64 val; + if (!pname[0]) { + memset(var, 0, size); + return 0; + } + prop = fdt_getprop(fdt, node, pname, &len); if (!prop) return 1; @@ -81,7 +90,7 @@ static int __init efi_get_fdt_prop(const void *fdt, int node, const char *pname, return 0; } -u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm) +u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm, u32 *secure_boot) { const void *fdt = initial_boot_params; unsigned long systab; @@ -95,6 +104,7 @@ u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm) [MMSIZE] = { &mm->size, sizeof(mm->size) }, [DCSIZE] = { &mm->desc_size, sizeof(mm->desc_size) }, [DCVERS] = { &mm->desc_version, sizeof(mm->desc_version) }, + [SBMODE] = { secure_boot, sizeof(*secure_boot) }, }; BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name)); diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 6a337f1f8787b..6c679da644dd6 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -132,6 +132,12 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size, } } + fdt_val32 = cpu_to_fdt32(efi_get_secureboot()); + status = fdt_setprop(fdt, node, "linux,uefi-secure-boot", + &fdt_val32, sizeof(fdt_val32)); + if (status) + goto fdt_set_fail; + /* Shrink the FDT back to its minimum size: */ fdt_pack(fdt); diff --git a/include/linux/efi.h b/include/linux/efi.h index 80b21d1c6eafa..3246c35c6936f 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -756,7 +756,8 @@ extern void efi_mem_reserve(phys_addr_t addr, u64 size); extern int efi_mem_reserve_persistent(phys_addr_t addr, u64 size); extern void efi_initialize_iomem_resources(struct resource *code_resource, struct resource *data_resource, struct resource *bss_resource); -extern u64 efi_get_fdt_params(struct efi_memory_map_data *data); +extern u64 efi_get_fdt_params(struct efi_memory_map_data *data, + u32 *secure_boot); extern struct kobject *efi_kobj; extern int efi_reboot_quirk_mode; From 7cb46ee2f7862f5f13c14b60a23488f489cd718b Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 18 Feb 2019 12:45:03 +0000 Subject: [PATCH 2/4] efi: Add an EFI_SECURE_BOOT flag to indicate secure boot mode UEFI machines can be booted in Secure Boot mode. Add an EFI_SECURE_BOOT flag that can be passed to efi_enabled() to find out whether secure boot is enabled. Move the switch-statement in x86's setup_arch() that inteprets the secure_boot boot parameter to generic code and set the bit there. Suggested-by: Ard Biesheuvel Signed-off-by: David Howells Reviewed-by: Ard Biesheuvel cc: linux-efi@vger.kernel.org [rperier: Forward-ported to 5.5: - Use pr_warn() - Adjust context] [bwh: Forward-ported to 5.6: adjust context] [bwh: Forward-ported to 5.7: - Use the next available bit in efi.flags - Adjust context] --- arch/x86/kernel/setup.c | 14 +---------- drivers/firmware/efi/Makefile | 1 + drivers/firmware/efi/secureboot.c | 39 +++++++++++++++++++++++++++++++ include/linux/efi.h | 17 ++++++++------ 4 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 drivers/firmware/efi/secureboot.c diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index eb129277dcdd6..7c4a6697e39d2 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1190,19 +1190,7 @@ void __init setup_arch(char **cmdline_p) /* Allocate bigger log buffer */ setup_log_buf(1); - if (efi_enabled(EFI_BOOT)) { - switch (boot_params.secure_boot) { - case efi_secureboot_mode_disabled: - pr_info("Secure boot disabled\n"); - break; - case efi_secureboot_mode_enabled: - pr_info("Secure boot enabled\n"); - break; - default: - pr_info("Secure boot could not be determined\n"); - break; - } - } + efi_set_secure_boot(boot_params.secure_boot); reserve_initrd(); diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index e489fefd23dae..f2dfae764fb5e 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -25,6 +25,7 @@ subdir-$(CONFIG_EFI_STUB) += libstub obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o obj-$(CONFIG_EFI_TEST) += test/ obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o +obj-$(CONFIG_EFI) += secureboot.o obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o diff --git a/drivers/firmware/efi/secureboot.c b/drivers/firmware/efi/secureboot.c new file mode 100644 index 0000000000000..b6620669e32bc --- /dev/null +++ b/drivers/firmware/efi/secureboot.c @@ -0,0 +1,39 @@ + +/* Core kernel secure boot support. + * + * Copyright (C) 2017 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. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include + +/* + * Decide what to do when UEFI secure boot mode is enabled. + */ +void __init efi_set_secure_boot(enum efi_secureboot_mode mode) +{ + if (efi_enabled(EFI_BOOT)) { + switch (mode) { + case efi_secureboot_mode_disabled: + 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: + pr_warn("Secure boot could not be determined (mode %u)\n", + mode); + break; + } + } +} diff --git a/include/linux/efi.h b/include/linux/efi.h index 3246c35c6936f..fbce526768d3e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -872,6 +872,14 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */ #define EFI_MEM_NO_SOFT_RESERVE 11 /* Is the kernel configured to ignore soft reservations? */ #define EFI_PRESERVE_BS_REGIONS 12 /* Are EFI boot-services memory segments available? */ +#define EFI_SECURE_BOOT 13 /* Are we in Secure Boot mode? */ + +enum efi_secureboot_mode { + efi_secureboot_mode_unset, + efi_secureboot_mode_unknown, + efi_secureboot_mode_disabled, + efi_secureboot_mode_enabled, +}; #ifdef CONFIG_EFI /* @@ -896,6 +904,7 @@ static inline bool efi_rt_services_supported(unsigned int mask) return (efi.runtime_supported_mask & mask) == mask; } extern void efi_find_mirror(void); +extern void __init efi_set_secure_boot(enum efi_secureboot_mode mode); #else static inline bool efi_enabled(int feature) { @@ -915,6 +924,7 @@ static inline bool efi_rt_services_supported(unsigned int mask) } static inline void efi_find_mirror(void) {} +static inline void efi_set_secure_boot(enum efi_secureboot_mode mode) {} #endif extern int efi_status_to_err(efi_status_t status); @@ -1134,13 +1144,6 @@ static inline bool efi_runtime_disabled(void) { return true; } extern void efi_call_virt_check_flags(unsigned long flags, const void *caller); extern unsigned long efi_call_virt_save_flags(void); -enum efi_secureboot_mode { - efi_secureboot_mode_unset, - efi_secureboot_mode_unknown, - efi_secureboot_mode_disabled, - efi_secureboot_mode_enabled, -}; - static inline enum efi_secureboot_mode efi_get_secureboot_mode(efi_get_variable_t *get_var) { From 1ddb4dc7a7f72504f5547cc67a0d854ea9a33fbb Mon Sep 17 00:00:00 2001 From: Allen Pais Date: Mon, 29 Jul 2024 17:35:10 +0000 Subject: [PATCH 3/4] 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 Backported to v6.6.40 - AzLinux Signed-off-by: Allen Pais --- arch/x86/kernel/setup.c | 4 ++-- drivers/firmware/efi/secureboot.c | 5 +++++ include/linux/security.h | 9 +++++++++ security/lockdown/Kconfig | 15 +++++++++++++++ security/lockdown/lockdown.c | 2 +- 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 7c4a6697e39d2..04e73973098e1 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1028,6 +1028,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(); x86_init.resources.dmi_setup(); @@ -1190,8 +1192,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(); diff --git a/drivers/firmware/efi/secureboot.c b/drivers/firmware/efi/secureboot.c index b6620669e32bc..a019d14f46ac5 100644 --- 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_secureboot_mode mode) 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: diff --git a/include/linux/security.h b/include/linux/security.h index eea27168eb905..ddf14a0fe6ef2 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -508,6 +508,7 @@ void security_bdev_free(struct block_device *bdev); int security_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type, const void *value, size_t size); +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) @@ -1439,6 +1440,7 @@ static inline int security_locked_down(enum lockdown_reason what) { return 0; } +<<<<<<< HEAD static inline int security_bdev_alloc(struct block_device *bdev) { @@ -1456,6 +1458,13 @@ static inline int security_bdev_setintegrity(struct block_device *bdev, return 0; } +======= +static inline int +lock_kernel_down(const char *where, enum lockdown_reason level) +{ + return -EOPNOTSUPP; +} +>>>>>>> efi: Lock down the kernel if booted in secure boot mode #endif /* CONFIG_SECURITY */ #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) diff --git a/security/lockdown/Kconfig b/security/lockdown/Kconfig index e84ddf4840101..4175b50b1e6e1 100644 --- a/security/lockdown/Kconfig +++ b/security/lockdown/Kconfig @@ -45,3 +45,18 @@ config LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY 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. diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c index 68d19632aeb72..67cc9839952f8 100644 --- a/security/lockdown/lockdown.c +++ b/security/lockdown/lockdown.c @@ -23,7 +23,7 @@ static const enum lockdown_reason lockdown_levels[] = {LOCKDOWN_NONE, /* * 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; From 8bbb6780deb56560af81a3bacd59aaf48714240e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 30 Aug 2019 15:54:24 +0100 Subject: [PATCH 4/4] mtd: phram,slram: Disable when the kernel is locked down These drivers allow mapping arbitrary memory ranges as MTD devices. This should be disabled to preserve the kernel's integrity when it is locked down. * Add the HWPARAM flag to the module parameters * When slram is built-in, it uses __setup() to read kernel parameters, so add an explicit check security_locked_down() check Signed-off-by: Ben Hutchings Cc: Matthew Garrett Cc: David Howells Cc: Joern Engel Cc: linux-mtd@lists.infradead.org --- drivers/mtd/devices/phram.c | 6 +++++- drivers/mtd/devices/slram.c | 9 ++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 208bd4d871f42..30f84a91692db 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -364,7 +364,11 @@ static int phram_param_call(const char *val, const struct kernel_param *kp) #endif } -module_param_call(phram, phram_param_call, NULL, NULL, 0200); +static const struct kernel_param_ops phram_param_ops = { + .set = phram_param_call +}; +__module_param_call(MODULE_PARAM_PREFIX, phram, &phram_param_ops, NULL, + 0200, -1, KERNEL_PARAM_FL_HWPARAM | hwparam_iomem); MODULE_PARM_DESC(phram, "Memory region to map. \"phram=,,[,]\""); #ifdef CONFIG_OF diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 28131a127d065..d92a2461e2ce4 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -65,7 +66,7 @@ typedef struct slram_mtd_list { #ifdef MODULE static char *map[SLRAM_MAX_DEVICES_PARAMS]; -module_param_array(map, charp, NULL, 0); +module_param_hw_array(map, charp, iomem, NULL, 0); MODULE_PARM_DESC(map, "List of memory regions to map. \"map=, , \""); #else static char *map; @@ -281,11 +282,17 @@ static int __init init_slram(void) #ifndef MODULE char *devstart; char *devlength; + int ret; if (!map) { E("slram: not enough parameters.\n"); return(-EINVAL); } + + ret = security_locked_down(LOCKDOWN_MODULE_PARAMETERS); + if (ret) + return ret; + while (map) { devname = devstart = devlength = NULL;