diff --git a/docs/grub.texi b/docs/grub.texi index eeac9b2ce..e3de2a4dc 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -5910,15 +5910,16 @@ secure boot chain. @section UEFI secure boot and shim support The GRUB, except the @command{chainloader} command, works with the UEFI secure -boot and the shim. This functionality is provided by the shim_lock module. It -is recommend to build in this and other required modules into the @file{core.img}. +boot and the shim. This functionality is provided by the shim_lock verifier. It +is built into the @file{core.img} and is registered if the UEFI secure boot is +enabled. + All modules not stored in the @file{core.img} and the ACPI tables for the @command{acpi} command have to be signed, e.g. using PGP. Additionally, the @command{iorw}, the @command{memrw} and the @command{wrmsr} commands are prohibited if the UEFI secure boot is enabled. This is done due to security reasons. All above mentioned requirements are enforced by the -shim_lock module. And itself it is a persistent module which means that -it cannot be unloaded if it was loaded into the memory. +shim_lock verifier logic. @node Measured Boot @section Measuring boot components diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 0cecc3875..2b98fe1fc 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -944,12 +944,6 @@ module = { cppflags = '-I$(srcdir)/lib/posix_wrap'; }; -module = { - name = shim_lock; - common = commands/efi/shim_lock.c; - enable = efi; -}; - module = { name = hdparm; common = commands/hdparm.c; diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c deleted file mode 100644 index f7f3109d6..000000000 --- a/grub-core/commands/efi/shim_lock.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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 . - * - * EFI shim lock verifier. - */ - -#include -#include -#include -#include -#include -#include -#include - -GRUB_MOD_LICENSE ("GPLv3+"); - -static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID; - -/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */ -static const char * const disabled_mods[] = {"iorw", "memrw", "wrmsr", 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; - - 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; - } - - /* Fall through. */ - - case GRUB_FILE_TYPE_ACPI_TABLE: - case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: - *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; - - 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) -{ - grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0); - - if (sl == NULL) - return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found")); - - 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) -{ - grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0); - - if (sl == NULL || grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED) - return; - - grub_verifier_register (&shim_lock); - - grub_dl_set_persistent (mod); -} - -GRUB_MOD_FINI(shim_lock) -{ - grub_verifier_unregister (&shim_lock); -} diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 2c31847bf..b683bec5a 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,9 @@ grub_efi_init (void) /* Initialize the memory management system. */ grub_efi_mm_init (); + /* Register the shim_lock verifier if UEFI Secure Boot is enabled. */ + grub_shim_lock_verifier_setup (); + efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer, 0, 0, 0, NULL); diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c index 19658d962..8bd5e936d 100644 --- a/grub-core/kern/efi/sb.c +++ b/grub-core/kern/efi/sb.c @@ -22,9 +22,16 @@ #include #include #include +#include #include #include #include +#include + +static grub_efi_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID; + +/* List of modules which cannot be loaded if UEFI secure boot mode is enabled. */ +static const char * const disabled_mods[] = {"iorw", "memrw", "wrmsr", NULL}; /* * Determine whether we're in secure boot mode. @@ -107,3 +114,101 @@ grub_efi_get_secureboot (void) return secureboot; } + +static grub_err_t +shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + 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; + + 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; + } + + /* Fall through. */ + + case GRUB_FILE_TYPE_ACPI_TABLE: + case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: + *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; + + 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_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); + + if (!sl) + return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found")); + + 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_verifier = + { + .name = "shim_lock_verifier", + .init = shim_lock_verifier_init, + .write = shim_lock_verifier_write + }; + +void +grub_shim_lock_verifier_setup (void) +{ + grub_efi_shim_lock_protocol_t *sl = + grub_efi_locate_protocol (&shim_lock_guid, 0); + + if (!sl) + return; + + if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED) + return; + + grub_verifier_register (&shim_lock_verifier); +} diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h index a33d985e3..30c4335bb 100644 --- a/include/grub/efi/sb.h +++ b/include/grub/efi/sb.h @@ -30,6 +30,9 @@ #ifdef GRUB_MACHINE_EFI extern grub_uint8_t EXPORT_FUNC (grub_efi_get_secureboot) (void); + +extern void +grub_shim_lock_verifier_setup (void); #else static inline grub_uint8_t grub_efi_get_secureboot (void)