This module provides shim lock verification for various kernels if UEFI secure boot is enabled on a machine.
It is recommended to put this module into GRUB2 standalone image (avoid putting iorw and memrw modules into it; they are disallowed if UEFI secure boot is enabled). However, it is also possible to use it as a normal module. Though such configurations are more fragile and less secure due to various limitations. If the module is loaded and UEFI secure boot is enabled then: - module itself cannot be unloaded (persistent module), - the iorw and memrw modules cannot be loaded, - if the iorw and memrw modules are loaded then machine boot is disabled, - GRUB2 defers modules verification to other verifiers. Signed-off-by: Daniel Kiper <daniel.ki...@oracle.com> --- v3 - suggestions/fixes: - disable module unload, - disable the iorw and memrw modules loading, - disable boot if the iorw and memrw modules are loaded, - defer GRUB2 modules verification to other verifiers. --- grub-core/Makefile.core.def | 6 ++ grub-core/commands/efi/shim_lock.c | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 grub-core/commands/efi/shim_lock.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 3008b58..4a7c15f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -900,6 +900,12 @@ module = { }; module = { + name = shim_lock; + common = commands/efi/shim_lock.c; + enable = x86_64_efi; +}; + +module = { name = hdparm; common = commands/hdparm.c; enable = pci; diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c new file mode 100644 index 0000000..1bbf624 --- /dev/null +++ b/grub-core/commands/efi/shim_lock.c @@ -0,0 +1,140 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + * + * EFI shim lock verifier. + */ + +#include <grub/dl.h> +#include <grub/efi/efi.h> +#include <grub/err.h> +#include <grub/file.h> +#include <grub/misc.h> +#include <grub/verify.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define GRUB_EFI_SHIM_LOCK_GUID \ + { 0x605dab50, 0xe046, 0x4300, \ + { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \ + } + +struct grub_efi_shim_lock_protocol +{ + grub_efi_status_t + (*verify) (void *buffer, + grub_uint32_t size); +}; +typedef struct grub_efi_shim_lock_protocol grub_efi_shim_lock_protocol_t; + +static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID; +static grub_efi_shim_lock_protocol_t *sl; + +/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */ +static const char * const disabled_mods[] = {/* "acpi", ??? */ "iorw", "memrw", NULL}; + +static grub_err_t +shim_lock_init (grub_file_t io, enum grub_file_type type, + void **context __attribute__ ((unused)), + enum grub_verify_flags *flags) +{ + const char *b, *e; + int i; + + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; + + if (!sl) + return GRUB_ERR_NONE; + + switch (type & GRUB_FILE_TYPE_MASK) + { + case GRUB_FILE_TYPE_GRUB_MODULE: + /* Establish GRUB module name. */ + b = grub_strrchr (io->name, '/'); + e = grub_strrchr (io->name, '.'); + + b = b ? (b + 1) : io->name; + e = e ? e : io->name + grub_strlen (io->name); + e = (e > b) ? e : io->name + grub_strlen (io->name); + + for (i = 0; disabled_mods[i]; i++) + if (!grub_strncmp (b, disabled_mods[i], grub_strlen (b) - grub_strlen (e))) + { + grub_error (GRUB_ERR_ACCESS_DENIED, + N_("module cannot be loaded in UEFI secure boot mode: %s"), + io->name); + return GRUB_ERR_ACCESS_DENIED; + } + + *flags = GRUB_VERIFY_FLAGS_DEFER; + + return GRUB_ERR_NONE; + + case GRUB_FILE_TYPE_LINUX_KERNEL: + case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: + case GRUB_FILE_TYPE_BSD_KERNEL: + case GRUB_FILE_TYPE_XNU_KERNEL: + case GRUB_FILE_TYPE_PLAN9_KERNEL: + + for (i = 0; disabled_mods[i]; i++) + if (grub_dl_get (disabled_mods[i])) + { + grub_error (GRUB_ERR_ACCESS_DENIED, + N_("cannot boot due to dangerous module in memory: %s"), + disabled_mods[i]); + return GRUB_ERR_ACCESS_DENIED; + } + + *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; + + /* Fall through. */ + + default: + return GRUB_ERR_NONE; + } +} + +static grub_err_t +shim_lock_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size) +{ + if (sl->verify (buf, size) != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature")); + + return GRUB_ERR_NONE; +} + +struct grub_file_verifier shim_lock = + { + .name = "shim_lock", + .init = shim_lock_init, + .write = shim_lock_write + }; + +GRUB_MOD_INIT(shim_lock) +{ + sl = grub_efi_locate_protocol (&shim_lock_guid, 0); + grub_verifier_register (&shim_lock); + + if (!sl) + return; + + grub_dl_set_persistent (mod); +} + +GRUB_MOD_FINI(shim_lock) +{ + grub_verifier_unregister (&shim_lock); +} -- 1.7.10.4 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel