forked from pool/grub2
be3181b1eb
- VUL-0: grub2,shim: implement new SBAT method (bsc#1182057) * 0031-util-mkimage-Remove-unused-code-to-add-BSS-section.patch * 0032-util-mkimage-Use-grub_host_to_target32-instead-of-gr.patch * 0033-util-mkimage-Always-use-grub_host_to_target32-to-ini.patch * 0034-util-mkimage-Unify-more-of-the-PE32-and-PE32-header-.patch * 0035-util-mkimage-Reorder-PE-optional-header-fields-set-u.patch * 0036-util-mkimage-Improve-data_size-value-calculation.patch * 0037-util-mkimage-Refactor-section-setup-to-use-a-helper.patch * 0038-util-mkimage-Add-an-option-to-import-SBAT-metadata-i.patch * 0039-grub-install-common-Add-sbat-option.patch - Fix CVE-2021-20225 (bsc#1182262) * 0022-lib-arg-Block-repeated-short-options-that-require-an.patch - Fix CVE-2020-27749 (bsc#1179264) * 0024-kern-parser-Fix-resource-leak-if-argc-0.patch * 0025-kern-parser-Fix-a-memory-leak.patch * 0026-kern-parser-Introduce-process_char-helper.patch * 0027-kern-parser-Introduce-terminate_arg-helper.patch * 0028-kern-parser-Refactor-grub_parser_split_cmdline-clean.patch * 0029-kern-buffer-Add-variable-sized-heap-buffer.patch * 0030-kern-parser-Fix-a-stack-buffer-overflow.patch - Fix CVE-2021-20233 (bsc#1182263) * 0023-commands-menuentry-Fix-quoting-in-setparams_prefix.patch - Fix CVE-2020-25647 (bsc#1177883) * 0021-usb-Avoid-possible-out-of-bound-accesses-caused-by-m.patch - Fix CVE-2020-25632 (bsc#1176711) * 0020-dl-Only-allow-unloading-modules-that-are-not-depende.patch - Fix CVE-2020-27779, CVE-2020-14372 (bsc#1179265) (bsc#1175970) * 0001-include-grub-i386-linux.h-Include-missing-grub-types.patch * 0002-efi-Make-shim_lock-GUID-and-protocol-type-public.patch * 0003-efi-Return-grub_efi_status_t-from-grub_efi_get_varia.patch OBS-URL: https://build.opensuse.org/request/show/876326 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=374
369 lines
11 KiB
Diff
369 lines
11 KiB
Diff
From b16919b634129e377431e96bc3252179fed83a40 Mon Sep 17 00:00:00 2001
|
|
From: Marco A Benatto <mbenatto@redhat.com>
|
|
Date: Wed, 23 Sep 2020 14:21:14 -0400
|
|
Subject: [PATCH 08/46] efi: Move the shim_lock verifier to the GRUB core
|
|
|
|
Move the shim_lock verifier from its own module into the core image. The
|
|
Secure Boot lockdown mechanism has the intent to prevent the load of any
|
|
unsigned code or binary when Secure Boot is enabled.
|
|
|
|
The reason is that GRUB must be able to prevent executing untrusted code
|
|
if UEFI Secure Boot is enabled, without depending on external modules.
|
|
|
|
Signed-off-by: Marco A Benatto <mbenatto@redhat.com>
|
|
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
docs/grub.texi | 9 +-
|
|
grub-core/Makefile.core.def | 6 --
|
|
grub-core/commands/efi/shim_lock.c | 133 -----------------------------
|
|
grub-core/kern/efi/init.c | 4 +
|
|
grub-core/kern/efi/sb.c | 105 +++++++++++++++++++++++
|
|
include/grub/efi/sb.h | 3 +
|
|
6 files changed, 117 insertions(+), 143 deletions(-)
|
|
delete mode 100644 grub-core/commands/efi/shim_lock.c
|
|
|
|
diff --git a/docs/grub.texi b/docs/grub.texi
|
|
index bd0e02057..d3fbc81db 100644
|
|
--- a/docs/grub.texi
|
|
+++ b/docs/grub.texi
|
|
@@ -5764,15 +5764,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 5cb869f5b..8c8f8c579 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 = x86_64_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 <http://www.gnu.org/licenses/>.
|
|
- *
|
|
- * EFI shim lock verifier.
|
|
- */
|
|
-
|
|
-#include <grub/dl.h>
|
|
-#include <grub/efi/efi.h>
|
|
-#include <grub/efi/sb.h>
|
|
-#include <grub/err.h>
|
|
-#include <grub/file.h>
|
|
-#include <grub/misc.h>
|
|
-#include <grub/verify.h>
|
|
-
|
|
-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 5c7876e42..9c143eed7 100644
|
|
--- a/grub-core/kern/efi/init.c
|
|
+++ b/grub-core/kern/efi/init.c
|
|
@@ -20,6 +20,7 @@
|
|
#include <grub/efi/efi.h>
|
|
#include <grub/efi/console.h>
|
|
#include <grub/efi/disk.h>
|
|
+#include <grub/efi/sb.h>
|
|
#include <grub/term.h>
|
|
#include <grub/misc.h>
|
|
#include <grub/env.h>
|
|
@@ -40,6 +41,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 <grub/efi/pe32.h>
|
|
#include <grub/efi/sb.h>
|
|
#include <grub/err.h>
|
|
+#include <grub/file.h>
|
|
#include <grub/i386/linux.h>
|
|
#include <grub/mm.h>
|
|
#include <grub/types.h>
|
|
+#include <grub/verify.h>
|
|
+
|
|
+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)
|
|
--
|
|
2.26.2
|
|
|