- Use shim loader protocol to verify images in the shim_lock verifier. - Add API to allow downstream consumers to re-use image handles produced by the verifier. This is necessary to avoid having images measured twice to the TPM. - Register shim loader protocol as an image loader.
Signed-off-by: Mate Kukri <mate.ku...@canonical.com> --- grub-core/kern/efi/sb.c | 45 ++++++++++++++++-------------- grub-core/loader/efi/chainloader.c | 21 ++++++++------ grub-core/loader/efi/linux.c | 30 ++++++-------------- include/grub/efi/api.h | 5 ++++ include/grub/efi/efi.h | 19 ++++++++----- include/grub/efi/sb.h | 5 ++-- 6 files changed, 66 insertions(+), 59 deletions(-) diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c index 8d3e41360..fcc71e4e8 100644 --- a/grub-core/kern/efi/sb.c +++ b/grub-core/kern/efi/sb.c @@ -31,8 +31,11 @@ #include <grub/verify.h> static grub_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID; +static grub_guid_t shim_loader_guid = GRUB_EFI_SHIM_IMAGE_LOADER_GUID; -static bool shim_lock_enabled = false; +static grub_efi_loader_t *shim_loader = NULL; + +static grub_efi_handle_t last_verified_image_handle; /* * Determine whether we're in secure boot mode. @@ -95,14 +98,6 @@ grub_efi_get_secureboot (void) if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1) { secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED; - /* - * TODO: Replace this all with shim's LoadImage protocol, delegating policy to it. - * - * We need to set shim_lock_enabled here because we disabled secure boot - * validation *inside* shim but not in the firmware, so we set this variable - * here to trigger that code path, whereas the actual verifier is not enabled. - */ - shim_lock_enabled = true; goto out; } @@ -183,14 +178,18 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), static grub_err_t shim_lock_verifier_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size) { - grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0); + grub_efi_handle_t image_handle; - if (!sl) - return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found")); + if (last_verified_image_handle) + { + shim_loader->unload_image (last_verified_image_handle); + last_verified_image_handle = NULL; + } - if (sl->verify (buf, size) != GRUB_EFI_SUCCESS) + if (shim_loader->load_image (false, grub_efi_image_handle, NULL, buf, size, &image_handle) != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature")); + last_verified_image_handle = image_handle; return GRUB_ERR_NONE; } @@ -205,11 +204,11 @@ void grub_shim_lock_verifier_setup (void) { struct grub_module_header *header; - grub_efi_shim_lock_protocol_t *sl = - grub_efi_locate_protocol (&shim_lock_guid, 0); - /* shim_lock is missing, check if GRUB image is built with --disable-shim-lock. */ - if (!sl) + shim_loader = grub_efi_locate_protocol (&shim_loader_guid, 0); + + /* shim is missing, check if GRUB image is built with --disable-shim-lock. */ + if (!shim_loader) { FOR_MODULES (header) { @@ -225,14 +224,18 @@ grub_shim_lock_verifier_setup (void) /* Enforce shim_lock_verifier. */ grub_verifier_register (&shim_lock_verifier); - shim_lock_enabled = true; + /* Register shim loader if supported. */ + grub_efi_register_loader (shim_loader); grub_env_set ("shim_lock", "y"); grub_env_export ("shim_lock"); } -bool -grub_is_shim_lock_enabled (void) + +grub_efi_handle_t +grub_efi_get_last_verified_image_handle (void) { - return shim_lock_enabled; + grub_efi_handle_t tmp = last_verified_image_handle; + last_verified_image_handle = NULL; + return tmp; } diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index 11b64ac1b..e77bd863c 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -33,6 +33,7 @@ #include <grub/efi/efi.h> #include <grub/efi/disk.h> #include <grub/efi/memory.h> +#include <grub/efi/sb.h> #include <grub/command.h> #include <grub/i18n.h> #include <grub/net.h> @@ -337,16 +338,20 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), } #endif - status = grub_efi_load_image (0, grub_efi_image_handle, file_path, - boot_image, size, &image_handle); - if (status != GRUB_EFI_SUCCESS) + image_handle = grub_efi_get_last_verified_image_handle (); + if (image_handle == NULL) { - if (status == GRUB_EFI_OUT_OF_RESOURCES) - grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources"); - else - grub_error (GRUB_ERR_BAD_OS, "cannot load image"); + status = grub_efi_load_image (0, grub_efi_image_handle, file_path, + boot_image, size, &image_handle); + if (status != GRUB_EFI_SUCCESS) + { + if (status == GRUB_EFI_OUT_OF_RESOURCES) + grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of resources"); + else + grub_error (GRUB_ERR_BAD_OS, "cannot load image"); - goto fail; + goto fail; + } } /* LoadImage does not set a device handler when the image is diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c index 7342f3ee7..b97b3e27b 100644 --- a/grub-core/loader/efi/linux.c +++ b/grub-core/loader/efi/linux.c @@ -206,11 +206,15 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args) mempath[1].header.subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; mempath[1].header.length = sizeof (grub_efi_device_path_t); - status = grub_efi_load_image (0, grub_efi_image_handle, - (grub_efi_device_path_t *)mempath, - (void *)addr, size, &image_handle); - if (status != GRUB_EFI_SUCCESS) - return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); + image_handle = grub_efi_get_last_verified_image_handle (); + if (image_handle == NULL) + { + status = grub_efi_load_image (0, grub_efi_image_handle, + (grub_efi_device_path_t *)mempath, + (void *)addr, size, &image_handle); + if (status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_OS, "cannot load image"); + } grub_dprintf ("linux", "linux command line: '%s'\n", args); @@ -461,22 +465,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_dl_ref (my_mod); - if (grub_is_shim_lock_enabled () == true) - { -#if defined(__i386__) || defined(__x86_64__) - grub_dprintf ("linux", "shim_lock enabled, falling back to legacy Linux kernel loader\n"); - - err = grub_cmd_linux_x86_legacy (cmd, argc, argv); - - if (err == GRUB_ERR_NONE) - return GRUB_ERR_NONE; - else - goto fail; -#else - grub_dprintf ("linux", "shim_lock enabled, trying Linux kernel EFI stub loader\n"); -#endif - } - if (argc == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index b686e8afe..9ae908729 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -364,6 +364,11 @@ { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \ } +#define GRUB_EFI_SHIM_IMAGE_LOADER_GUID \ + { 0x1f492041, 0xfadb, 0x4e59, \ + {0x9e, 0x57, 0x7c, 0xaf, 0xe7, 0x3a, 0x55, 0xab } \ + } + #define GRUB_EFI_RNG_PROTOCOL_GUID \ { 0x3152bca5, 0xeade, 0x433d, \ { 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44 } \ diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index 692a1b935..b4d2f2d46 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -150,15 +150,20 @@ EXPORT_FUNC (grub_efi_unload_image) (grub_efi_handle_t image_handle); typedef struct grub_efi_loader { grub_efi_status_t (__grub_efi_api *load_image) (grub_efi_boolean_t boot_policy, - grub_efi_handle_t parent_image_handle, - grub_efi_device_path_t *file_path, - void *source_buffer, - grub_efi_uintn_t source_size, - grub_efi_handle_t *image_handle); + grub_efi_handle_t parent_image_handle, + grub_efi_device_path_t *file_path, + void *source_buffer, + grub_efi_uintn_t source_size, + grub_efi_handle_t *image_handle); grub_efi_status_t (__grub_efi_api *start_image) (grub_efi_handle_t image_handle, - grub_efi_uintn_t *exit_data_size, - grub_efi_char16_t **exit_data); + grub_efi_uintn_t *exit_data_size, + grub_efi_char16_t **exit_data); + + grub_efi_status_t (__grub_efi_api *exit) (grub_efi_handle_t image_handle, + grub_efi_status_t exit_status, + grub_efi_uintn_t exit_data_size, + grub_efi_char16_t *exit_data); grub_efi_status_t (__grub_efi_api *unload_image) (grub_efi_handle_t image_handle); } grub_efi_loader_t; diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h index 49a9ad01c..284e14992 100644 --- a/include/grub/efi/sb.h +++ b/include/grub/efi/sb.h @@ -21,6 +21,7 @@ #include <grub/types.h> #include <grub/dl.h> +#include <grub/efi/api.h> #define GRUB_EFI_SECUREBOOT_MODE_UNSET 0 #define GRUB_EFI_SECUREBOOT_MODE_UNKNOWN 1 @@ -31,8 +32,8 @@ extern grub_uint8_t EXPORT_FUNC (grub_efi_get_secureboot) (void); -extern bool -EXPORT_FUNC (grub_is_shim_lock_enabled) (void); +extern grub_efi_handle_t +EXPORT_FUNC (grub_efi_get_last_verified_image_handle) (void); extern void grub_shim_lock_verifier_setup (void); -- 2.39.2 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel