From: Dan Duval Date: Fri, 11 Dec 2015 20:20:20 +0000 (-0500) Subject: x86/efi: Set securelevel when loaded without efi stub X-Git-Tag: v4.1.12-92~184^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7744d564001adfc0eedb4ace1f2d7a23d383d700;p=users%2Fjedix%2Flinux-maple.git x86/efi: Set securelevel when loaded without efi stub Orabug: 22364965 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 (cherry picked from commit a954f7350658a8fde4b893c7b74de8137864ad12) Signed-off-by: Dan Duval --- diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 97838c712a96a..7cea402a45d33 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 02744df576d52..fc8c2054f3ab3 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 03eed462480c1..10df94c7b35c4 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 2115055faeac9..eee9db77db76b 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();