efi: Get and store the secure boot status
Get the firmware's secure-boot status in the kernel boot wrapper and stash it somewhere that the main kernel image can find. The efi_get_secureboot() function is extracted from the ARM stub and (a) generalised so that it can be called from x86 and (b) made to use efi_call_runtime() so that it can be run in mixed-mode. For x86, it is stored in boot_params and can be overridden by the boot loader or kexec. This allows secure-boot mode to be passed on to a new kernel. Suggested-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Matt Fleming <matt@codeblueprint.co.uk> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/1486380166-31868-5-git-send-email-ard.biesheuvel@linaro.org [ Small readability edits. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:

committed by
Ingo Molnar

parent
e58910cdc9
commit
de8cb45862
@@ -28,7 +28,7 @@ OBJECT_FILES_NON_STANDARD := y
|
||||
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
|
||||
KCOV_INSTRUMENT := n
|
||||
|
||||
lib-y := efi-stub-helper.o gop.o
|
||||
lib-y := efi-stub-helper.o gop.o secureboot.o
|
||||
|
||||
# include the stub's generic dependencies from lib/ when building for ARM/arm64
|
||||
arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
|
||||
|
@@ -20,52 +20,6 @@
|
||||
|
||||
bool __nokaslr;
|
||||
|
||||
static int efi_get_secureboot(efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
static efi_char16_t const sb_var_name[] = {
|
||||
'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
|
||||
static efi_char16_t const sm_var_name[] = {
|
||||
'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 };
|
||||
|
||||
efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
|
||||
efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable;
|
||||
u8 val;
|
||||
unsigned long size = sizeof(val);
|
||||
efi_status_t status;
|
||||
|
||||
status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)&var_guid,
|
||||
NULL, &size, &val);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto out_efi_err;
|
||||
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)&var_guid,
|
||||
NULL, &size, &val);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto out_efi_err;
|
||||
|
||||
if (val == 1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
out_efi_err:
|
||||
switch (status) {
|
||||
case EFI_NOT_FOUND:
|
||||
return 0;
|
||||
case EFI_DEVICE_ERROR:
|
||||
return -EIO;
|
||||
case EFI_SECURITY_VIOLATION:
|
||||
return -EACCES;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg,
|
||||
void *__image, void **__fh)
|
||||
{
|
||||
@@ -157,7 +111,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
||||
efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
|
||||
unsigned long reserve_addr = 0;
|
||||
unsigned long reserve_size = 0;
|
||||
int secure_boot = 0;
|
||||
enum efi_secureboot_mode secure_boot;
|
||||
struct screen_info *si;
|
||||
|
||||
/* Check if we were booted by the EFI firmware */
|
||||
@@ -227,19 +181,14 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
|
||||
pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
|
||||
|
||||
secure_boot = efi_get_secureboot(sys_table);
|
||||
if (secure_boot > 0)
|
||||
pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
|
||||
|
||||
if (secure_boot < 0) {
|
||||
pr_efi_err(sys_table,
|
||||
"could not determine UEFI Secure Boot status.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Unauthenticated device tree data is a security hazard, so
|
||||
* ignore 'dtb=' unless UEFI Secure Boot is disabled.
|
||||
* Unauthenticated device tree data is a security hazard, so ignore
|
||||
* 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure
|
||||
* boot is enabled if we can't determine its state.
|
||||
*/
|
||||
if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) {
|
||||
if (secure_boot != efi_secureboot_mode_disabled &&
|
||||
strstr(cmdline_ptr, "dtb=")) {
|
||||
pr_efi(sys_table, "Ignoring DTB from command line.\n");
|
||||
} else {
|
||||
status = handle_cmdline_files(sys_table, image, cmdline_ptr,
|
||||
|
61
drivers/firmware/efi/libstub/secureboot.c
Normal file
61
drivers/firmware/efi/libstub/secureboot.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Secure boot handling.
|
||||
*
|
||||
* Copyright (C) 2013,2014 Linaro Limited
|
||||
* Roy Franz <roy.franz@linaro.org
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
* Mark Salter <msalter@redhat.com>
|
||||
*
|
||||
* This file is part of the Linux kernel, and is made available under the
|
||||
* terms of the GNU General Public License version 2.
|
||||
*/
|
||||
#include <linux/efi.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
/* BIOS variables */
|
||||
static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
|
||||
static const efi_char16_t const efi_SecureBoot_name[] = {
|
||||
'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0
|
||||
};
|
||||
static const efi_char16_t const efi_SetupMode_name[] = {
|
||||
'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0
|
||||
};
|
||||
|
||||
#define get_efi_var(name, vendor, ...) \
|
||||
efi_call_runtime(get_variable, \
|
||||
(efi_char16_t *)(name), (efi_guid_t *)(vendor), \
|
||||
__VA_ARGS__);
|
||||
|
||||
/*
|
||||
* Determine whether we're in secure boot mode.
|
||||
*/
|
||||
enum efi_secureboot_mode efi_get_secureboot(efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
u8 secboot, setupmode;
|
||||
unsigned long size;
|
||||
efi_status_t status;
|
||||
|
||||
size = sizeof(secboot);
|
||||
status = get_efi_var(efi_SecureBoot_name, &efi_variable_guid,
|
||||
NULL, &size, &secboot);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto out_efi_err;
|
||||
|
||||
size = sizeof(setupmode);
|
||||
status = get_efi_var(efi_SetupMode_name, &efi_variable_guid,
|
||||
NULL, &size, &setupmode);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto out_efi_err;
|
||||
|
||||
if (secboot == 0 || setupmode == 1)
|
||||
return efi_secureboot_mode_disabled;
|
||||
|
||||
pr_efi(sys_table_arg, "UEFI Secure Boot is enabled.\n");
|
||||
return efi_secureboot_mode_enabled;
|
||||
|
||||
out_efi_err:
|
||||
pr_efi_err(sys_table_arg, "Could not determine UEFI Secure Boot status.\n");
|
||||
if (status == EFI_NOT_FOUND)
|
||||
return efi_secureboot_mode_disabled;
|
||||
return efi_secureboot_mode_unknown;
|
||||
}
|
Reference in New Issue
Block a user