From a954f7350658a8fde4b893c7b74de8137864ad12 Mon Sep 17 00:00:00 2001 From: Dan Duval Date: Fri, 11 Dec 2015 15:20:20 -0500 Subject: [PATCH] x86/efi: Set securelevel when loaded without efi stub Orabug: 22353360 With UEFI Secure Boot enabled and securelevel set, after a kernel is loaded using kexec and booted, securelevel is disabled. With the securelevel patch set, the state of UEFI Secure Boot is queried when booted via the efi stub, but kexec does not use the efi stub. To allow kernels which are not loaded through the efi stub to properly set securelevel as well, add a new init routine to start_kernel() to query the state of UEFI Secure Boot and enable securelevel if needed. Taken from https://bugzilla.redhat.com/attachment.cgi?id=1052836 . Signed-off-by: Linn Crosetto Signed-off-by: Dan Duval --- arch/x86/kernel/setup.c | 8 ------- arch/x86/platform/efi/efi.c | 47 +++++++++++++++++++++++++++++++++++++ include/linux/efi.h | 1 + init/main.c | 2 ++ 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 97838c712a96..7cea402a45d3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1157,14 +1157,6 @@ void __init setup_arch(char **cmdline_p) io_delay_init(); -#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL - if (boot_params.secure_boot) { - set_bit(EFI_SECURE_BOOT, &efi.flags); - set_securelevel(1); - pr_info("Secure boot enabled\n"); - } -#endif - /* * Parse the ACPI tables for possible boot-time SMP configuration. */ diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 02744df576d5..fc8c2054f3ab 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -78,6 +79,41 @@ static int __init setup_add_efi_memmap(char *arg) } early_param("add_efi_memmap", setup_add_efi_memmap); +static int __init efi_secure_boot_enabled(void) +{ + efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; + static efi_char16_t sb_var[] = { + 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + static efi_char16_t sm_var[] = { + 'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 }; + u8 sb, setup; + unsigned long datasize = sizeof(sb); + efi_status_t status; + + if (boot_params.secure_boot) + return 1; + + status = efi.get_variable((efi_char16_t*)sb_var, + &var_guid, NULL, &datasize, &sb); + + if (status != EFI_SUCCESS) + return 0; + + if (sb == 0) + return 0; + + status = efi.get_variable((efi_char16_t*)sm_var, + &var_guid, NULL, &datasize, &setup); + + if (status != EFI_SUCCESS) + return 0; + + if (setup == 1) + return 0; + + return 1; +} + static efi_status_t __init phys_efi_set_virtual_address_map( unsigned long memory_map_size, unsigned long descriptor_size, @@ -436,6 +472,17 @@ static int __init efi_memmap_init(void) return 0; } +void __init efi_secure_boot_init(void) +{ + if (!efi_secure_boot_enabled()) + return; + + boot_params.secure_boot = 1; +#ifdef CONFIG_EFI_SECURE_BOOT_SECURELEVEL + set_securelevel(1); +#endif +} + void __init efi_init(void) { efi_char16_t *c16; diff --git a/include/linux/efi.h b/include/linux/efi.h index 03eed462480c..10df94c7b35c 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -890,6 +890,7 @@ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if pos extern void efi_late_init(void); extern void efi_free_boot_services(void); extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size); +extern void efi_secure_boot_init(void); #else static inline void efi_late_init(void) {} static inline void efi_free_boot_services(void) {} diff --git a/init/main.c b/init/main.c index 2115055faeac..eee9db77db76 100644 --- a/init/main.c +++ b/init/main.c @@ -639,6 +639,8 @@ asmlinkage __visible void __init start_kernel(void) if (efi_enabled(EFI_RUNTIME_SERVICES)) efi_enter_virtual_mode(); #endif + if (efi_enabled(EFI_RUNTIME_SERVICES)) + efi_secure_boot_init(); #ifdef CONFIG_X86_ESPFIX64 /* Should be run before the first non-init thread is created */ init_espfix_bsp(); -- 2.50.1