From 496890ebd2605eb1ff15f8d96c30b5d617f1bb85 Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Fri, 6 Nov 2020 11:19:06 +0000 Subject: [PATCH 7/9] linuxefi: fail kernel validation without shim protocol. If certificates that signed grub are installed into db, grub can be booted directly. It will then boot any kernel without signature validation. The booted kernel will think it was booted in secureboot mode and will implement lockdown, yet it could have been tampered. This version of the patch skips calling verification, when booted without secureboot. And is indented with gnu ident. CVE-2020-15705 Reported-by: Mathieu Trudel-Lapierre Signed-off-by: Michael Chang --- grub-core/loader/arm64/efi/linux.c | 38 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c index a4041be5c..0e5782caa 100644 --- a/grub-core/loader/arm64/efi/linux.c +++ b/grub-core/loader/arm64/efi/linux.c @@ -58,21 +58,35 @@ struct grub_efi_shim_lock }; typedef struct grub_efi_shim_lock grub_efi_shim_lock_t; -static grub_efi_boolean_t +// Returns 1 on success, -1 on error, 0 when not available +static int grub_linuxefi_secure_validate (void *data, grub_uint32_t size) { grub_efi_guid_t guid = SHIM_LOCK_GUID; grub_efi_shim_lock_t *shim_lock; + grub_efi_status_t status; shim_lock = grub_efi_locate_protocol(&guid, NULL); - + grub_dprintf ("secureboot", "shim_lock: %p\n", shim_lock); if (!shim_lock) - return 1; + { + grub_dprintf ("secureboot", "shim not available\n"); + return 0; + } - if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS) - return 1; + grub_dprintf ("secureboot", "Asking shim to verify kernel signature\n"); + status = shim_lock->verify (data, size); + grub_dprintf ("secureboot", "shim_lock->verify(): %ld\n", (long int)status); + if (status == GRUB_EFI_SUCCESS) + { + grub_dprintf ("secureboot", "Kernel signature verification passed\n"); + return 1; + } - return 0; + grub_dprintf ("secureboot", "Kernel signature verification failed (0x%lx)\n", + (unsigned long) status); + + return -1; } #pragma GCC diagnostic push @@ -399,6 +413,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), struct linux_arch_kernel_header lh; struct grub_armxx_linux_pe_header *pe; grub_err_t err; + int rc; grub_dl_ref (my_mod); @@ -443,10 +458,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("linux", "kernel @ %p\n", kernel_addr); - if (!grub_linuxefi_secure_validate (kernel_addr, kernel_size)) + if (grub_efi_secure_boot ()) { - grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); - goto fail; + rc = grub_linuxefi_secure_validate (kernel_addr, kernel_size); + if (rc <= 0) + { + grub_error (GRUB_ERR_INVALID_COMMAND, + N_("%s has invalid signature"), argv[0]); + goto fail; + } } pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset); -- 2.26.2