Accepting request 877254 from openSUSE:Factory

Revert to pre-boothole2-fix - dualboot support broken; can't chainload windows

OBS-URL: https://build.opensuse.org/request/show/877254
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=236
This commit is contained in:
Dominique Leuenberger 2021-03-05 15:52:16 +00:00 committed by Git OBS Bridge
parent 8e0232c488
commit 5c46e6fba6
52 changed files with 202 additions and 5723 deletions

View File

@ -1,41 +0,0 @@
From eaed36ac87c3f8edeea67bf333700819e80ac732 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 5 Mar 2021 17:33:17 +0800
Subject: [PATCH] Add chainloaded image as shim's verifiable object
This fixed error in dual booting Microsoft Windows
error ../../grub-core/kern/verifiers.c:119:verification requested but
nobody cares: /EFI/Microsoft/Boot/bootmgfw.efi.
---
grub-core/kern/efi/sb.c | 1 +
grub-core/kern/lockdown.c | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 41dadcd14..96d237722 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -129,6 +129,7 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
case GRUB_FILE_TYPE_BSD_KERNEL:
case GRUB_FILE_TYPE_XNU_KERNEL:
case GRUB_FILE_TYPE_PLAN9_KERNEL:
+ case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
*flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
/* Fall through. */
diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
index 0bc70fd42..e1fd1c1e2 100644
--- a/grub-core/kern/lockdown.c
+++ b/grub-core/kern/lockdown.c
@@ -48,7 +48,6 @@ lockdown_verifier_init (grub_file_t io __attribute__ ((unused)),
case GRUB_FILE_TYPE_PXECHAINLOADER:
case GRUB_FILE_TYPE_PCCHAINLOADER:
case GRUB_FILE_TYPE_COREBOOT_CHAINLOADER:
- case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
case GRUB_FILE_TYPE_ACPI_TABLE:
case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
*flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
--
2.26.2

View File

@ -1,39 +0,0 @@
From f756ab3eac93346c3945eeb254773436ea3e1607 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 3 Dec 2020 16:01:43 +0100
Subject: [PATCH 01/46] include/grub/i386/linux.h: Include missing
<grub/types.h> header
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This header uses types defined in <grub/types.h> but does not include it,
which leads to compile errors like the following:
In file included from ../include/grub/cpu/linux.h:19,
from kern/efi/sb.c:21:
../include/grub/i386/linux.h:80:3: error: unknown type name grub_uint64_t
80 | grub_uint64_t addr;
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
include/grub/i386/linux.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h
index ce30e7fb0..6da5f030f 100644
--- a/include/grub/i386/linux.h
+++ b/include/grub/i386/linux.h
@@ -19,6 +19,8 @@
#ifndef GRUB_I386_LINUX_HEADER
#define GRUB_I386_LINUX_HEADER 1
+#include <grub/types.h>
+
#define GRUB_LINUX_I386_MAGIC_SIGNATURE 0x53726448 /* "HdrS" */
#define GRUB_LINUX_DEFAULT_SETUP_SECTS 4
#define GRUB_LINUX_INITRD_MAX_ADDRESS 0x37FFFFFF
--
2.26.2

View File

@ -0,0 +1,53 @@
From 1b4f4b2f5cd9b804a5bb66861b659d05d9a4f35a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 17 Aug 2020 17:09:01 +0800
Subject: [PATCH 1/2] 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.
CVE-2020-15705
Reported-by: Mathieu Trudel-Lapierre <cyphermox@ubuntu.com>
Also-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/i386/efi/linux.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 61b2d5177..8017e8c05 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -172,6 +172,23 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
+ if (grub_efi_secure_boot())
+ {
+ grub_dl_t mod;
+
+ mod = grub_dl_get ("shim_lock");
+ if (!mod)
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock module is not loaded"));
+ goto fail;
+ }
+ if (!grub_dl_is_persistent (mod))
+ {
+ grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol is not available"));
+ goto fail;
+ }
+ }
+
file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
if (! file)
goto fail;
--
2.26.2

View File

@ -0,0 +1,41 @@
From a60cfeacdeefb21215d35c4cad025e57de900352 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 27 Aug 2020 13:18:25 +0800
Subject: [PATCH] shim_lock: Disable GRUB_VERIFY_FLAGS_DEFER_AUTH if secure
boot off
The GRUB_VERIFY_FLAGS_DEFER_AUTH is enabled regardless secure boot
status that will cause error [1] on loading external grub modules if
secure boot turned off in which shim protocol itself did not verify
images so should not request verification for external modules either.
This patch fixed the problem by adding the secure boot status check
before requesting other verifiers to verify external module, therefore
external module loading can work after shim_lock module loaded and
secure boot turned off.
[1] error: verification requested but nobody cares:
(hd0,gpt10)/boot/grub2/x86_64-efi/linux.mod.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/efi/shim_lock.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c
index 764098cfc..18d121297 100644
--- a/grub-core/commands/efi/shim_lock.c
+++ b/grub-core/commands/efi/shim_lock.c
@@ -82,7 +82,8 @@ shim_lock_init (grub_file_t io, enum grub_file_type type,
case GRUB_FILE_TYPE_ACPI_TABLE:
case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
- *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+ if (grub_efi_secure_boot())
+ *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
return GRUB_ERR_NONE;
--
2.26.2

View File

@ -1,96 +0,0 @@
From 3b60f205de1450ed6bbe8655bfb59ea0dac4ad78 Mon Sep 17 00:00:00 2001
From: Daniel Kiper <daniel.kiper@oracle.com>
Date: Thu, 3 Dec 2020 16:01:45 +0100
Subject: [PATCH 02/46] efi: Make shim_lock GUID and protocol type public
The GUID will be used to properly detect and report UEFI Secure Boot
status to the x86 Linux kernel. The functionality will be added by
subsequent patches. The shim_lock protocol type is made public for
completeness.
Additionally, fix formatting of four preceding GUIDs.
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
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>
---
grub-core/commands/efi/shim_lock.c | 12 ------------
include/grub/efi/api.h | 19 +++++++++++++++----
2 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c
index 764098cfc..d8f52d721 100644
--- a/grub-core/commands/efi/shim_lock.c
+++ b/grub-core/commands/efi/shim_lock.c
@@ -27,18 +27,6 @@
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;
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 21efee3f3..b5cef9a88 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -316,22 +316,27 @@
#define GRUB_EFI_SAL_TABLE_GUID \
{ 0xeb9d2d32, 0x2d88, 0x11d3, \
- { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
}
#define GRUB_EFI_HCDP_TABLE_GUID \
{ 0xf951938d, 0x620b, 0x42ef, \
- { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \
+ { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \
}
#define GRUB_EFI_DEVICE_TREE_GUID \
{ 0xb1b621d5, 0xf19c, 0x41a5, \
- { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } \
+ { 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 } \
}
#define GRUB_EFI_VENDOR_APPLE_GUID \
{ 0x2B0585EB, 0xD8B8, 0x49A9, \
- { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
+ { 0x8B, 0x8C, 0xE2, 0x1B, 0x01, 0xAE, 0xF2, 0xB7 } \
+ }
+
+#define GRUB_EFI_SHIM_LOCK_GUID \
+ { 0x605dab50, 0xe046, 0x4300, \
+ { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } \
}
#define GRUB_EFI_IP4_CONFIG2_PROTOCOL_GUID \
@@ -1970,6 +1975,12 @@ struct grub_efi_ip6_config_manual_address {
};
typedef struct grub_efi_ip6_config_manual_address grub_efi_ip6_config_manual_address_t;
+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;
+
#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
|| defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
|| defined(__riscv)
--
2.26.2

View File

@ -1,146 +0,0 @@
From 10ee52fd565c9a88d9428a837c7f753a6c7fac5b Mon Sep 17 00:00:00 2001
From: Daniel Kiper <daniel.kiper@oracle.com>
Date: Thu, 3 Dec 2020 16:01:46 +0100
Subject: [PATCH 03/46] efi: Return grub_efi_status_t from
grub_efi_get_variable()
This is needed to properly detect and report UEFI Secure Boot status
to the x86 Linux kernel. The functionality will be added by subsequent
patches.
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
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>
---
grub-core/commands/efi/efifwsetup.c | 8 ++++----
grub-core/kern/efi/efi.c | 16 +++++++++-------
grub-core/video/efi_gop.c | 2 +-
include/grub/efi/efi.h | 7 ++++---
4 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c
index 7a137a72a..eaca03283 100644
--- a/grub-core/commands/efi/efifwsetup.c
+++ b/grub-core/commands/efi/efifwsetup.c
@@ -38,8 +38,8 @@ grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)),
grub_size_t oi_size;
grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
- old_os_indications = grub_efi_get_variable ("OsIndications", &global,
- &oi_size);
+ grub_efi_get_variable ("OsIndications", &global, &oi_size,
+ (void **) &old_os_indications);
if (old_os_indications != NULL && oi_size == sizeof (os_indications))
os_indications |= *old_os_indications;
@@ -63,8 +63,8 @@ efifwsetup_is_supported (void)
grub_size_t oi_size = 0;
grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
- os_indications_supported = grub_efi_get_variable ("OsIndicationsSupported",
- &global, &oi_size);
+ grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size,
+ (void **) &os_indications_supported);
if (!os_indications_supported)
return 0;
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 02d298b0c..9fd136694 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -222,9 +222,9 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var);
}
-void *
+grub_efi_status_t
grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
- grub_size_t *datasize_out)
+ grub_size_t *datasize_out, void **data_out)
{
grub_efi_status_t status;
grub_efi_uintn_t datasize = 0;
@@ -233,13 +233,14 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
void *data;
grub_size_t len, len16;
+ *data_out = NULL;
*datasize_out = 0;
len = grub_strlen (var);
len16 = len * GRUB_MAX_UTF16_PER_UTF8;
var16 = grub_calloc (len16 + 1, sizeof (var16[0]));
if (!var16)
- return NULL;
+ return GRUB_EFI_OUT_OF_RESOURCES;
len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
var16[len16] = 0;
@@ -250,14 +251,14 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize)
{
grub_free (var16);
- return NULL;
+ return status;
}
data = grub_malloc (datasize);
if (!data)
{
grub_free (var16);
- return NULL;
+ return GRUB_EFI_OUT_OF_RESOURCES;
}
status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, data);
@@ -265,12 +266,13 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
if (status == GRUB_EFI_SUCCESS)
{
+ *data_out = data;
*datasize_out = datasize;
- return data;
+ return status;
}
grub_free (data);
- return NULL;
+ return status;
}
grub_efi_boolean_t
diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c
index df29853f0..962f0eb8f 100644
--- a/grub-core/video/efi_gop.c
+++ b/grub-core/video/efi_gop.c
@@ -310,7 +310,7 @@ grub_video_gop_get_edid (struct grub_video_edid_info *edid_info)
char edidname[] = "agp-internal-edid";
grub_size_t datasize;
grub_uint8_t *data;
- data = grub_efi_get_variable (edidname, &efi_var_guid, &datasize);
+ grub_efi_get_variable (edidname, &efi_var_guid, &datasize, (void **) &data);
if (data && datasize > 16)
{
copy_size = datasize - 16;
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 085ee0524..f27d3a365 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -77,9 +77,10 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo
grub_efi_uintn_t descriptor_size,
grub_efi_uint32_t descriptor_version,
grub_efi_memory_descriptor_t *virtual_map);
-void *EXPORT_FUNC (grub_efi_get_variable) (const char *variable,
- const grub_efi_guid_t *guid,
- grub_size_t *datasize_out);
+grub_efi_status_t EXPORT_FUNC (grub_efi_get_variable) (const char *variable,
+ const grub_efi_guid_t *guid,
+ grub_size_t *datasize_out,
+ void **data_out);
grub_err_t
EXPORT_FUNC (grub_efi_set_variable) (const char *var,
const grub_efi_guid_t *guid,
--
2.26.2

View File

@ -1,79 +0,0 @@
From 5f2d71f71bc62c5cffbe27a9ee247803a77dc032 Mon Sep 17 00:00:00 2001
From: Daniel Kiper <daniel.kiper@oracle.com>
Date: Thu, 3 Dec 2020 16:01:47 +0100
Subject: [PATCH 04/46] efi: Add a function to read EFI variables with
attributes
It will be used to properly detect and report UEFI Secure Boot status to
the x86 Linux kernel. The functionality will be added by subsequent patches.
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
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>
---
grub-core/kern/efi/efi.c | 16 +++++++++++++---
include/grub/efi/efi.h | 5 +++++
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 9fd136694..92e99b441 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -223,8 +223,11 @@ grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
}
grub_efi_status_t
-grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
- grub_size_t *datasize_out, void **data_out)
+grub_efi_get_variable_with_attributes (const char *var,
+ const grub_efi_guid_t *guid,
+ grub_size_t *datasize_out,
+ void **data_out,
+ grub_efi_uint32_t *attributes)
{
grub_efi_status_t status;
grub_efi_uintn_t datasize = 0;
@@ -261,7 +264,7 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
return GRUB_EFI_OUT_OF_RESOURCES;
}
- status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, data);
+ status = efi_call_5 (r->get_variable, var16, guid, attributes, &datasize, data);
grub_free (var16);
if (status == GRUB_EFI_SUCCESS)
@@ -303,6 +306,13 @@ grub_efi_secure_boot (void)
return ret;
}
+grub_efi_status_t
+grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
+ grub_size_t *datasize_out, void **data_out)
+{
+ return grub_efi_get_variable_with_attributes (var, guid, datasize_out, data_out, NULL);
+}
+
#pragma GCC diagnostic ignored "-Wcast-align"
/* Search the mods section from the PE32/PE32+ image. This code uses
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index f27d3a365..568d80030 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -77,6 +77,11 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo
grub_efi_uintn_t descriptor_size,
grub_efi_uint32_t descriptor_version,
grub_efi_memory_descriptor_t *virtual_map);
+grub_efi_status_t EXPORT_FUNC (grub_efi_get_variable_with_attributes) (const char *variable,
+ const grub_efi_guid_t *guid,
+ grub_size_t *datasize_out,
+ void **data_out,
+ grub_efi_uint32_t *attributes);
grub_efi_status_t EXPORT_FUNC (grub_efi_get_variable) (const char *variable,
const grub_efi_guid_t *guid,
grub_size_t *datasize_out,
--
2.26.2

View File

@ -1,210 +0,0 @@
From 12650d0953372674fb587c2e6331257fc7a90a94 Mon Sep 17 00:00:00 2001
From: Daniel Kiper <daniel.kiper@oracle.com>
Date: Thu, 3 Dec 2020 16:01:48 +0100
Subject: [PATCH 05/46] efi: Add secure boot detection
Introduce grub_efi_get_secureboot() function which returns whether
UEFI Secure Boot is enabled or not on UEFI systems.
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
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>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 1 +
grub-core/kern/efi/sb.c | 109 ++++++++++++++++++++++++++++++++++++
include/grub/efi/sb.h | 40 +++++++++++++
4 files changed, 151 insertions(+)
create mode 100644 grub-core/kern/efi/sb.c
create mode 100644 include/grub/efi/sb.h
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index ede596170..5ff3afd62 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -71,6 +71,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index ce4f71ebe..072b1628c 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -203,6 +203,7 @@ kernel = {
efi = term/efi/console.c;
efi = kern/acpi.c;
efi = kern/efi/acpi.c;
+ efi = kern/efi/sb.c;
i386_coreboot = kern/i386/pc/acpi.c;
i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c;
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
new file mode 100644
index 000000000..19658d962
--- /dev/null
+++ b/grub-core/kern/efi/sb.c
@@ -0,0 +1,109 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2020 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/>.
+ *
+ * UEFI Secure Boot related checkings.
+ */
+
+#include <grub/efi/efi.h>
+#include <grub/efi/pe32.h>
+#include <grub/efi/sb.h>
+#include <grub/err.h>
+#include <grub/i386/linux.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+/*
+ * Determine whether we're in secure boot mode.
+ *
+ * Please keep the logic in sync with the Linux kernel,
+ * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot().
+ */
+grub_uint8_t
+grub_efi_get_secureboot (void)
+{
+ static grub_efi_guid_t efi_variable_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
+ static grub_efi_guid_t efi_shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID;
+ grub_efi_status_t status;
+ grub_efi_uint32_t attr = 0;
+ grub_size_t size = 0;
+ grub_uint8_t *secboot = NULL;
+ grub_uint8_t *setupmode = NULL;
+ grub_uint8_t *moksbstate = NULL;
+ grub_uint8_t secureboot = GRUB_EFI_SECUREBOOT_MODE_UNKNOWN;
+ const char *secureboot_str = "UNKNOWN";
+
+ status = grub_efi_get_variable ("SecureBoot", &efi_variable_guid,
+ &size, (void **) &secboot);
+
+ if (status == GRUB_EFI_NOT_FOUND)
+ {
+ secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
+ goto out;
+ }
+
+ if (status != GRUB_EFI_SUCCESS)
+ goto out;
+
+ status = grub_efi_get_variable ("SetupMode", &efi_variable_guid,
+ &size, (void **) &setupmode);
+
+ if (status != GRUB_EFI_SUCCESS)
+ goto out;
+
+ if ((*secboot == 0) || (*setupmode == 1))
+ {
+ secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
+ goto out;
+ }
+
+ /*
+ * See if a user has put the shim into insecure mode. If so, and if the
+ * variable doesn't have the runtime attribute set, we might as well
+ * honor that.
+ */
+ status = grub_efi_get_variable_with_attributes ("MokSBState", &efi_shim_lock_guid,
+ &size, (void **) &moksbstate, &attr);
+
+ /* If it fails, we don't care why. Default to secure. */
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED;
+ goto out;
+ }
+
+ if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1)
+ {
+ secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED;
+ goto out;
+ }
+
+ secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED;
+
+ out:
+ grub_free (moksbstate);
+ grub_free (setupmode);
+ grub_free (secboot);
+
+ if (secureboot == GRUB_EFI_SECUREBOOT_MODE_DISABLED)
+ secureboot_str = "Disabled";
+ else if (secureboot == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+ secureboot_str = "Enabled";
+
+ grub_dprintf ("efi", "UEFI Secure Boot state: %s\n", secureboot_str);
+
+ return secureboot;
+}
diff --git a/include/grub/efi/sb.h b/include/grub/efi/sb.h
new file mode 100644
index 000000000..a33d985e3
--- /dev/null
+++ b/include/grub/efi/sb.h
@@ -0,0 +1,40 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2020 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/>.
+ */
+
+#ifndef GRUB_EFI_SB_H
+#define GRUB_EFI_SB_H 1
+
+#include <grub/types.h>
+#include <grub/dl.h>
+
+#define GRUB_EFI_SECUREBOOT_MODE_UNSET 0
+#define GRUB_EFI_SECUREBOOT_MODE_UNKNOWN 1
+#define GRUB_EFI_SECUREBOOT_MODE_DISABLED 2
+#define GRUB_EFI_SECUREBOOT_MODE_ENABLED 3
+
+#ifdef GRUB_MACHINE_EFI
+extern grub_uint8_t
+EXPORT_FUNC (grub_efi_get_secureboot) (void);
+#else
+static inline grub_uint8_t
+grub_efi_get_secureboot (void)
+{
+ return GRUB_EFI_SECUREBOOT_MODE_UNSET;
+}
+#endif
+#endif /* GRUB_EFI_SB_H */
--
2.26.2

View File

@ -1,90 +0,0 @@
From a0659724e8fb6ddc9b6db68973e50637cf781605 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 3 Dec 2020 16:01:49 +0100
Subject: [PATCH 06/46] efi: Only register shim_lock verifier if shim_lock
protocol is found and SB enabled
The shim_lock module registers a verifier to call shim's verify, but the
handler is registered even when the shim_lock protocol was not installed.
This doesn't cause a NULL pointer dereference in shim_lock_write() because
the shim_lock_init() function just returns GRUB_ERR_NONE if sl isn't set.
But in that case there's no point to even register the shim_lock verifier
since won't do anything. Additionally, it is only useful when Secure Boot
is enabled.
Finally, don't assume that the shim_lock protocol will always be present
when the shim_lock_write() function is called, and check for it on every
call to this function.
Reported-by: Michael Chang <mchang@suse.com>
Reported-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/efi/shim_lock.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/grub-core/commands/efi/shim_lock.c b/grub-core/commands/efi/shim_lock.c
index d8f52d721..f7f3109d6 100644
--- a/grub-core/commands/efi/shim_lock.c
+++ b/grub-core/commands/efi/shim_lock.c
@@ -20,6 +20,7 @@
#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>
@@ -28,7 +29,6 @@
GRUB_MOD_LICENSE ("GPLv3+");
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[] = {"iorw", "memrw", "wrmsr", NULL};
@@ -43,9 +43,6 @@ shim_lock_init (grub_file_t io, enum grub_file_type type,
*flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
- if (!sl)
- return GRUB_ERR_NONE;
-
switch (type & GRUB_FILE_TYPE_MASK)
{
case GRUB_FILE_TYPE_GRUB_MODULE:
@@ -100,6 +97,11 @@ shim_lock_init (grub_file_t io, enum grub_file_type type,
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"));
@@ -115,12 +117,13 @@ struct grub_file_verifier shim_lock =
GRUB_MOD_INIT(shim_lock)
{
- sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
- grub_verifier_register (&shim_lock);
+ grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0);
- if (!sl)
+ if (sl == NULL || grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
return;
+ grub_verifier_register (&shim_lock);
+
grub_dl_set_persistent (mod);
}
--
2.26.2

View File

@ -0,0 +1,97 @@
From 496890ebd2605eb1ff15f8d96c30b5d617f1bb85 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
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 <cyphermox@ubuntu.com>
Signed-off-by: Michael Chang <mchang@suse.com>
---
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

View File

@ -1,129 +0,0 @@
From ea5950d8597278ba9066f24d7abcee403f825668 Mon Sep 17 00:00:00 2001
From: Marco A Benatto <mbenatto@redhat.com>
Date: Wed, 23 Sep 2020 11:33:33 -0400
Subject: [PATCH 07/46] verifiers: Move verifiers API to kernel image
Move verifiers API from a module to the kernel image, so it can be
used there as well. There are no functional changes in this patch.
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>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 6 +-----
grub-core/kern/main.c | 4 ++++
grub-core/{commands => kern}/verifiers.c | 8 ++------
include/grub/verify.h | 9 ++++++---
5 files changed, 14 insertions(+), 14 deletions(-)
rename grub-core/{commands => kern}/verifiers.c (97%)
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 5ff3afd62..3569b7101 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -91,6 +91,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/verify.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 072b1628c..5cb869f5b 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -140,6 +140,7 @@ kernel = {
common = kern/rescue_parser.c;
common = kern/rescue_reader.c;
common = kern/term.c;
+ common = kern/verifiers.c;
noemu = kern/compiler-rt.c;
noemu = kern/mm.c;
@@ -943,11 +944,6 @@ module = {
cppflags = '-I$(srcdir)/lib/posix_wrap';
};
-module = {
- name = verifiers;
- common = commands/verifiers.c;
-};
-
module = {
name = shim_lock;
common = commands/efi/shim_lock.c;
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 9cad0c448..73967e2f5 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -29,6 +29,7 @@
#include <grub/command.h>
#include <grub/reader.h>
#include <grub/parser.h>
+#include <grub/verify.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/memory.h>
@@ -274,6 +275,9 @@ grub_main (void)
grub_printf ("Welcome to GRUB!\n\n");
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+ /* Init verifiers API. */
+ grub_verifiers_init ();
+
grub_load_config ();
grub_boot_time ("Before loading embedded modules.");
diff --git a/grub-core/commands/verifiers.c b/grub-core/kern/verifiers.c
similarity index 97%
rename from grub-core/commands/verifiers.c
rename to grub-core/kern/verifiers.c
index 7b9297cd3..3d19bffd1 100644
--- a/grub-core/commands/verifiers.c
+++ b/grub-core/kern/verifiers.c
@@ -218,12 +218,8 @@ grub_verify_string (char *str, enum grub_verify_string_type type)
return GRUB_ERR_NONE;
}
-GRUB_MOD_INIT(verifiers)
+void
+grub_verifiers_init (void)
{
grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);
}
-
-GRUB_MOD_FINI(verifiers)
-{
- grub_file_filter_unregister (GRUB_FILE_FILTER_VERIFY);
-}
diff --git a/include/grub/verify.h b/include/grub/verify.h
index ea0491433..cd129c398 100644
--- a/include/grub/verify.h
+++ b/include/grub/verify.h
@@ -64,7 +64,10 @@ struct grub_file_verifier
grub_err_t (*verify_string) (char *str, enum grub_verify_string_type type);
};
-extern struct grub_file_verifier *grub_file_verifiers;
+extern struct grub_file_verifier *EXPORT_VAR (grub_file_verifiers);
+
+extern void
+grub_verifiers_init (void);
static inline void
grub_verifier_register (struct grub_file_verifier *ver)
@@ -78,7 +81,7 @@ grub_verifier_unregister (struct grub_file_verifier *ver)
grub_list_remove (GRUB_AS_LIST (ver));
}
-grub_err_t
-grub_verify_string (char *str, enum grub_verify_string_type type);
+extern grub_err_t
+EXPORT_FUNC (grub_verify_string) (char *str, enum grub_verify_string_type type);
#endif /* ! GRUB_VERIFY_HEADER */
--
2.26.2

View File

@ -1,368 +0,0 @@
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

View File

@ -1,430 +0,0 @@
From 1aebb5645e749917034444b24b88825ea557cae9 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Mon, 28 Sep 2020 20:08:02 +0200
Subject: [PATCH 09/46] kern: Add lockdown support
When the GRUB starts on a secure boot platform, some commands can be
used to subvert the protections provided by the verification mechanism and
could lead to booting untrusted system.
To prevent that situation, allow GRUB to be locked down. That way the code
may check if GRUB has been locked down and further restrict the commands
that are registered or what subset of their functionality could be used.
The lockdown support adds the following components:
* The grub_lockdown() function which can be used to lockdown GRUB if,
e.g., UEFI Secure Boot is enabled.
* The grub_is_lockdown() function which can be used to check if the GRUB
was locked down.
* A verifier that flags OS kernels, the GRUB modules, Device Trees and ACPI
tables as GRUB_VERIFY_FLAGS_DEFER_AUTH to defer verification to other
verifiers. These files are only successfully verified if another registered
verifier returns success. Otherwise, the whole verification process fails.
For example, PE/COFF binaries verification can be done by the shim_lock
verifier which validates the signatures using the shim_lock protocol.
However, the verification is not deferred directly to the shim_lock verifier.
The shim_lock verifier is hooked into the verification process instead.
* A set of grub_{command,extcmd}_lockdown functions that can be used by
code registering command handlers, to only register unsafe commands if
the GRUB has not been locked down.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
conf/Makefile.common | 2 +
docs/grub-dev.texi | 27 +++++++++++++
docs/grub.texi | 8 ++++
grub-core/Makefile.am | 5 ++-
grub-core/Makefile.core.def | 1 +
grub-core/commands/extcmd.c | 23 +++++++++++
grub-core/kern/command.c | 24 +++++++++++
grub-core/kern/lockdown.c | 80 +++++++++++++++++++++++++++++++++++++
include/grub/command.h | 5 +++
include/grub/extcmd.h | 7 ++++
include/grub/lockdown.h | 44 ++++++++++++++++++++
11 files changed, 225 insertions(+), 1 deletion(-)
create mode 100644 grub-core/kern/lockdown.c
create mode 100644 include/grub/lockdown.h
diff --git a/conf/Makefile.common b/conf/Makefile.common
index 6cd71cbb2..2a1a886f6 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -84,7 +84,9 @@ CPPFLAGS_PARTTOOL_LIST = -Dgrub_parttool_register=PARTTOOL_LIST_MARKER
CPPFLAGS_TERMINAL_LIST = '-Dgrub_term_register_input(...)=INPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)'
+CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_lockdown(...)=COMMAND_LOCKDOWN_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_LIST_MARKER(__VA_ARGS__)'
+CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd_lockdown(...)=EXTCOMMAND_LOCKDOWN_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_p1(...)=P1COMMAND_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_FDT_LIST := '-Dgrub_fdtbus_register(...)=FDT_DRIVER_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_MARKER = $(CPPFLAGS_FS_LIST) $(CPPFLAGS_VIDEO_LIST) \
diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
index ee389fd83..635ec7231 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -86,6 +86,7 @@ This edition documents version @value{VERSION}.
* PFF2 Font File Format::
* Graphical Menu Software Design::
* Verifiers framework::
+* Lockdown framework::
* Copying This Manual:: Copying This Manual
* Index::
@end menu
@@ -2086,6 +2087,32 @@ Optionally at the end of the file @samp{fini}, if it exists, is called with just
the context. If you return no error during any of @samp{init}, @samp{write} and
@samp{fini} then the file is considered as having succeded verification.
+@node Lockdown framework
+@chapter Lockdown framework
+
+The GRUB can be locked down, which is a restricted mode where some operations
+are not allowed. For instance, some commands cannot be used when the GRUB is
+locked down.
+
+The function
+@code{grub_lockdown()} is used to lockdown GRUB and the function
+@code{grub_is_lockdown()} function can be used to check whether lockdown is
+enabled or not. When enabled, the function returns @samp{GRUB_LOCKDOWN_ENABLED}
+and @samp{GRUB_LOCKDOWN_DISABLED} when is not enabled.
+
+The following functions can be used to register the commands that can only be
+used when lockdown is disabled:
+
+@itemize
+
+@item @code{grub_cmd_lockdown()} registers command which should not run when the
+GRUB is in lockdown mode.
+
+@item @code{grub_cmd_lockdown()} registers extended command which should not run
+when the GRUB is in lockdown mode.
+
+@end itemize
+
@node Copying This Manual
@appendix Copying This Manual
diff --git a/docs/grub.texi b/docs/grub.texi
index d3fbc81db..a459a71e4 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5598,6 +5598,7 @@ environment variables and commands are listed in the same order.
* Using digital signatures:: Booting digitally signed code
* UEFI secure boot and shim:: Booting digitally signed PE files
* Measured Boot:: Measuring boot components
+* Lockdown:: Lockdown when booting on a secure setup
@end menu
@node Authentication and authorisation
@@ -5812,6 +5813,13 @@ into @file{core.img} in order to avoid a potential gap in measurement between
Measured boot is currently only supported on EFI platforms.
+@node Lockdown
+@section Lockdown when booting on a secure setup
+
+The GRUB can be locked down when booted on a secure boot environment, for example
+if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will
+be restricted and some operations/commands cannot be executed.
+
@node Platform limitations
@chapter Platform limitations
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 3569b7101..6b2e5e139 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -80,6 +80,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lockdown.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h
@@ -378,8 +379,10 @@ command.lst: $(MARKER_FILES)
b=`basename $$pp .marker`; \
sed -n \
-e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
+ -e "/EXTCOMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
- -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
+ -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" \
+ -e "/COMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
done) | sort -u > $@
platform_DATA += command.lst
CLEANFILES += command.lst
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 8c8f8c579..a00e7f983 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -205,6 +205,7 @@ kernel = {
efi = kern/acpi.c;
efi = kern/efi/acpi.c;
efi = kern/efi/sb.c;
+ efi = kern/lockdown.c;
i386_coreboot = kern/i386/pc/acpi.c;
i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c;
diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c
index 69574e2b0..90a5ca24a 100644
--- a/grub-core/commands/extcmd.c
+++ b/grub-core/commands/extcmd.c
@@ -19,6 +19,7 @@
#include <grub/mm.h>
#include <grub/list.h>
+#include <grub/lockdown.h>
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/script_sh.h>
@@ -110,6 +111,28 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func,
summary, description, parser, 1);
}
+static grub_err_t
+grub_extcmd_lockdown (grub_extcmd_context_t ctxt __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **argv __attribute__ ((unused)))
+{
+ return grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("%s: the command is not allowed when lockdown is enforced"),
+ ctxt->extcmd->cmd->name);
+}
+
+grub_extcmd_t
+grub_register_extcmd_lockdown (const char *name, grub_extcmd_func_t func,
+ grub_command_flags_t flags, const char *summary,
+ const char *description,
+ const struct grub_arg_option *parser)
+{
+ if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
+ func = grub_extcmd_lockdown;
+
+ return grub_register_extcmd (name, func, flags, summary, description, parser);
+}
+
void
grub_unregister_extcmd (grub_extcmd_t ext)
{
diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c
index acd721879..4aabcd4b5 100644
--- a/grub-core/kern/command.c
+++ b/grub-core/kern/command.c
@@ -17,6 +17,7 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <grub/lockdown.h>
#include <grub/mm.h>
#include <grub/command.h>
@@ -77,6 +78,29 @@ grub_register_command_prio (const char *name,
return cmd;
}
+static grub_err_t
+grub_cmd_lockdown (grub_command_t cmd __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **argv __attribute__ ((unused)))
+
+{
+ return grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("%s: the command is not allowed when lockdown is enforced"),
+ cmd->name);
+}
+
+grub_command_t
+grub_register_command_lockdown (const char *name,
+ grub_command_func_t func,
+ const char *summary,
+ const char *description)
+{
+ if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
+ func = grub_cmd_lockdown;
+
+ return grub_register_command_prio (name, func, summary, description, 0);
+}
+
void
grub_unregister_command (grub_command_t cmd)
{
diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
new file mode 100644
index 000000000..1e56c0b80
--- /dev/null
+++ b/grub-core/kern/lockdown.c
@@ -0,0 +1,80 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2020 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/>.
+ *
+ */
+
+#include <grub/dl.h>
+#include <grub/file.h>
+#include <grub/lockdown.h>
+#include <grub/verify.h>
+
+static int lockdown = GRUB_LOCKDOWN_DISABLED;
+
+static grub_err_t
+lockdown_verifier_init (grub_file_t io __attribute__ ((unused)),
+ enum grub_file_type type,
+ void **context __attribute__ ((unused)),
+ enum grub_verify_flags *flags)
+{
+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
+
+ switch (type & GRUB_FILE_TYPE_MASK)
+ {
+ case GRUB_FILE_TYPE_GRUB_MODULE:
+ case GRUB_FILE_TYPE_LINUX_KERNEL:
+ case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
+ case GRUB_FILE_TYPE_XEN_HYPERVISOR:
+ case GRUB_FILE_TYPE_BSD_KERNEL:
+ case GRUB_FILE_TYPE_XNU_KERNEL:
+ case GRUB_FILE_TYPE_PLAN9_KERNEL:
+ case GRUB_FILE_TYPE_NTLDR:
+ case GRUB_FILE_TYPE_TRUECRYPT:
+ case GRUB_FILE_TYPE_FREEDOS:
+ case GRUB_FILE_TYPE_PXECHAINLOADER:
+ case GRUB_FILE_TYPE_PCCHAINLOADER:
+ case GRUB_FILE_TYPE_COREBOOT_CHAINLOADER:
+ case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
+ case GRUB_FILE_TYPE_ACPI_TABLE:
+ case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE:
+ *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH;
+
+ /* Fall through. */
+
+ default:
+ return GRUB_ERR_NONE;
+ }
+}
+
+struct grub_file_verifier lockdown_verifier =
+ {
+ .name = "lockdown_verifier",
+ .init = lockdown_verifier_init,
+ };
+
+void
+grub_lockdown (void)
+{
+ lockdown = GRUB_LOCKDOWN_ENABLED;
+
+ grub_verifier_register (&lockdown_verifier);
+}
+
+int
+grub_is_lockdown (void)
+{
+ return lockdown;
+}
diff --git a/include/grub/command.h b/include/grub/command.h
index eee4e847e..2a6f7f846 100644
--- a/include/grub/command.h
+++ b/include/grub/command.h
@@ -86,6 +86,11 @@ EXPORT_FUNC(grub_register_command_prio) (const char *name,
const char *summary,
const char *description,
int prio);
+grub_command_t
+EXPORT_FUNC(grub_register_command_lockdown) (const char *name,
+ grub_command_func_t func,
+ const char *summary,
+ const char *description);
void EXPORT_FUNC(grub_unregister_command) (grub_command_t cmd);
static inline grub_command_t
diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h
index 19fe59266..fe9248b8b 100644
--- a/include/grub/extcmd.h
+++ b/include/grub/extcmd.h
@@ -62,6 +62,13 @@ grub_extcmd_t EXPORT_FUNC(grub_register_extcmd) (const char *name,
const char *description,
const struct grub_arg_option *parser);
+grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_lockdown) (const char *name,
+ grub_extcmd_func_t func,
+ grub_command_flags_t flags,
+ const char *summary,
+ const char *description,
+ const struct grub_arg_option *parser);
+
grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_prio) (const char *name,
grub_extcmd_func_t func,
grub_command_flags_t flags,
diff --git a/include/grub/lockdown.h b/include/grub/lockdown.h
new file mode 100644
index 000000000..40531fa82
--- /dev/null
+++ b/include/grub/lockdown.h
@@ -0,0 +1,44 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2020 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/>.
+ */
+
+#ifndef GRUB_LOCKDOWN_H
+#define GRUB_LOCKDOWN_H 1
+
+#include <grub/symbol.h>
+
+#define GRUB_LOCKDOWN_DISABLED 0
+#define GRUB_LOCKDOWN_ENABLED 1
+
+#ifdef GRUB_MACHINE_EFI
+extern void
+EXPORT_FUNC (grub_lockdown) (void);
+extern int
+EXPORT_FUNC (grub_is_lockdown) (void);
+#else
+static inline void
+grub_lockdown (void)
+{
+}
+
+static inline int
+grub_is_lockdown (void)
+{
+ return GRUB_LOCKDOWN_DISABLED;
+}
+#endif
+#endif /* ! GRUB_LOCKDOWN_H */
--
2.26.2

View File

@ -1,57 +0,0 @@
From 959db537b12c5e76c244ccc51cbbed7f27b0abe2 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Tue, 2 Feb 2021 19:59:48 +0100
Subject: [PATCH 10/46] kern/lockdown: Set a variable if the GRUB is locked
down
It may be useful for scripts to determine whether the GRUB is locked
down or not. Add the lockdown variable which is set to "y" when the GRUB
is locked down.
Suggested-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 3 +++
grub-core/kern/lockdown.c | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/docs/grub.texi b/docs/grub.texi
index a459a71e4..3a4d18e06 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5820,6 +5820,9 @@ The GRUB can be locked down when booted on a secure boot environment, for exampl
if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will
be restricted and some operations/commands cannot be executed.
+The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down.
+Otherwise it does not exit.
+
@node Platform limitations
@chapter Platform limitations
diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c
index 1e56c0b80..0bc70fd42 100644
--- a/grub-core/kern/lockdown.c
+++ b/grub-core/kern/lockdown.c
@@ -18,6 +18,7 @@
*/
#include <grub/dl.h>
+#include <grub/env.h>
#include <grub/file.h>
#include <grub/lockdown.h>
#include <grub/verify.h>
@@ -71,6 +72,9 @@ grub_lockdown (void)
lockdown = GRUB_LOCKDOWN_ENABLED;
grub_verifier_register (&lockdown_verifier);
+
+ grub_env_set ("lockdown", "y");
+ grub_env_export ("lockdown");
}
int
--
2.26.2

View File

@ -1,49 +0,0 @@
From a255fd33e08015335aeac619348536b5fda8303e Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Mon, 28 Sep 2020 20:08:29 +0200
Subject: [PATCH 11/46] efi: Lockdown the GRUB when the UEFI Secure Boot is
enabled
If the UEFI Secure Boot is enabled then the GRUB must be locked down
to prevent executing code that can potentially be used to subvert its
verification mechanisms.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/efi/init.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c
index 9c143eed7..08ef2b8f4 100644
--- a/grub-core/kern/efi/init.c
+++ b/grub-core/kern/efi/init.c
@@ -21,6 +21,7 @@
#include <grub/efi/console.h>
#include <grub/efi/disk.h>
#include <grub/efi/sb.h>
+#include <grub/lockdown.h>
#include <grub/term.h>
#include <grub/misc.h>
#include <grub/env.h>
@@ -41,8 +42,15 @@ 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 ();
+ /*
+ * Lockdown the GRUB and register the shim_lock verifier
+ * if the UEFI Secure Boot is enabled.
+ */
+ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
+ {
+ grub_lockdown ();
+ grub_shim_lock_verifier_setup ();
+ }
efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer,
0, 0, 0, NULL);
--
2.26.2

View File

@ -1,231 +0,0 @@
From fd04f7a20cffb4bde9deb688f4e33e5ff2c80181 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Mon, 28 Sep 2020 20:08:33 +0200
Subject: [PATCH 12/46] efi: Use grub_is_lockdown() instead of hardcoding a
disabled modules list
Now the GRUB can check if it has been locked down and this can be used to
prevent executing commands that can be utilized to circumvent the UEFI
Secure Boot mechanisms. So, instead of hardcoding a list of modules that
have to be disabled, prevent the usage of commands that can be dangerous.
This not only allows the commands to be disabled on other platforms, but
also properly separate the concerns. Since the shim_lock verifier logic
should be only about preventing to run untrusted binaries and not about
defining these kind of policies.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 15 +++++++-----
grub-core/commands/i386/wrmsr.c | 5 ++--
grub-core/commands/iorw.c | 19 +++++++--------
grub-core/commands/memrw.c | 19 +++++++--------
grub-core/kern/efi/sb.c | 41 ---------------------------------
5 files changed, 32 insertions(+), 67 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 3a4d18e06..6d8d32b0b 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5256,6 +5256,9 @@ only applies to the particular cpu/core/thread that runs the command.
Also, if you specify a reserved or unimplemented MSR address, it will
cause a general protection exception (which is not currently being handled)
and the system will reboot.
+
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+ This is done to prevent subverting various security mechanisms.
@end deffn
@node xen_hypervisor
@@ -5769,12 +5772,12 @@ 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 verifier logic.
+All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables,
+Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands
+that can be used to subvert the UEFI secure boot mechanism, such as @command{iorw}
+and @command{memrw} will not be available when the UEFI secure boot is enabled.
+This is done for security reasons and are enforced by the GRUB Lockdown mechanism
+(@pxref{Lockdown}).
@node Measured Boot
@section Measuring boot components
diff --git a/grub-core/commands/i386/wrmsr.c b/grub-core/commands/i386/wrmsr.c
index 9c5e510eb..56a29c29f 100644
--- a/grub-core/commands/i386/wrmsr.c
+++ b/grub-core/commands/i386/wrmsr.c
@@ -24,6 +24,7 @@
#include <grub/env.h>
#include <grub/command.h>
#include <grub/extcmd.h>
+#include <grub/lockdown.h>
#include <grub/i18n.h>
#include <grub/i386/cpuid.h>
#include <grub/i386/wrmsr.h>
@@ -83,8 +84,8 @@ grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char
GRUB_MOD_INIT(wrmsr)
{
- cmd_write = grub_register_command ("wrmsr", grub_cmd_msr_write, N_("ADDR VALUE"),
- N_("Write a value to a CPU model specific register."));
+ cmd_write = grub_register_command_lockdown ("wrmsr", grub_cmd_msr_write, N_("ADDR VALUE"),
+ N_("Write a value to a CPU model specific register."));
}
GRUB_MOD_FINI(wrmsr)
diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c
index a0c164e54..584baec8f 100644
--- a/grub-core/commands/iorw.c
+++ b/grub-core/commands/iorw.c
@@ -23,6 +23,7 @@
#include <grub/env.h>
#include <grub/cpu/io.h>
#include <grub/i18n.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -131,17 +132,17 @@ GRUB_MOD_INIT(memrw)
N_("PORT"), N_("Read 32-bit value from PORT."),
options);
cmd_write_byte =
- grub_register_command ("outb", grub_cmd_write,
- N_("PORT VALUE [MASK]"),
- N_("Write 8-bit VALUE to PORT."));
+ grub_register_command_lockdown ("outb", grub_cmd_write,
+ N_("PORT VALUE [MASK]"),
+ N_("Write 8-bit VALUE to PORT."));
cmd_write_word =
- grub_register_command ("outw", grub_cmd_write,
- N_("PORT VALUE [MASK]"),
- N_("Write 16-bit VALUE to PORT."));
+ grub_register_command_lockdown ("outw", grub_cmd_write,
+ N_("PORT VALUE [MASK]"),
+ N_("Write 16-bit VALUE to PORT."));
cmd_write_dword =
- grub_register_command ("outl", grub_cmd_write,
- N_("ADDR VALUE [MASK]"),
- N_("Write 32-bit VALUE to PORT."));
+ grub_register_command_lockdown ("outl", grub_cmd_write,
+ N_("ADDR VALUE [MASK]"),
+ N_("Write 32-bit VALUE to PORT."));
}
GRUB_MOD_FINI(memrw)
diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c
index 98769eadb..d401a6db0 100644
--- a/grub-core/commands/memrw.c
+++ b/grub-core/commands/memrw.c
@@ -22,6 +22,7 @@
#include <grub/extcmd.h>
#include <grub/env.h>
#include <grub/i18n.h>
+#include <grub/lockdown.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -133,17 +134,17 @@ GRUB_MOD_INIT(memrw)
N_("ADDR"), N_("Read 32-bit value from ADDR."),
options);
cmd_write_byte =
- grub_register_command ("write_byte", grub_cmd_write,
- N_("ADDR VALUE [MASK]"),
- N_("Write 8-bit VALUE to ADDR."));
+ grub_register_command_lockdown ("write_byte", grub_cmd_write,
+ N_("ADDR VALUE [MASK]"),
+ N_("Write 8-bit VALUE to ADDR."));
cmd_write_word =
- grub_register_command ("write_word", grub_cmd_write,
- N_("ADDR VALUE [MASK]"),
- N_("Write 16-bit VALUE to ADDR."));
+ grub_register_command_lockdown ("write_word", grub_cmd_write,
+ N_("ADDR VALUE [MASK]"),
+ N_("Write 16-bit VALUE to ADDR."));
cmd_write_dword =
- grub_register_command ("write_dword", grub_cmd_write,
- N_("ADDR VALUE [MASK]"),
- N_("Write 32-bit VALUE to ADDR."));
+ grub_register_command_lockdown ("write_dword", grub_cmd_write,
+ N_("ADDR VALUE [MASK]"),
+ N_("Write 32-bit VALUE to ADDR."));
}
GRUB_MOD_FINI(memrw)
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 8bd5e936d..5d7210a82 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -30,9 +30,6 @@
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.
*
@@ -121,53 +118,15 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
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. */
--
2.26.2

View File

@ -1,75 +0,0 @@
From 08c63ad119ce0c0d0de56d9878f0be6811f623d4 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Mon, 28 Sep 2020 20:08:41 +0200
Subject: [PATCH 13/46] acpi: Don't register the acpi command when locked down
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The command is not allowed when lockdown is enforced. Otherwise an
attacker can instruct the GRUB to load an SSDT table to overwrite
the kernel lockdown configuration and later load and execute
unsigned code.
Fixes: CVE-2020-14372
Reported-by: Máté Kukri <km@mkukri.xyz>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 5 +++++
grub-core/commands/acpi.c | 15 ++++++++-------
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 6d8d32b0b..2ee8721a1 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3986,6 +3986,11 @@ Normally, this command will replace the Root System Description Pointer
(RSDP) in the Extended BIOS Data Area to point to the new tables. If the
@option{--no-ebda} option is used, the new tables will be known only to
GRUB, but may be used by GRUB's EFI emulation.
+
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+ Otherwise an attacker can instruct the GRUB to load an SSDT table to
+ overwrite the kernel lockdown configuration and later load and execute
+ unsigned code.
@end deffn
diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c
index 5a1499aa0..1215f2a62 100644
--- a/grub-core/commands/acpi.c
+++ b/grub-core/commands/acpi.c
@@ -27,6 +27,7 @@
#include <grub/mm.h>
#include <grub/memory.h>
#include <grub/i18n.h>
+#include <grub/lockdown.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
@@ -775,13 +776,13 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(acpi)
{
- cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0,
- N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
- "--load-only=TABLE1,TABLE2] FILE1"
- " [FILE2] [...]"),
- N_("Load host ACPI tables and tables "
- "specified by arguments."),
- options);
+ cmd = grub_register_extcmd_lockdown ("acpi", grub_cmd_acpi, 0,
+ N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
+ "--load-only=TABLE1,TABLE2] FILE1"
+ " [FILE2] [...]"),
+ N_("Load host ACPI tables and tables "
+ "specified by arguments."),
+ options);
}
GRUB_MOD_FINI(acpi)
--
2.26.2

View File

@ -1,69 +0,0 @@
From cbd4d630728847bcc3eb82c4a1667fc7ba6de73a Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Wed, 14 Oct 2020 16:33:42 +0200
Subject: [PATCH 14/46] mmap: Don't register cutmem and badram commands when
lockdown is enforced
The cutmem and badram commands can be used to remove EFI memory regions
and potentially disable the UEFI Secure Boot. Prevent the commands to be
registered if the GRUB is locked down.
Fixes: CVE-2020-27779
Reported-by: Teddy Reed <teddy.reed@gmail.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 4 ++++
grub-core/mmap/mmap.c | 13 +++++++------
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 2ee8721a1..70bf91f40 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4051,6 +4051,10 @@ this page is to be filtered. This syntax makes it easy to represent patterns
that are often result of memory damage, due to physical distribution of memory
cells.
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+ This prevents removing EFI memory regions to potentially subvert the
+ security mechanisms provided by the UEFI secure boot.
+
@node blocklist
@subsection blocklist
diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c
index 57b4e9a72..7ebf32e1e 100644
--- a/grub-core/mmap/mmap.c
+++ b/grub-core/mmap/mmap.c
@@ -20,6 +20,7 @@
#include <grub/memory.h>
#include <grub/machine/memory.h>
#include <grub/err.h>
+#include <grub/lockdown.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/command.h>
@@ -534,12 +535,12 @@ static grub_command_t cmd, cmd_cut;
GRUB_MOD_INIT(mmap)
{
- cmd = grub_register_command ("badram", grub_cmd_badram,
- N_("ADDR1,MASK1[,ADDR2,MASK2[,...]]"),
- N_("Declare memory regions as faulty (badram)."));
- cmd_cut = grub_register_command ("cutmem", grub_cmd_cutmem,
- N_("FROM[K|M|G] TO[K|M|G]"),
- N_("Remove any memory regions in specified range."));
+ cmd = grub_register_command_lockdown ("badram", grub_cmd_badram,
+ N_("ADDR1,MASK1[,ADDR2,MASK2[,...]]"),
+ N_("Declare memory regions as faulty (badram)."));
+ cmd_cut = grub_register_command_lockdown ("cutmem", grub_cmd_cutmem,
+ N_("FROM[K|M|G] TO[K|M|G]"),
+ N_("Remove any memory regions in specified range."));
}
--
2.26.2

View File

@ -1,104 +0,0 @@
From d1a40f870dbcb55280f57673c1d9c2c7110df42a Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Wed, 24 Feb 2021 09:00:05 +0100
Subject: [PATCH 15/46] commands: Restrict commands that can load BIOS or DT
blobs when locked down
There are some more commands that should be restricted when the GRUB is
locked down. Following is the list of commands and reasons to restrict:
* fakebios: creates BIOS-like structures for backward compatibility with
existing OSes. This should not be allowed when locked down.
* loadbios: reads a BIOS dump from storage and loads it. This action
should not be allowed when locked down.
* devicetree: loads a Device Tree blob and passes it to the OS. It replaces
any Device Tree provided by the firmware. This also should
not be allowed when locked down.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 3 +++
grub-core/commands/efi/loadbios.c | 16 ++++++++--------
grub-core/loader/arm/linux.c | 6 +++---
grub-core/loader/efi/fdt.c | 4 ++--
4 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 70bf91f40..cf29a1797 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4236,6 +4236,9 @@ Load a device tree blob (.dtb) from a filesystem, for later use by a Linux
kernel. Does not perform merging with any device tree supplied by firmware,
but rather replaces it completely.
@ref{GNU/Linux}.
+
+Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
+ This is done to prevent subverting various security mechanisms.
@end deffn
@node distrust
diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c
index d41d521a4..5c7725f8b 100644
--- a/grub-core/commands/efi/loadbios.c
+++ b/grub-core/commands/efi/loadbios.c
@@ -205,14 +205,14 @@ static grub_command_t cmd_fakebios, cmd_loadbios;
GRUB_MOD_INIT(loadbios)
{
- cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
- 0, N_("Create BIOS-like structures for"
- " backward compatibility with"
- " existing OS."));
-
- cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
- N_("BIOS_DUMP [INT10_DUMP]"),
- N_("Load BIOS dump."));
+ cmd_fakebios = grub_register_command_lockdown ("fakebios", grub_cmd_fakebios,
+ 0, N_("Create BIOS-like structures for"
+ " backward compatibility with"
+ " existing OS."));
+
+ cmd_loadbios = grub_register_command_lockdown ("loadbios", grub_cmd_loadbios,
+ N_("BIOS_DUMP [INT10_DUMP]"),
+ N_("Load BIOS dump."));
}
GRUB_MOD_FINI(loadbios)
diff --git a/grub-core/loader/arm/linux.c b/grub-core/loader/arm/linux.c
index d70c17486..ed23dc71e 100644
--- a/grub-core/loader/arm/linux.c
+++ b/grub-core/loader/arm/linux.c
@@ -493,9 +493,9 @@ GRUB_MOD_INIT (linux)
0, N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
0, N_("Load initrd."));
- cmd_devicetree = grub_register_command ("devicetree", grub_cmd_devicetree,
- /* TRANSLATORS: DTB stands for device tree blob. */
- 0, N_("Load DTB file."));
+ cmd_devicetree = grub_register_command_lockdown ("devicetree", grub_cmd_devicetree,
+ /* TRANSLATORS: DTB stands for device tree blob. */
+ 0, N_("Load DTB file."));
my_mod = mod;
current_fdt = (const void *) grub_arm_firmware_get_boot_data ();
machine_type = grub_arm_firmware_get_machine_type ();
diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c
index ee9c5592c..003d07cd8 100644
--- a/grub-core/loader/efi/fdt.c
+++ b/grub-core/loader/efi/fdt.c
@@ -165,8 +165,8 @@ static grub_command_t cmd_devicetree;
GRUB_MOD_INIT (fdt)
{
cmd_devicetree =
- grub_register_command ("devicetree", grub_cmd_devicetree, 0,
- N_("Load DTB file."));
+ grub_register_command_lockdown ("devicetree", grub_cmd_devicetree, 0,
+ N_("Load DTB file."));
}
GRUB_MOD_FINI (fdt)
--
2.26.2

View File

@ -1,37 +0,0 @@
From 3e5b0593346fde8d92dd4e87ce15ff07e0cacf88 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Wed, 24 Feb 2021 22:59:59 +0100
Subject: [PATCH 16/46] commands/setpci: Restrict setpci command when locked
down
This command can set PCI devices register values, which makes it dangerous
in a locked down configuration. Restrict it so can't be used on this setup.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/setpci.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c
index d5bc97d60..fa2ba7d89 100644
--- a/grub-core/commands/setpci.c
+++ b/grub-core/commands/setpci.c
@@ -329,10 +329,10 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(setpci)
{
- cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0,
- N_("[-s POSITION] [-d DEVICE] [-v VAR] "
- "REGISTER[=VALUE[:MASK]]"),
- N_("Manipulate PCI devices."), options);
+ cmd = grub_register_extcmd_lockdown ("setpci", grub_cmd_setpci, 0,
+ N_("[-s POSITION] [-d DEVICE] [-v VAR] "
+ "REGISTER[=VALUE[:MASK]]"),
+ N_("Manipulate PCI devices."), options);
}
GRUB_MOD_FINI(setpci)
--
2.26.2

View File

@ -1,35 +0,0 @@
From 75dd393392f16194904c8958a22fe12034f915a3 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Wed, 24 Feb 2021 12:59:29 +0100
Subject: [PATCH 17/46] commands/hdparm: Restrict hdparm command when locked
down
The command can be used to get/set ATA disk parameters. Some of these can
be dangerous since change the disk behavior. Restrict it when locked down.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/hdparm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c
index d3fa9661e..2e2319e64 100644
--- a/grub-core/commands/hdparm.c
+++ b/grub-core/commands/hdparm.c
@@ -436,9 +436,9 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(hdparm)
{
- cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0,
- N_("[OPTIONS] DISK"),
- N_("Get/set ATA disk parameters."), options);
+ cmd = grub_register_extcmd_lockdown ("hdparm", grub_cmd_hdparm, 0,
+ N_("[OPTIONS] DISK"),
+ N_("Get/set ATA disk parameters."), options);
}
GRUB_MOD_FINI(hdparm)
--
2.26.2

View File

@ -1,61 +0,0 @@
From a4df9a0d74376aa4fc82f8c86c280cb087de01be Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Wed, 24 Feb 2021 15:03:26 +0100
Subject: [PATCH 18/46] gdb: Restrict GDB access when locked down
The gdbstub* commands allow to start and control a GDB stub running on
local host that can be used to connect from a remote debugger. Restrict
this functionality when the GRUB is locked down.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/gdb/gdb.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/grub-core/gdb/gdb.c b/grub-core/gdb/gdb.c
index 847a1e1e3..1818cb6f8 100644
--- a/grub-core/gdb/gdb.c
+++ b/grub-core/gdb/gdb.c
@@ -75,20 +75,24 @@ static grub_command_t cmd, cmd_stop, cmd_break;
GRUB_MOD_INIT (gdb)
{
grub_gdb_idtinit ();
- cmd = grub_register_command ("gdbstub", grub_cmd_gdbstub,
- N_("PORT"),
- /* TRANSLATORS: GDB stub is a small part of
- GDB functionality running on local host
- which allows remote debugger to
- connect to it. */
- N_("Start GDB stub on given port"));
- cmd_break = grub_register_command ("gdbstub_break", grub_cmd_gdb_break,
- /* TRANSLATORS: this refers to triggering
- a breakpoint so that the user will land
- into GDB. */
- 0, N_("Break into GDB"));
- cmd_stop = grub_register_command ("gdbstub_stop", grub_cmd_gdbstop,
- 0, N_("Stop GDB stub"));
+ cmd = grub_register_command_lockdown ("gdbstub", grub_cmd_gdbstub,
+ N_("PORT"),
+ /*
+ * TRANSLATORS: GDB stub is a small part of
+ * GDB functionality running on local host
+ * which allows remote debugger to
+ * connect to it.
+ */
+ N_("Start GDB stub on given port"));
+ cmd_break = grub_register_command_lockdown ("gdbstub_break", grub_cmd_gdb_break,
+ /*
+ * TRANSLATORS: this refers to triggering
+ * a breakpoint so that the user will land
+ * into GDB.
+ */
+ 0, N_("Break into GDB"));
+ cmd_stop = grub_register_command_lockdown ("gdbstub_stop", grub_cmd_gdbstop,
+ 0, N_("Stop GDB stub"));
}
GRUB_MOD_FINI (gdb)
--
2.26.2

View File

@ -1,60 +0,0 @@
From da75051bd36ce97b94254f17a6a94b5cbdf77d48 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Wed, 24 Feb 2021 14:44:38 +0100
Subject: [PATCH 19/46] loader/xnu: Don't allow loading extension and packages
when locked down
The shim_lock verifier validates the XNU kernels but no its extensions
and packages. Prevent these to be loaded when the GRUB is locked down.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/loader/xnu.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c
index 77d7060e1..07232d2a1 100644
--- a/grub-core/loader/xnu.c
+++ b/grub-core/loader/xnu.c
@@ -1482,20 +1482,23 @@ GRUB_MOD_INIT(xnu)
N_("Load XNU image."));
cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64,
0, N_("Load 64-bit XNU image."));
- cmd_mkext = grub_register_command ("xnu_mkext", grub_cmd_xnu_mkext, 0,
- N_("Load XNU extension package."));
- cmd_kext = grub_register_command ("xnu_kext", grub_cmd_xnu_kext, 0,
- N_("Load XNU extension."));
- cmd_kextdir = grub_register_command ("xnu_kextdir", grub_cmd_xnu_kextdir,
- /* TRANSLATORS: OSBundleRequired is a
- variable name in xnu extensions
- manifests. It behaves mostly like
- GNU/Linux runlevels.
- */
- N_("DIRECTORY [OSBundleRequired]"),
- /* TRANSLATORS: There are many extensions
- in extension directory. */
- N_("Load XNU extension directory."));
+ cmd_mkext = grub_register_command_lockdown ("xnu_mkext", grub_cmd_xnu_mkext, 0,
+ N_("Load XNU extension package."));
+ cmd_kext = grub_register_command_lockdown ("xnu_kext", grub_cmd_xnu_kext, 0,
+ N_("Load XNU extension."));
+ cmd_kextdir = grub_register_command_lockdown ("xnu_kextdir", grub_cmd_xnu_kextdir,
+ /*
+ * TRANSLATORS: OSBundleRequired is
+ * a variable name in xnu extensions
+ * manifests. It behaves mostly like
+ * GNU/Linux runlevels.
+ */
+ N_("DIRECTORY [OSBundleRequired]"),
+ /*
+ * TRANSLATORS: There are many extensions
+ * in extension directory.
+ */
+ N_("Load XNU extension directory."));
cmd_ramdisk = grub_register_command ("xnu_ramdisk", grub_cmd_xnu_ramdisk, 0,
/* TRANSLATORS: ramdisk here isn't identifier. It can be translated. */
N_("Load XNU ramdisk. "
--
2.26.2

View File

@ -1,87 +0,0 @@
From 01df3544dd3ea226e2832735c0284fc6d9157347 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Tue, 29 Sep 2020 14:08:55 +0200
Subject: [PATCH 20/46] dl: Only allow unloading modules that are not
dependencies
When a module is attempted to be removed its reference counter is always
decremented. This means that repeated rmmod invocations will cause the
module to be unloaded even if another module depends on it.
This may lead to a use-after-free scenario allowing an attacker to execute
arbitrary code and by-pass the UEFI Secure Boot protection.
While being there, add the extern keyword to some function declarations in
that header file.
Fixes: CVE-2020-25632
Reported-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/minicmd.c | 7 +++++--
grub-core/kern/dl.c | 9 +++++++++
include/grub/dl.h | 8 +++++---
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
index 6bbce3128..fa498931e 100644
--- a/grub-core/commands/minicmd.c
+++ b/grub-core/commands/minicmd.c
@@ -140,8 +140,11 @@ grub_mini_cmd_rmmod (struct grub_command *cmd __attribute__ ((unused)),
if (grub_dl_is_persistent (mod))
return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload persistent module");
- if (grub_dl_unref (mod) <= 0)
- grub_dl_unload (mod);
+ if (grub_dl_ref_count (mod) > 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload referenced module");
+
+ grub_dl_unref (mod);
+ grub_dl_unload (mod);
return 0;
}
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 2a8372e14..e02f2afc5 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -553,6 +553,15 @@ grub_dl_unref (grub_dl_t mod)
return --mod->ref_count;
}
+int
+grub_dl_ref_count (grub_dl_t mod)
+{
+ if (mod == NULL)
+ return 0;
+
+ return mod->ref_count;
+}
+
static void
grub_dl_flush_cache (grub_dl_t mod)
{
diff --git a/include/grub/dl.h b/include/grub/dl.h
index f03c03561..b3753c9ca 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -203,9 +203,11 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size);
int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
-void grub_dl_unload_unneeded (void);
-int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
-int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
+extern void grub_dl_unload_unneeded (void);
+extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
+extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
+extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod);
+
extern grub_dl_t EXPORT_VAR(grub_dl_head);
#ifndef GRUB_UTIL
--
2.26.2

View File

@ -1,115 +0,0 @@
From 6f8f29ca383eaa60a0eab00d4a934a072190c128 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Fri, 11 Dec 2020 19:19:21 +0100
Subject: [PATCH 21/46] usb: Avoid possible out-of-bound accesses caused by
malicious devices
The maximum number of configurations and interfaces are fixed but there is
no out-of-bound checking to prevent a malicious USB device to report large
values for these and cause accesses outside the arrays' memory.
Fixes: CVE-2020-25647
Reported-by: Joseph Tartaro (IOActive)
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/bus/usb/usb.c | 15 ++++++++++++---
include/grub/usb.h | 10 +++++++---
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c
index 8da5e4c74..7cb3cc230 100644
--- a/grub-core/bus/usb/usb.c
+++ b/grub-core/bus/usb/usb.c
@@ -75,6 +75,9 @@ grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook,
grub_usb_err_t
grub_usb_clear_halt (grub_usb_device_t dev, int endpoint)
{
+ if (endpoint >= GRUB_USB_MAX_TOGGLE)
+ return GRUB_USB_ERR_BADDEVICE;
+
dev->toggle[endpoint] = 0;
return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
| GRUB_USB_REQTYPE_STANDARD
@@ -134,10 +137,10 @@ grub_usb_device_initialize (grub_usb_device_t dev)
return err;
descdev = &dev->descdev;
- for (i = 0; i < 8; i++)
+ for (i = 0; i < GRUB_USB_MAX_CONF; i++)
dev->config[i].descconf = NULL;
- if (descdev->configcnt == 0)
+ if (descdev->configcnt == 0 || descdev->configcnt > GRUB_USB_MAX_CONF)
{
err = GRUB_USB_ERR_BADDEVICE;
goto fail;
@@ -172,6 +175,12 @@ grub_usb_device_initialize (grub_usb_device_t dev)
/* Skip the configuration descriptor. */
pos = dev->config[i].descconf->length;
+ if (dev->config[i].descconf->numif > GRUB_USB_MAX_IF)
+ {
+ err = GRUB_USB_ERR_BADDEVICE;
+ goto fail;
+ }
+
/* Read all interfaces. */
for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
{
@@ -217,7 +226,7 @@ grub_usb_device_initialize (grub_usb_device_t dev)
fail:
- for (i = 0; i < 8; i++)
+ for (i = 0; i < GRUB_USB_MAX_CONF; i++)
grub_free (dev->config[i].descconf);
return err;
diff --git a/include/grub/usb.h b/include/grub/usb.h
index 512ae1dd0..6475c552f 100644
--- a/include/grub/usb.h
+++ b/include/grub/usb.h
@@ -23,6 +23,10 @@
#include <grub/usbdesc.h>
#include <grub/usbtrans.h>
+#define GRUB_USB_MAX_CONF 8
+#define GRUB_USB_MAX_IF 32
+#define GRUB_USB_MAX_TOGGLE 256
+
typedef struct grub_usb_device *grub_usb_device_t;
typedef struct grub_usb_controller *grub_usb_controller_t;
typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t;
@@ -167,7 +171,7 @@ struct grub_usb_configuration
struct grub_usb_desc_config *descconf;
/* Interfaces associated to this configuration. */
- struct grub_usb_interface interf[32];
+ struct grub_usb_interface interf[GRUB_USB_MAX_IF];
};
struct grub_usb_hub_port
@@ -191,7 +195,7 @@ struct grub_usb_device
struct grub_usb_controller controller;
/* Device configurations (after opening the device). */
- struct grub_usb_configuration config[8];
+ struct grub_usb_configuration config[GRUB_USB_MAX_CONF];
/* Device address. */
int addr;
@@ -203,7 +207,7 @@ struct grub_usb_device
int initialized;
/* Data toggle values (used for bulk transfers only). */
- int toggle[256];
+ int toggle[GRUB_USB_MAX_TOGGLE];
/* Used by libusb wrapper. Schedulded for removal. */
void *data;
--
2.26.2

View File

@ -1,54 +0,0 @@
From fafede32c0ed3bc1953c5663b58036a58fb7b6bd Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Fri, 22 Jan 2021 16:07:29 +1100
Subject: [PATCH 22/46] lib/arg: Block repeated short options that require an
argument
Fuzzing found the following crash:
search -hhhhhhhhhhhhhf
We didn't allocate enough option space for 13 hints because the
allocation code counts the number of discrete arguments (i.e. argc).
However, the shortopt parsing code will happily keep processing
a combination of short options without checking if those short
options require an argument. This means you can easily end writing
past the allocated option space.
This fixes a OOB write which can cause heap corruption.
Fixes: CVE-2021-20225
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/lib/arg.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c
index 3288609a5..537c5e94b 100644
--- a/grub-core/lib/arg.c
+++ b/grub-core/lib/arg.c
@@ -299,6 +299,19 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
it can have an argument value. */
if (*curshort)
{
+ /*
+ * Only permit further short opts if this one doesn't
+ * require a value.
+ */
+ if (opt->type != ARG_TYPE_NONE &&
+ !(opt->flags & GRUB_ARG_OPTION_OPTIONAL))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("missing mandatory option for `%s'"),
+ opt->longarg);
+ goto fail;
+ }
+
if (parse_option (cmd, opt, 0, usr) || grub_errno)
goto fail;
}
--
2.26.2

View File

@ -1,46 +0,0 @@
From 833324355ed1c88b509a2c5e8632a190ce11bf40 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Fri, 22 Jan 2021 17:10:48 +1100
Subject: [PATCH 23/46] commands/menuentry: Fix quoting in setparams_prefix()
Commit 9acdcbf32542 (use single quotes in menuentry setparams command)
says that expressing a quoted single quote will require 3 characters. It
actually requires (and always did require!) 4 characters:
str: a'b => a'\''b
len: 3 => 6 (2 for the letters + 4 for the quote)
This leads to not allocating enough memory and thus out of bounds writes
that have been observed to cause heap corruption.
Allocate 4 bytes for each single quote.
Commit 22e7dbb2bb81 (Fix quoting in legacy parser.) does the same
quoting, but it adds 3 as extra overhead on top of the single byte that
the quote already needs. So it's correct.
Fixes: CVE-2021-20233
Fixes: 9acdcbf32542 (use single quotes in menuentry setparams command)
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/menuentry.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
index 348d72dac..c36913752 100644
--- a/grub-core/commands/menuentry.c
+++ b/grub-core/commands/menuentry.c
@@ -233,7 +233,7 @@ setparams_prefix (int argc, char **args)
len += 3; /* 3 = 1 space + 2 quotes */
p = args[i];
while (*p)
- len += (*p++ == '\'' ? 3 : 1);
+ len += (*p++ == '\'' ? 4 : 1);
}
result = grub_malloc (len + 2);
--
2.26.2

View File

@ -1,50 +0,0 @@
From 61aebf1dd8213cd8e3d4b3493f4bb4c221331c17 Mon Sep 17 00:00:00 2001
From: Darren Kenny <darren.kenny@oracle.com>
Date: Fri, 22 Jan 2021 12:32:41 +0000
Subject: [PATCH 24/46] kern/parser: Fix resource leak if argc == 0
After processing the command-line yet arriving at the point where we are
setting argv, we are allocating memory, even if argc == 0, which makes
no sense since we never put anything into the allocated argv.
The solution is to simply return that we've successfully processed the
arguments but that argc == 0, and also ensure that argv is NULL when
we're not allocating anything in it.
There are only 2 callers of this function, and both are handling a zero
value in argc assuming nothing is allocated in argv.
Fixes: CID 96680
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/parser.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 619db3122..d1cf061ad 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -146,6 +146,7 @@ grub_parser_split_cmdline (const char *cmdline,
int i;
*argc = 0;
+ *argv = NULL;
do
{
if (!rd || !*rd)
@@ -207,6 +208,10 @@ grub_parser_split_cmdline (const char *cmdline,
(*argc)++;
}
+ /* If there are no args, then we're done. */
+ if (!*argc)
+ return 0;
+
/* Reserve memory for the return values. */
args = grub_malloc (bp - buffer);
if (!args)
--
2.26.2

View File

@ -1,76 +0,0 @@
From b6e9ddb100e90665d090d7f92cdc69f03f0a6498 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Wed, 18 Nov 2020 00:59:24 +0000
Subject: [PATCH 25/46] kern/parser: Fix a memory leak
The getline() function supplied to grub_parser_split_cmdline() returns
a newly allocated buffer and can be called multiple times, but the
returned buffer is never freed.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/parser.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index d1cf061ad..39e4df65b 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -140,6 +140,7 @@ grub_parser_split_cmdline (const char *cmdline,
char buffer[1024];
char *bp = buffer;
char *rd = (char *) cmdline;
+ char *rp = rd;
char varname[200];
char *vp = varname;
char *args;
@@ -149,10 +150,18 @@ grub_parser_split_cmdline (const char *cmdline,
*argv = NULL;
do
{
- if (!rd || !*rd)
+ if (rp == NULL || *rp == '\0')
{
+ if (rd != cmdline)
+ {
+ grub_free (rd);
+ rd = rp = NULL;
+ }
if (getline)
- getline (&rd, 1, getline_data);
+ {
+ getline (&rd, 1, getline_data);
+ rp = rd;
+ }
else
break;
}
@@ -160,12 +169,12 @@ grub_parser_split_cmdline (const char *cmdline,
if (!rd)
break;
- for (; *rd; rd++)
+ for (; *rp != '\0'; rp++)
{
grub_parser_state_t newstate;
char use;
- newstate = grub_parser_cmdline_state (state, *rd, &use);
+ newstate = grub_parser_cmdline_state (state, *rp, &use);
/* If a variable was being processed and this character does
not describe the variable anymore, write the variable to
@@ -198,6 +207,9 @@ grub_parser_split_cmdline (const char *cmdline,
}
while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
+ if (rd != cmdline)
+ grub_free (rd);
+
/* A special case for when the last character was part of a
variable. */
add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
--
2.26.2

View File

@ -1,119 +0,0 @@
From 80b048e51705c78638afecac539e53e80647f8bd Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Tue, 5 Jan 2021 22:17:28 +0000
Subject: [PATCH 26/46] kern/parser: Introduce process_char() helper
grub_parser_split_cmdline() iterates over each command line character.
In order to add error checking and to simplify the subsequent error
handling, split the character processing in to a separate function.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/parser.c | 74 +++++++++++++++++++++++++----------------
1 file changed, 46 insertions(+), 28 deletions(-)
diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 39e4df65b..0d3582bd8 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -1,7 +1,7 @@
/* parser.c - the part of the parser that can return partial tokens */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2005,2007,2009 Free Software Foundation, Inc.
+ * Copyright (C) 2005,2007,2009,2021 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
@@ -129,6 +129,46 @@ add_var (char *varname, char **bp, char **vp,
*((*bp)++) = *val;
}
+static grub_err_t
+process_char (char c, char *buffer, char **bp, char *varname, char **vp,
+ grub_parser_state_t state, int *argc,
+ grub_parser_state_t *newstate)
+{
+ char use;
+
+ *newstate = grub_parser_cmdline_state (state, c, &use);
+
+ /*
+ * If a variable was being processed and this character does
+ * not describe the variable anymore, write the variable to
+ * the buffer.
+ */
+ add_var (varname, bp, vp, state, *newstate);
+
+ if (check_varstate (*newstate))
+ {
+ if (use)
+ *((*vp)++) = use;
+ }
+ else if (*newstate == GRUB_PARSER_STATE_TEXT &&
+ state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
+ {
+ /*
+ * Don't add more than one argument if multiple
+ * spaces are used.
+ */
+ if (*bp != buffer && *((*bp) - 1) != '\0')
+ {
+ *((*bp)++) = '\0';
+ (*argc)++;
+ }
+ }
+ else if (use)
+ *((*bp)++) = use;
+
+ return GRUB_ERR_NONE;
+}
+
grub_err_t
grub_parser_split_cmdline (const char *cmdline,
grub_reader_getline_t getline, void *getline_data,
@@ -172,35 +212,13 @@ grub_parser_split_cmdline (const char *cmdline,
for (; *rp != '\0'; rp++)
{
grub_parser_state_t newstate;
- char use;
-
- newstate = grub_parser_cmdline_state (state, *rp, &use);
- /* If a variable was being processed and this character does
- not describe the variable anymore, write the variable to
- the buffer. */
- add_var (varname, &bp, &vp, state, newstate);
-
- if (check_varstate (newstate))
- {
- if (use)
- *(vp++) = use;
- }
- else
+ if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
+ &newstate) != GRUB_ERR_NONE)
{
- if (newstate == GRUB_PARSER_STATE_TEXT
- && state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
- {
- /* Don't add more than one argument if multiple
- spaces are used. */
- if (bp != buffer && *(bp - 1))
- {
- *(bp++) = '\0';
- (*argc)++;
- }
- }
- else if (use)
- *(bp++) = use;
+ if (rd != cmdline)
+ grub_free (rd);
+ return grub_errno;
}
state = newstate;
}
--
2.26.2

View File

@ -1,65 +0,0 @@
From b4086b4baa1412fc962b9f88aa5e2a982afee0da Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Thu, 7 Jan 2021 19:53:55 +0000
Subject: [PATCH 27/46] kern/parser: Introduce terminate_arg() helper
process_char() and grub_parser_split_cmdline() use similar code for
terminating the most recent argument. Add a helper function for this.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/parser.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 0d3582bd8..572c67089 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -129,6 +129,16 @@ add_var (char *varname, char **bp, char **vp,
*((*bp)++) = *val;
}
+static void
+terminate_arg (char *buffer, char **bp, int *argc)
+{
+ if (*bp != buffer && *((*bp) - 1) != '\0')
+ {
+ *((*bp)++) = '\0';
+ (*argc)++;
+ }
+}
+
static grub_err_t
process_char (char c, char *buffer, char **bp, char *varname, char **vp,
grub_parser_state_t state, int *argc,
@@ -157,11 +167,7 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
* Don't add more than one argument if multiple
* spaces are used.
*/
- if (*bp != buffer && *((*bp) - 1) != '\0')
- {
- *((*bp)++) = '\0';
- (*argc)++;
- }
+ terminate_arg (buffer, bp, argc);
}
else if (use)
*((*bp)++) = use;
@@ -232,11 +238,8 @@ grub_parser_split_cmdline (const char *cmdline,
variable. */
add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
- if (bp != buffer && *(bp - 1))
- {
- *(bp++) = '\0';
- (*argc)++;
- }
+ /* Ensure that the last argument is terminated. */
+ terminate_arg (buffer, &bp, argc);
/* If there are no args, then we're done. */
if (!*argc)
--
2.26.2

View File

@ -1,92 +0,0 @@
From 550c0e6582b6be09b0af2fb2775a149f51c51bbc Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Wed, 6 Jan 2021 13:54:26 +0000
Subject: [PATCH 28/46] kern/parser: Refactor grub_parser_split_cmdline()
cleanup
Introduce a common function epilogue used for cleaning up on all
return paths, which will simplify additional error handling to be
introduced in a subsequent commit.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/parser.c | 35 ++++++++++++++++++++---------------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index 572c67089..e010eaa1f 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -221,19 +221,13 @@ grub_parser_split_cmdline (const char *cmdline,
if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
&newstate) != GRUB_ERR_NONE)
- {
- if (rd != cmdline)
- grub_free (rd);
- return grub_errno;
- }
+ goto fail;
+
state = newstate;
}
}
while (state != GRUB_PARSER_STATE_TEXT && !check_varstate (state));
- if (rd != cmdline)
- grub_free (rd);
-
/* A special case for when the last character was part of a
variable. */
add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
@@ -243,20 +237,20 @@ grub_parser_split_cmdline (const char *cmdline,
/* If there are no args, then we're done. */
if (!*argc)
- return 0;
+ {
+ grub_errno = GRUB_ERR_NONE;
+ goto out;
+ }
/* Reserve memory for the return values. */
args = grub_malloc (bp - buffer);
if (!args)
- return grub_errno;
+ goto fail;
grub_memcpy (args, buffer, bp - buffer);
*argv = grub_calloc (*argc + 1, sizeof (char *));
if (!*argv)
- {
- grub_free (args);
- return grub_errno;
- }
+ goto fail;
/* The arguments are separated with 0's, setup argv so it points to
the right values. */
@@ -269,7 +263,18 @@ grub_parser_split_cmdline (const char *cmdline,
bp++;
}
- return 0;
+ grub_errno = GRUB_ERR_NONE;
+
+ out:
+ if (rd != cmdline)
+ grub_free (rd);
+
+ return grub_errno;
+
+ fail:
+ grub_free (*argv);
+ grub_free (args);
+ goto out;
}
/* Helper for grub_parser_execute. */
--
2.26.2

View File

@ -1,307 +0,0 @@
From 6fa7584551965d6e444ca1a934839c6538646d0d Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Thu, 7 Jan 2021 15:15:43 +0000
Subject: [PATCH 29/46] kern/buffer: Add variable sized heap buffer
Add a new variable sized heap buffer type (grub_buffer_t) with simple
operations for appending data, accessing the data and maintaining
a read cursor.
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/Makefile.core.def | 1 +
grub-core/kern/buffer.c | 117 +++++++++++++++++++++++++++++
include/grub/buffer.h | 144 ++++++++++++++++++++++++++++++++++++
3 files changed, 262 insertions(+)
create mode 100644 grub-core/kern/buffer.c
create mode 100644 include/grub/buffer.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index a00e7f983..eac42a7b7 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -123,6 +123,7 @@ kernel = {
riscv32_efi_startup = kern/riscv/efi/startup.S;
riscv64_efi_startup = kern/riscv/efi/startup.S;
+ common = kern/buffer.c;
common = kern/command.c;
common = kern/corecmd.c;
common = kern/device.c;
diff --git a/grub-core/kern/buffer.c b/grub-core/kern/buffer.c
new file mode 100644
index 000000000..9f5f8b867
--- /dev/null
+++ b/grub-core/kern/buffer.c
@@ -0,0 +1,117 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2021 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/>.
+ */
+
+#include <grub/buffer.h>
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/safemath.h>
+#include <grub/types.h>
+
+grub_buffer_t
+grub_buffer_new (grub_size_t sz)
+{
+ struct grub_buffer *ret;
+
+ ret = (struct grub_buffer *) grub_malloc (sizeof (*ret));
+ if (ret == NULL)
+ return NULL;
+
+ ret->data = (grub_uint8_t *) grub_malloc (sz);
+ if (ret->data == NULL)
+ {
+ grub_free (ret);
+ return NULL;
+ }
+
+ ret->sz = sz;
+ ret->pos = 0;
+ ret->used = 0;
+
+ return ret;
+}
+
+void
+grub_buffer_free (grub_buffer_t buf)
+{
+ grub_free (buf->data);
+ grub_free (buf);
+}
+
+grub_err_t
+grub_buffer_ensure_space (grub_buffer_t buf, grub_size_t req)
+{
+ grub_uint8_t *d;
+ grub_size_t newsz = 1;
+
+ /* Is the current buffer size adequate? */
+ if (buf->sz >= req)
+ return GRUB_ERR_NONE;
+
+ /* Find the smallest power-of-2 size that satisfies the request. */
+ while (newsz < req)
+ {
+ if (newsz == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("requested buffer size is too large"));
+ newsz <<= 1;
+ }
+
+ d = (grub_uint8_t *) grub_realloc (buf->data, newsz);
+ if (d == NULL)
+ return grub_errno;
+
+ buf->data = d;
+ buf->sz = newsz;
+
+ return GRUB_ERR_NONE;
+}
+
+void *
+grub_buffer_take_data (grub_buffer_t buf)
+{
+ void *data = buf->data;
+
+ buf->data = NULL;
+ buf->sz = buf->pos = buf->used = 0;
+
+ return data;
+}
+
+void
+grub_buffer_reset (grub_buffer_t buf)
+{
+ buf->pos = buf->used = 0;
+}
+
+grub_err_t
+grub_buffer_advance_read_pos (grub_buffer_t buf, grub_size_t n)
+{
+ grub_size_t newpos;
+
+ if (grub_add (buf->pos, n, &newpos))
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+
+ if (newpos > buf->used)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("new read is position beyond the end of the written data"));
+
+ buf->pos = newpos;
+
+ return GRUB_ERR_NONE;
+}
diff --git a/include/grub/buffer.h b/include/grub/buffer.h
new file mode 100644
index 000000000..f4b10cf28
--- /dev/null
+++ b/include/grub/buffer.h
@@ -0,0 +1,144 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2021 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/>.
+ */
+
+#ifndef GRUB_BUFFER_H
+#define GRUB_BUFFER_H 1
+
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/safemath.h>
+#include <grub/types.h>
+
+struct grub_buffer
+{
+ grub_uint8_t *data;
+ grub_size_t sz;
+ grub_size_t pos;
+ grub_size_t used;
+};
+
+/*
+ * grub_buffer_t represents a simple variable sized byte buffer with
+ * read and write cursors. It currently only implements
+ * functionality required by the only user in GRUB (append byte[s],
+ * peeking data at a specified position and updating the read cursor.
+ * Some things that this doesn't do yet are:
+ * - Reading a portion of the buffer by copying data from the current
+ * read position in to a caller supplied destination buffer and then
+ * automatically updating the read cursor.
+ * - Dropping the read part at the start of the buffer when an append
+ * requires more space.
+ */
+typedef struct grub_buffer *grub_buffer_t;
+
+/* Allocate a new buffer with the specified initial size. */
+extern grub_buffer_t grub_buffer_new (grub_size_t sz);
+
+/* Free the buffer and its resources. */
+extern void grub_buffer_free (grub_buffer_t buf);
+
+/* Return the number of unread bytes in this buffer. */
+static inline grub_size_t
+grub_buffer_get_unread_bytes (grub_buffer_t buf)
+{
+ return buf->used - buf->pos;
+}
+
+/*
+ * Ensure that the buffer size is at least the requested
+ * number of bytes.
+ */
+extern grub_err_t grub_buffer_ensure_space (grub_buffer_t buf, grub_size_t req);
+
+/*
+ * Append the specified number of bytes from the supplied
+ * data to the buffer.
+ */
+static inline grub_err_t
+grub_buffer_append_data (grub_buffer_t buf, const void *data, grub_size_t len)
+{
+ grub_size_t req;
+
+ if (grub_add (buf->used, len, &req))
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+
+ if (grub_buffer_ensure_space (buf, req) != GRUB_ERR_NONE)
+ return grub_errno;
+
+ grub_memcpy (&buf->data[buf->used], data, len);
+ buf->used = req;
+
+ return GRUB_ERR_NONE;
+}
+
+/* Append the supplied character to the buffer. */
+static inline grub_err_t
+grub_buffer_append_char (grub_buffer_t buf, char c)
+{
+ return grub_buffer_append_data (buf, &c, 1);
+}
+
+/*
+ * Forget and return the underlying data buffer. The caller
+ * becomes the owner of this buffer, and must free it when it
+ * is no longer required.
+ */
+extern void *grub_buffer_take_data (grub_buffer_t buf);
+
+/* Reset this buffer. Note that this does not deallocate any resources. */
+void grub_buffer_reset (grub_buffer_t buf);
+
+/*
+ * Return a pointer to the underlying data buffer at the specified
+ * offset from the current read position. Note that this pointer may
+ * become invalid if the buffer is mutated further.
+ */
+static inline void *
+grub_buffer_peek_data_at (grub_buffer_t buf, grub_size_t off)
+{
+ if (grub_add (buf->pos, off, &off))
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected."));
+ return NULL;
+ }
+
+ if (off >= buf->used)
+ {
+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("peek out of range"));
+ return NULL;
+ }
+
+ return &buf->data[off];
+}
+
+/*
+ * Return a pointer to the underlying data buffer at the current
+ * read position. Note that this pointer may become invalid if the
+ * buffer is mutated further.
+ */
+static inline void *
+grub_buffer_peek_data (grub_buffer_t buf)
+{
+ return grub_buffer_peek_data_at (buf, 0);
+}
+
+/* Advance the read position by the specified number of bytes. */
+extern grub_err_t grub_buffer_advance_read_pos (grub_buffer_t buf, grub_size_t n);
+
+#endif /* GRUB_BUFFER_H */
--
2.26.2

View File

@ -1,247 +0,0 @@
From e26b56b819c65d251d12175dd82fab4679cfbc87 Mon Sep 17 00:00:00 2001
From: Chris Coulson <chris.coulson@canonical.com>
Date: Thu, 7 Jan 2021 19:21:03 +0000
Subject: [PATCH 30/46] kern/parser: Fix a stack buffer overflow
grub_parser_split_cmdline() expands variable names present in the supplied
command line in to their corresponding variable contents and uses a 1 kiB
stack buffer for temporary storage without sufficient bounds checking. If
the function is called with a command line that references a variable with
a sufficiently large payload, it is possible to overflow the stack
buffer via tab completion, corrupt the stack frame and potentially
control execution.
Fixes: CVE-2020-27749
Reported-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/parser.c | 110 ++++++++++++++++++++++++----------------
1 file changed, 67 insertions(+), 43 deletions(-)
diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c
index e010eaa1f..6ab7aa427 100644
--- a/grub-core/kern/parser.c
+++ b/grub-core/kern/parser.c
@@ -18,6 +18,7 @@
*/
#include <grub/parser.h>
+#include <grub/buffer.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/mm.h>
@@ -107,8 +108,8 @@ check_varstate (grub_parser_state_t s)
}
-static void
-add_var (char *varname, char **bp, char **vp,
+static grub_err_t
+add_var (grub_buffer_t varname, grub_buffer_t buf,
grub_parser_state_t state, grub_parser_state_t newstate)
{
const char *val;
@@ -116,31 +117,41 @@ add_var (char *varname, char **bp, char **vp,
/* Check if a variable was being read in and the end of the name
was reached. */
if (!(check_varstate (state) && !check_varstate (newstate)))
- return;
+ return GRUB_ERR_NONE;
+
+ if (grub_buffer_append_char (varname, '\0') != GRUB_ERR_NONE)
+ return grub_errno;
- *((*vp)++) = '\0';
- val = grub_env_get (varname);
- *vp = varname;
+ val = grub_env_get ((const char *) grub_buffer_peek_data (varname));
+ grub_buffer_reset (varname);
if (!val)
- return;
+ return GRUB_ERR_NONE;
/* Insert the contents of the variable in the buffer. */
- for (; *val; val++)
- *((*bp)++) = *val;
+ return grub_buffer_append_data (buf, val, grub_strlen (val));
}
-static void
-terminate_arg (char *buffer, char **bp, int *argc)
+static grub_err_t
+terminate_arg (grub_buffer_t buffer, int *argc)
{
- if (*bp != buffer && *((*bp) - 1) != '\0')
- {
- *((*bp)++) = '\0';
- (*argc)++;
- }
+ grub_size_t unread = grub_buffer_get_unread_bytes (buffer);
+
+ if (unread == 0)
+ return GRUB_ERR_NONE;
+
+ if (*(const char *) grub_buffer_peek_data_at (buffer, unread - 1) == '\0')
+ return GRUB_ERR_NONE;
+
+ if (grub_buffer_append_char (buffer, '\0') != GRUB_ERR_NONE)
+ return grub_errno;
+
+ (*argc)++;
+
+ return GRUB_ERR_NONE;
}
static grub_err_t
-process_char (char c, char *buffer, char **bp, char *varname, char **vp,
+process_char (char c, grub_buffer_t buffer, grub_buffer_t varname,
grub_parser_state_t state, int *argc,
grub_parser_state_t *newstate)
{
@@ -153,12 +164,13 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
* not describe the variable anymore, write the variable to
* the buffer.
*/
- add_var (varname, bp, vp, state, *newstate);
+ if (add_var (varname, buffer, state, *newstate) != GRUB_ERR_NONE)
+ return grub_errno;
if (check_varstate (*newstate))
{
if (use)
- *((*vp)++) = use;
+ return grub_buffer_append_char (varname, use);
}
else if (*newstate == GRUB_PARSER_STATE_TEXT &&
state != GRUB_PARSER_STATE_ESC && grub_isspace (use))
@@ -167,10 +179,10 @@ process_char (char c, char *buffer, char **bp, char *varname, char **vp,
* Don't add more than one argument if multiple
* spaces are used.
*/
- terminate_arg (buffer, bp, argc);
+ return terminate_arg (buffer, argc);
}
else if (use)
- *((*bp)++) = use;
+ return grub_buffer_append_char (buffer, use);
return GRUB_ERR_NONE;
}
@@ -181,19 +193,22 @@ grub_parser_split_cmdline (const char *cmdline,
int *argc, char ***argv)
{
grub_parser_state_t state = GRUB_PARSER_STATE_TEXT;
- /* XXX: Fixed size buffer, perhaps this buffer should be dynamically
- allocated. */
- char buffer[1024];
- char *bp = buffer;
+ grub_buffer_t buffer, varname;
char *rd = (char *) cmdline;
char *rp = rd;
- char varname[200];
- char *vp = varname;
- char *args;
int i;
*argc = 0;
*argv = NULL;
+
+ buffer = grub_buffer_new (1024);
+ if (buffer == NULL)
+ return grub_errno;
+
+ varname = grub_buffer_new (200);
+ if (varname == NULL)
+ goto fail;
+
do
{
if (rp == NULL || *rp == '\0')
@@ -219,7 +234,7 @@ grub_parser_split_cmdline (const char *cmdline,
{
grub_parser_state_t newstate;
- if (process_char (*rp, buffer, &bp, varname, &vp, state, argc,
+ if (process_char (*rp, buffer, varname, state, argc,
&newstate) != GRUB_ERR_NONE)
goto fail;
@@ -230,10 +245,12 @@ grub_parser_split_cmdline (const char *cmdline,
/* A special case for when the last character was part of a
variable. */
- add_var (varname, &bp, &vp, state, GRUB_PARSER_STATE_TEXT);
+ if (add_var (varname, buffer, state, GRUB_PARSER_STATE_TEXT) != GRUB_ERR_NONE)
+ goto fail;
/* Ensure that the last argument is terminated. */
- terminate_arg (buffer, &bp, argc);
+ if (terminate_arg (buffer, argc) != GRUB_ERR_NONE)
+ goto fail;
/* If there are no args, then we're done. */
if (!*argc)
@@ -242,38 +259,45 @@ grub_parser_split_cmdline (const char *cmdline,
goto out;
}
- /* Reserve memory for the return values. */
- args = grub_malloc (bp - buffer);
- if (!args)
- goto fail;
- grub_memcpy (args, buffer, bp - buffer);
-
*argv = grub_calloc (*argc + 1, sizeof (char *));
if (!*argv)
goto fail;
/* The arguments are separated with 0's, setup argv so it points to
the right values. */
- bp = args;
for (i = 0; i < *argc; i++)
{
- (*argv)[i] = bp;
- while (*bp)
- bp++;
- bp++;
+ char *arg;
+
+ if (i > 0)
+ {
+ if (grub_buffer_advance_read_pos (buffer, 1) != GRUB_ERR_NONE)
+ goto fail;
+ }
+
+ arg = (char *) grub_buffer_peek_data (buffer);
+ if (arg == NULL ||
+ grub_buffer_advance_read_pos (buffer, grub_strlen (arg)) != GRUB_ERR_NONE)
+ goto fail;
+
+ (*argv)[i] = arg;
}
+ /* Keep memory for the return values. */
+ grub_buffer_take_data (buffer);
+
grub_errno = GRUB_ERR_NONE;
out:
if (rd != cmdline)
grub_free (rd);
+ grub_buffer_free (buffer);
+ grub_buffer_free (varname);
return grub_errno;
fail:
grub_free (*argv);
- grub_free (args);
goto out;
}
--
2.26.2

View File

@ -1,60 +0,0 @@
From 88862305f889d23a176c936ff337a8f3ec492efd Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 11 Feb 2021 17:06:49 +0100
Subject: [PATCH 31/46] util/mkimage: Remove unused code to add BSS section
The code is compiled out so there is no reason to keep it.
Additionally, don't set bss_size field since we do not add a BSS section.
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 17 -----------------
1 file changed, 17 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index 37d6249f1..32bb8ea68 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1304,7 +1304,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
o->code_size = grub_host_to_target32 (layout.exec_size);
o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
- header_size);
- o->bss_size = grub_cpu_to_le32 (layout.bss_size);
o->entry_addr = grub_cpu_to_le32 (layout.start_address);
o->code_base = grub_cpu_to_le32 (header_size);
@@ -1342,7 +1341,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
o->code_size = grub_host_to_target32 (layout.exec_size);
o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
- header_size);
- o->bss_size = grub_cpu_to_le32 (layout.bss_size);
o->entry_addr = grub_cpu_to_le32 (layout.start_address);
o->code_base = grub_cpu_to_le32 (header_size);
o->image_base = 0;
@@ -1387,21 +1385,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_READ
| GRUB_PE32_SCN_MEM_WRITE);
-
-#if 0
- bss_section = data_section + 1;
- strcpy (bss_section->name, ".bss");
- bss_section->virtual_size = grub_cpu_to_le32 (layout.bss_size);
- bss_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size);
- bss_section->raw_data_size = 0;
- bss_section->raw_data_offset = 0;
- bss_section->characteristics
- = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_MEM_READ
- | GRUB_PE32_SCN_MEM_WRITE
- | GRUB_PE32_SCN_ALIGN_64BYTES
- | GRUB_PE32_SCN_CNT_INITIALIZED_DATA
- | 0x80);
-#endif
mods_section = data_section + 1;
strcpy (mods_section->name, "mods");
--
2.26.2

View File

@ -1,112 +0,0 @@
From 6e003a43373e87683f3c5b783cdc8e423e1a6bc3 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 15 Feb 2021 13:59:21 +0100
Subject: [PATCH 32/46] util/mkimage: Use grub_host_to_target32() instead of
grub_cpu_to_le32()
The latter doesn't take into account the target image endianness. There is
a grub_cpu_to_le32_compile_time() but no compile time variant for function
grub_host_to_target32(). So, let's keep using the other one for this case.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 44 ++++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index 32bb8ea68..02944f28e 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1302,10 +1302,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ sizeof (struct grub_pe32_coff_header));
o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
o->code_size = grub_host_to_target32 (layout.exec_size);
- o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
+ o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
- header_size);
- o->entry_addr = grub_cpu_to_le32 (layout.start_address);
- o->code_base = grub_cpu_to_le32 (header_size);
+ o->entry_addr = grub_host_to_target32 (layout.start_address);
+ o->code_base = grub_host_to_target32 (header_size);
o->data_base = grub_host_to_target32 (header_size + layout.exec_size);
@@ -1339,10 +1339,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ sizeof (struct grub_pe32_coff_header));
o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
o->code_size = grub_host_to_target32 (layout.exec_size);
- o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
+ o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
- header_size);
- o->entry_addr = grub_cpu_to_le32 (layout.start_address);
- o->code_base = grub_cpu_to_le32 (header_size);
+ o->entry_addr = grub_host_to_target32 (layout.start_address);
+ o->code_base = grub_host_to_target32 (header_size);
o->image_base = 0;
o->section_alignment = grub_host_to_target32 (image_target->section_align);
o->file_alignment = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
@@ -1366,10 +1366,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
/* The sections. */
text_section = sections;
strcpy (text_section->name, ".text");
- text_section->virtual_size = grub_cpu_to_le32 (layout.exec_size);
- text_section->virtual_address = grub_cpu_to_le32 (header_size);
- text_section->raw_data_size = grub_cpu_to_le32 (layout.exec_size);
- text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
+ text_section->virtual_size = grub_host_to_target32 (layout.exec_size);
+ text_section->virtual_address = grub_host_to_target32 (header_size);
+ text_section->raw_data_size = grub_host_to_target32 (layout.exec_size);
+ text_section->raw_data_offset = grub_host_to_target32 (header_size);
text_section->characteristics = grub_cpu_to_le32_compile_time (
GRUB_PE32_SCN_CNT_CODE
| GRUB_PE32_SCN_MEM_EXECUTE
@@ -1377,10 +1377,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
data_section = text_section + 1;
strcpy (data_section->name, ".data");
- data_section->virtual_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
- data_section->virtual_address = grub_cpu_to_le32 (header_size + layout.exec_size);
- data_section->raw_data_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
- data_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.exec_size);
+ data_section->virtual_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
+ data_section->virtual_address = grub_host_to_target32 (header_size + layout.exec_size);
+ data_section->raw_data_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
+ data_section->raw_data_offset = grub_host_to_target32 (header_size + layout.exec_size);
data_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_READ
@@ -1388,10 +1388,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
mods_section = data_section + 1;
strcpy (mods_section->name, "mods");
- mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
- mods_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size + layout.bss_size);
- mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
- mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.kernel_size);
+ mods_section->virtual_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
+ mods_section->virtual_address = grub_host_to_target32 (header_size + layout.kernel_size + layout.bss_size);
+ mods_section->raw_data_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
+ mods_section->raw_data_offset = grub_host_to_target32 (header_size + layout.kernel_size);
mods_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_READ
@@ -1399,10 +1399,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
reloc_section = mods_section + 1;
strcpy (reloc_section->name, ".reloc");
- reloc_section->virtual_size = grub_cpu_to_le32 (layout.reloc_size);
- reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + layout.bss_size);
- reloc_section->raw_data_size = grub_cpu_to_le32 (layout.reloc_size);
- reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
+ reloc_section->virtual_size = grub_host_to_target32 (layout.reloc_size);
+ reloc_section->virtual_address = grub_host_to_target32 (reloc_addr + layout.bss_size);
+ reloc_section->raw_data_size = grub_host_to_target32 (layout.reloc_size);
+ reloc_section->raw_data_offset = grub_host_to_target32 (reloc_addr);
reloc_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_DISCARDABLE
--
2.26.2

View File

@ -1,38 +0,0 @@
From 4bf74d11396e0adde218a3129599f145459852f3 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 15 Feb 2021 14:14:24 +0100
Subject: [PATCH 33/46] util/mkimage: Always use grub_host_to_target32() to
initialize PE stack and heap stuff
This change does not impact final result of initialization itself.
However, it eases PE code unification in subsequent patches.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index 02944f28e..b94bfb781 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1351,10 +1351,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
/* Do these really matter? */
- o->stack_reserve_size = grub_host_to_target64 (0x10000);
- o->stack_commit_size = grub_host_to_target64 (0x10000);
- o->heap_reserve_size = grub_host_to_target64 (0x10000);
- o->heap_commit_size = grub_host_to_target64 (0x10000);
+ o->stack_reserve_size = grub_host_to_target32 (0x10000);
+ o->stack_commit_size = grub_host_to_target32 (0x10000);
+ o->heap_reserve_size = grub_host_to_target32 (0x10000);
+ o->heap_commit_size = grub_host_to_target32 (0x10000);
o->num_data_directories
= grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
--
2.26.2

View File

@ -1,169 +0,0 @@
From 17db90317938d492561af63f0cc7356c6dadb46a Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 15 Feb 2021 14:19:31 +0100
Subject: [PATCH 34/46] util/mkimage: Unify more of the PE32 and PE32+ header
set-up
There's quite a bit of code duplication in the code that sets the optional
header for PE32 and PE32+. The two are very similar with the exception of
a few fields that have type grub_uint64_t instead of grub_uint32_t.
Factor out the common code and add a PE_OHDR() macro that simplifies the
set-up and make the code more readable.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 111 +++++++++++++++++++++++--------------------------
1 file changed, 51 insertions(+), 60 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index b94bfb781..a039039db 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -816,6 +816,21 @@ grub_install_get_image_targets_string (void)
return formats;
}
+/*
+ * tmp_ is just here so the compiler knows we'll never derefernce a NULL.
+ * It should get fully optimized away.
+ */
+#define PE_OHDR(o32, o64, field) (*( \
+{ \
+ __typeof__((o64)->field) tmp_; \
+ __typeof__((o64)->field) *ret_ = &tmp_; \
+ if (o32) \
+ ret_ = (void *)(&((o32)->field)); \
+ else if (o64) \
+ ret_ = (void *)(&((o64)->field)); \
+ ret_; \
+}))
+
void
grub_install_generate_image (const char *dir, const char *prefix,
FILE *out, const char *outname, char *mods[],
@@ -1252,6 +1267,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
int header_size;
int reloc_addr;
+ struct grub_pe32_optional_header *o32 = NULL;
+ struct grub_pe64_optional_header *o64 = NULL;
if (image_target->voidp_sizeof == 4)
header_size = EFI32_HEADER_SIZE;
@@ -1293,76 +1310,50 @@ grub_install_generate_image (const char *dir, const char *prefix,
/* The PE Optional header. */
if (image_target->voidp_sizeof == 4)
{
- struct grub_pe32_optional_header *o;
-
c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe32_optional_header));
- o = (struct grub_pe32_optional_header *)
- (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
- + sizeof (struct grub_pe32_coff_header));
- o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
- o->code_size = grub_host_to_target32 (layout.exec_size);
- o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
- - header_size);
- o->entry_addr = grub_host_to_target32 (layout.start_address);
- o->code_base = grub_host_to_target32 (header_size);
-
- o->data_base = grub_host_to_target32 (header_size + layout.exec_size);
-
- o->image_base = 0;
- o->section_alignment = grub_host_to_target32 (image_target->section_align);
- o->file_alignment = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
- o->image_size = grub_host_to_target32 (pe_size);
- o->header_size = grub_host_to_target32 (header_size);
- o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
-
- /* Do these really matter? */
- o->stack_reserve_size = grub_host_to_target32 (0x10000);
- o->stack_commit_size = grub_host_to_target32 (0x10000);
- o->heap_reserve_size = grub_host_to_target32 (0x10000);
- o->heap_commit_size = grub_host_to_target32 (0x10000);
-
- o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
+ o32 = (struct grub_pe32_optional_header *)
+ (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE +
+ sizeof (struct grub_pe32_coff_header));
+ o32->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
+ o32->data_base = grub_host_to_target32 (header_size + layout.exec_size);
- o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
- o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
- sections = o + 1;
+ sections = o32 + 1;
}
else
{
- struct grub_pe64_optional_header *o;
-
c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
- o = (struct grub_pe64_optional_header *)
- (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
- + sizeof (struct grub_pe32_coff_header));
- o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
- o->code_size = grub_host_to_target32 (layout.exec_size);
- o->data_size = grub_host_to_target32 (reloc_addr - layout.exec_size
- - header_size);
- o->entry_addr = grub_host_to_target32 (layout.start_address);
- o->code_base = grub_host_to_target32 (header_size);
- o->image_base = 0;
- o->section_alignment = grub_host_to_target32 (image_target->section_align);
- o->file_alignment = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
- o->image_size = grub_host_to_target32 (pe_size);
- o->header_size = grub_host_to_target32 (header_size);
- o->subsystem = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
-
- /* Do these really matter? */
- o->stack_reserve_size = grub_host_to_target32 (0x10000);
- o->stack_commit_size = grub_host_to_target32 (0x10000);
- o->heap_reserve_size = grub_host_to_target32 (0x10000);
- o->heap_commit_size = grub_host_to_target32 (0x10000);
-
- o->num_data_directories
- = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
+ o64 = (struct grub_pe64_optional_header *)
+ (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE +
+ sizeof (struct grub_pe32_coff_header));
+ o64->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
- o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
- o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
- sections = o + 1;
+ sections = o64 + 1;
}
+
+ PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+ PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address);
+ PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
+
+ PE_OHDR (o32, o64, image_base) = 0;
+ PE_OHDR (o32, o64, section_alignment) = grub_host_to_target32 (image_target->section_align);
+ PE_OHDR (o32, o64, file_alignment) = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
+ PE_OHDR (o32, o64, image_size) = grub_host_to_target32 (pe_size);
+ PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
+ PE_OHDR (o32, o64, subsystem) = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
+
+ /* Do these really matter? */
+ PE_OHDR (o32, o64, stack_reserve_size) = grub_host_to_target32 (0x10000);
+ PE_OHDR (o32, o64, stack_commit_size) = grub_host_to_target32 (0x10000);
+ PE_OHDR (o32, o64, heap_reserve_size) = grub_host_to_target32 (0x10000);
+ PE_OHDR (o32, o64, heap_commit_size) = grub_host_to_target32 (0x10000);
+
+ PE_OHDR (o32, o64, num_data_directories) = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
+ PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
+ PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
+
/* The sections. */
text_section = sections;
strcpy (text_section->name, ".text");
--
2.26.2

View File

@ -1,72 +0,0 @@
From fbacfa8211adbd1acaf264f7b1292781121a7195 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 15 Feb 2021 14:21:48 +0100
Subject: [PATCH 35/46] util/mkimage: Reorder PE optional header fields set-up
This makes the PE32 and PE32+ header fields set-up easier to follow by
setting them closer to the initialization of their related sections.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index a039039db..deaef5666 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1332,16 +1332,12 @@ grub_install_generate_image (const char *dir, const char *prefix,
sections = o64 + 1;
}
- PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
- PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+ PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
PE_OHDR (o32, o64, entry_addr) = grub_host_to_target32 (layout.start_address);
- PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
-
PE_OHDR (o32, o64, image_base) = 0;
+ PE_OHDR (o32, o64, image_size) = grub_host_to_target32 (pe_size);
PE_OHDR (o32, o64, section_alignment) = grub_host_to_target32 (image_target->section_align);
PE_OHDR (o32, o64, file_alignment) = grub_host_to_target32 (GRUB_PE32_FILE_ALIGNMENT);
- PE_OHDR (o32, o64, image_size) = grub_host_to_target32 (pe_size);
- PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
PE_OHDR (o32, o64, subsystem) = grub_host_to_target16 (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION);
/* Do these really matter? */
@@ -1351,10 +1347,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
PE_OHDR (o32, o64, heap_commit_size) = grub_host_to_target32 (0x10000);
PE_OHDR (o32, o64, num_data_directories) = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
- PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
- PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
/* The sections. */
+ PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
+ PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
text_section = sections;
strcpy (text_section->name, ".text");
text_section->virtual_size = grub_host_to_target32 (layout.exec_size);
@@ -1366,6 +1362,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
| GRUB_PE32_SCN_MEM_EXECUTE
| GRUB_PE32_SCN_MEM_READ);
+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+
data_section = text_section + 1;
strcpy (data_section->name, ".data");
data_section->virtual_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
@@ -1388,6 +1386,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
| GRUB_PE32_SCN_MEM_READ
| GRUB_PE32_SCN_MEM_WRITE);
+ PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
+ PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
reloc_section = mods_section + 1;
strcpy (reloc_section->name, ".reloc");
reloc_section->virtual_size = grub_host_to_target32 (layout.reloc_size);
--
2.26.2

View File

@ -1,49 +0,0 @@
From 805d58de7a06687572fba8f8d0f4110204246f2d Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 11 Feb 2021 17:07:33 +0100
Subject: [PATCH 36/46] util/mkimage: Improve data_size value calculation
According to "Microsoft Portable Executable and Common Object File Format
Specification", the Optional Header SizeOfInitializedData field contains:
Size of the initialized data section, or the sum of all such sections if
there are multiple data sections.
Make this explicit by adding the GRUB kernel data size to the sum of all
the modules sizes. The ALIGN_UP() is not required by the PE spec but do
it to avoid alignment issues.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index deaef5666..853a52179 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -1260,6 +1260,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
void *pe_img;
grub_uint8_t *header;
void *sections;
+ size_t scn_size;
size_t pe_size;
struct grub_pe32_coff_header *c;
struct grub_pe32_section_table *text_section, *data_section;
@@ -1362,7 +1363,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
| GRUB_PE32_SCN_MEM_EXECUTE
| GRUB_PE32_SCN_MEM_READ);
- PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (reloc_addr - layout.exec_size - header_size);
+ scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size +
+ ALIGN_UP (total_module_size,
+ GRUB_PE32_FILE_ALIGNMENT));
data_section = text_section + 1;
strcpy (data_section->name, ".data");
--
2.26.2

View File

@ -1,220 +0,0 @@
From aa25aa5d9ce91e862cc951225c5aabc78c4d4366 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 15 Feb 2021 14:58:06 +0100
Subject: [PATCH 37/46] util/mkimage: Refactor section setup to use a helper
Add a init_pe_section() helper function to setup PE sections. This makes
the code simpler and easier to read.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
util/mkimage.c | 143 ++++++++++++++++++++++++++-----------------------
1 file changed, 77 insertions(+), 66 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index 853a52179..8b475a691 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -816,6 +816,38 @@ grub_install_get_image_targets_string (void)
return formats;
}
+/*
+ * The image_target parameter is used by the grub_host_to_target32() macro.
+ */
+static struct grub_pe32_section_table *
+init_pe_section(const struct grub_install_image_target_desc *image_target,
+ struct grub_pe32_section_table *section,
+ const char * const name,
+ grub_uint32_t *vma, grub_uint32_t vsz, grub_uint32_t valign,
+ grub_uint32_t *rda, grub_uint32_t rsz,
+ grub_uint32_t characteristics)
+{
+ size_t len = strlen (name);
+
+ if (len > sizeof (section->name))
+ grub_util_error (_("section name %s length is bigger than %lu"),
+ name, (unsigned long) sizeof (section->name));
+
+ memcpy (section->name, name, len);
+
+ section->virtual_address = grub_host_to_target32 (*vma);
+ section->virtual_size = grub_host_to_target32 (vsz);
+ (*vma) = ALIGN_UP (*vma + vsz, valign);
+
+ section->raw_data_offset = grub_host_to_target32 (*rda);
+ section->raw_data_size = grub_host_to_target32 (rsz);
+ (*rda) = ALIGN_UP (*rda + rsz, GRUB_PE32_FILE_ALIGNMENT);
+
+ section->characteristics = grub_host_to_target32 (characteristics);
+
+ return section + 1;
+}
+
/*
* tmp_ is just here so the compiler knows we'll never derefernce a NULL.
* It should get fully optimized away.
@@ -1257,17 +1289,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
break;
case IMAGE_EFI:
{
- void *pe_img;
- grub_uint8_t *header;
- void *sections;
+ char *pe_img, *header;
+ struct grub_pe32_section_table *section;
size_t scn_size;
- size_t pe_size;
+ grub_uint32_t vma, raw_data;
+ size_t pe_size, header_size;
struct grub_pe32_coff_header *c;
- struct grub_pe32_section_table *text_section, *data_section;
- struct grub_pe32_section_table *mods_section, *reloc_section;
static const grub_uint8_t stub[] = GRUB_PE32_MSDOS_STUB;
- int header_size;
- int reloc_addr;
struct grub_pe32_optional_header *o32 = NULL;
struct grub_pe64_optional_header *o64 = NULL;
@@ -1276,17 +1304,12 @@ grub_install_generate_image (const char *dir, const char *prefix,
else
header_size = EFI64_HEADER_SIZE;
- reloc_addr = ALIGN_UP (header_size + core_size,
- GRUB_PE32_FILE_ALIGNMENT);
+ vma = raw_data = header_size;
+ pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) +
+ ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT);
+ header = pe_img = xcalloc (1, pe_size);
- pe_size = ALIGN_UP (reloc_addr + layout.reloc_size,
- GRUB_PE32_FILE_ALIGNMENT);
- pe_img = xmalloc (reloc_addr + layout.reloc_size);
- memset (pe_img, 0, header_size);
- memcpy ((char *) pe_img + header_size, core_img, core_size);
- memset ((char *) pe_img + header_size + core_size, 0, reloc_addr - (header_size + core_size));
- memcpy ((char *) pe_img + reloc_addr, layout.reloc_section, layout.reloc_size);
- header = pe_img;
+ memcpy (pe_img + raw_data, core_img, core_size);
/* The magic. */
memcpy (header, stub, GRUB_PE32_MSDOS_STUB_SIZE);
@@ -1319,18 +1342,17 @@ grub_install_generate_image (const char *dir, const char *prefix,
o32->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
o32->data_base = grub_host_to_target32 (header_size + layout.exec_size);
- sections = o32 + 1;
+ section = (struct grub_pe32_section_table *)(o32 + 1);
}
else
{
c->optional_header_size = grub_host_to_target16 (sizeof (struct grub_pe64_optional_header));
-
o64 = (struct grub_pe64_optional_header *)
(header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE +
sizeof (struct grub_pe32_coff_header));
o64->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
- sections = o64 + 1;
+ section = (struct grub_pe32_section_table *)(o64 + 1);
}
PE_OHDR (o32, o64, header_size) = grub_host_to_target32 (header_size);
@@ -1350,58 +1372,47 @@ grub_install_generate_image (const char *dir, const char *prefix,
PE_OHDR (o32, o64, num_data_directories) = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
/* The sections. */
- PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (header_size);
+ PE_OHDR (o32, o64, code_base) = grub_host_to_target32 (vma);
PE_OHDR (o32, o64, code_size) = grub_host_to_target32 (layout.exec_size);
- text_section = sections;
- strcpy (text_section->name, ".text");
- text_section->virtual_size = grub_host_to_target32 (layout.exec_size);
- text_section->virtual_address = grub_host_to_target32 (header_size);
- text_section->raw_data_size = grub_host_to_target32 (layout.exec_size);
- text_section->raw_data_offset = grub_host_to_target32 (header_size);
- text_section->characteristics = grub_cpu_to_le32_compile_time (
- GRUB_PE32_SCN_CNT_CODE
- | GRUB_PE32_SCN_MEM_EXECUTE
- | GRUB_PE32_SCN_MEM_READ);
+ section = init_pe_section (image_target, section, ".text",
+ &vma, layout.exec_size,
+ image_target->section_align,
+ &raw_data, layout.exec_size,
+ GRUB_PE32_SCN_CNT_CODE |
+ GRUB_PE32_SCN_MEM_EXECUTE |
+ GRUB_PE32_SCN_MEM_READ);
scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size +
ALIGN_UP (total_module_size,
GRUB_PE32_FILE_ALIGNMENT));
- data_section = text_section + 1;
- strcpy (data_section->name, ".data");
- data_section->virtual_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
- data_section->virtual_address = grub_host_to_target32 (header_size + layout.exec_size);
- data_section->raw_data_size = grub_host_to_target32 (layout.kernel_size - layout.exec_size);
- data_section->raw_data_offset = grub_host_to_target32 (header_size + layout.exec_size);
- data_section->characteristics
- = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
- | GRUB_PE32_SCN_MEM_READ
- | GRUB_PE32_SCN_MEM_WRITE);
-
- mods_section = data_section + 1;
- strcpy (mods_section->name, "mods");
- mods_section->virtual_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
- mods_section->virtual_address = grub_host_to_target32 (header_size + layout.kernel_size + layout.bss_size);
- mods_section->raw_data_size = grub_host_to_target32 (reloc_addr - layout.kernel_size - header_size);
- mods_section->raw_data_offset = grub_host_to_target32 (header_size + layout.kernel_size);
- mods_section->characteristics
- = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
- | GRUB_PE32_SCN_MEM_READ
- | GRUB_PE32_SCN_MEM_WRITE);
-
- PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (reloc_addr);
- PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (layout.reloc_size);
- reloc_section = mods_section + 1;
- strcpy (reloc_section->name, ".reloc");
- reloc_section->virtual_size = grub_host_to_target32 (layout.reloc_size);
- reloc_section->virtual_address = grub_host_to_target32 (reloc_addr + layout.bss_size);
- reloc_section->raw_data_size = grub_host_to_target32 (layout.reloc_size);
- reloc_section->raw_data_offset = grub_host_to_target32 (reloc_addr);
- reloc_section->characteristics
- = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
- | GRUB_PE32_SCN_MEM_DISCARDABLE
- | GRUB_PE32_SCN_MEM_READ);
+ section = init_pe_section (image_target, section, ".data",
+ &vma, scn_size, image_target->section_align,
+ &raw_data, scn_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_READ |
+ GRUB_PE32_SCN_MEM_WRITE);
+
+ scn_size = pe_size - layout.reloc_size - raw_data;
+ section = init_pe_section (image_target, section, "mods",
+ &vma, scn_size, image_target->section_align,
+ &raw_data, scn_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_READ |
+ GRUB_PE32_SCN_MEM_WRITE);
+
+ scn_size = layout.reloc_size;
+ PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma);
+ PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size);
+ memcpy (pe_img + raw_data, layout.reloc_section, scn_size);
+ init_pe_section (image_target, section, ".reloc",
+ &vma, scn_size, image_target->section_align,
+ &raw_data, scn_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_DISCARDABLE |
+ GRUB_PE32_SCN_MEM_READ);
+
free (core_img);
core_img = pe_img;
core_size = pe_size;
--
2.26.2

View File

@ -1,263 +0,0 @@
From c128817e4493836b9877e573820782036dea2163 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 15 Feb 2021 17:07:00 +0100
Subject: [PATCH 38/46] util/mkimage: Add an option to import SBAT metadata
into a .sbat section
Add a --sbat option to the grub-mkimage tool which allows us to import
an SBAT metadata formatted as a CSV file into a .sbat section of the
EFI binary.
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 19 ++++++++++++++++
include/grub/util/install.h | 3 ++-
include/grub/util/mkimage.h | 1 +
util/grub-install-common.c | 2 +-
util/grub-mkimage.c | 15 ++++++++++++-
util/mkimage.c | 43 +++++++++++++++++++++++++++++++------
6 files changed, 73 insertions(+), 10 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index cf29a1797..fa0b49737 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5612,6 +5612,7 @@ environment variables and commands are listed in the same order.
* Authentication and authorisation:: Users and access control
* Using digital signatures:: Booting digitally signed code
* UEFI secure boot and shim:: Booting digitally signed PE files
+* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation
* Measured Boot:: Measuring boot components
* Lockdown:: Lockdown when booting on a secure setup
@end menu
@@ -5791,6 +5792,24 @@ and @command{memrw} will not be available when the UEFI secure boot is enabled.
This is done for security reasons and are enforced by the GRUB Lockdown mechanism
(@pxref{Lockdown}).
+@node Secure Boot Advanced Targeting
+@section Embedded information for generation number based revocation
+
+The Secure Boot Advanced Targeting (SBAT) is a mechanism to allow the revocation
+of components in the boot path by using generation numbers embedded into the EFI
+binaries. The SBAT metadata is located in an .sbat data section that has set of
+UTF-8 strings as comma-separated values (CSV). See
+@uref{https://github.com/rhboot/shim/blob/main/SBAT.md} for more details.
+
+To add a data section containing the SBAT information into the binary, the
+@option{--sbat} option of @command{grub-mkimage} command should be used. The content
+of a CSV file, encoded with UTF-8, is copied as is to the .sbat data section into
+the generated EFI binary. The CSV file can be stored anywhere on the file system.
+
+@example
+grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efinet tftp
+@end example
+
@node Measured Boot
@section Measuring boot components
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 1541ee233..6ee3b4516 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -184,7 +184,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
char *config_path,
const struct grub_install_image_target_desc *image_target,
int note,
- grub_compression_t comp, const char *dtb_file);
+ grub_compression_t comp, const char *dtb_file,
+ const char *sbat_path);
const struct grub_install_image_target_desc *
grub_install_get_image_target (const char *arg);
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index ba9f568f6..3819a6744 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -24,6 +24,7 @@ struct grub_mkimage_layout
size_t exec_size;
size_t kernel_size;
size_t bss_size;
+ size_t sbat_size;
grub_uint64_t start_address;
void *reloc_section;
size_t reloc_size;
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index d1894f7c1..052f3ef3d 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -546,7 +546,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
grub_install_generate_image (dir, prefix, fp, outname,
modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt,
- note, compression, dtb);
+ note, compression, dtb, NULL);
while (dc--)
grub_install_pop_module ();
}
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index 912564e36..75b884710 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -81,6 +81,7 @@ static struct argp_option options[] = {
{"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0},
{"format", 'O', N_("FORMAT"), 0, 0, 0},
{"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
+ {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
{ 0, 0, 0, 0, 0, 0 }
};
@@ -123,6 +124,7 @@ struct arguments
size_t npubkeys;
char *font;
char *config;
+ char *sbat;
int note;
const struct grub_install_image_target_desc *image_target;
grub_compression_t comp;
@@ -224,6 +226,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
arguments->prefix = xstrdup (arg);
break;
+ case 's':
+ if (arguments->sbat)
+ free (arguments->sbat);
+
+ arguments->sbat = xstrdup (arg);
+ break;
+
case 'v':
verbosity++;
break;
@@ -309,7 +318,8 @@ main (int argc, char *argv[])
arguments.memdisk, arguments.pubkeys,
arguments.npubkeys, arguments.config,
arguments.image_target, arguments.note,
- arguments.comp, arguments.dtb);
+ arguments.comp, arguments.dtb,
+ arguments.sbat);
if (grub_util_file_sync (fp) < 0)
grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
@@ -328,5 +338,8 @@ main (int argc, char *argv[])
if (arguments.output)
free (arguments.output);
+ if (arguments.sbat)
+ free (arguments.sbat);
+
return 0;
}
diff --git a/util/mkimage.c b/util/mkimage.c
index 8b475a691..b354ec1d9 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -869,12 +869,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
char *memdisk_path, char **pubkey_paths,
size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc *image_target,
- int note, grub_compression_t comp, const char *dtb_path)
+ int note, grub_compression_t comp, const char *dtb_path,
+ const char *sbat_path)
{
char *kernel_img, *core_img;
size_t total_module_size, core_size;
size_t memdisk_size = 0, config_size = 0;
- size_t prefix_size = 0, dtb_size = 0;
+ size_t prefix_size = 0, dtb_size = 0, sbat_size = 0;
char *kernel_path;
size_t offset;
struct grub_util_path_list *path_list, *p;
@@ -925,6 +926,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
total_module_size += dtb_size + sizeof (struct grub_module_header);
}
+ if (sbat_path != NULL && image_target->id != IMAGE_EFI)
+ grub_util_error (_(".sbat section can be embedded into EFI images only"));
+
if (config_path)
{
config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@@ -1289,8 +1293,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
break;
case IMAGE_EFI:
{
- char *pe_img, *header;
+ char *pe_img, *pe_sbat, *header;
struct grub_pe32_section_table *section;
+ size_t n_sections = 4;
size_t scn_size;
grub_uint32_t vma, raw_data;
size_t pe_size, header_size;
@@ -1305,8 +1310,15 @@ grub_install_generate_image (const char *dir, const char *prefix,
header_size = EFI64_HEADER_SIZE;
vma = raw_data = header_size;
+
+ if (sbat_path != NULL)
+ {
+ sbat_size = ALIGN_ADDR (grub_util_get_image_size (sbat_path));
+ sbat_size = ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT);
+ }
+
pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) +
- ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT);
+ ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT) + sbat_size;
header = pe_img = xcalloc (1, pe_size);
memcpy (pe_img + raw_data, core_img, core_size);
@@ -1321,7 +1333,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ GRUB_PE32_SIGNATURE_SIZE);
c->machine = grub_host_to_target16 (image_target->pe_target);
- c->num_sections = grub_host_to_target16 (4);
+ if (sbat_path != NULL)
+ n_sections++;
+
+ c->num_sections = grub_host_to_target16 (n_sections);
c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP);
c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE
| GRUB_PE32_LINE_NUMS_STRIPPED
@@ -1383,7 +1398,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
GRUB_PE32_SCN_MEM_READ);
scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
- PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size +
+ /* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */
+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size +
ALIGN_UP (total_module_size,
GRUB_PE32_FILE_ALIGNMENT));
@@ -1394,7 +1410,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
GRUB_PE32_SCN_MEM_READ |
GRUB_PE32_SCN_MEM_WRITE);
- scn_size = pe_size - layout.reloc_size - raw_data;
+ scn_size = pe_size - layout.reloc_size - sbat_size - raw_data;
section = init_pe_section (image_target, section, "mods",
&vma, scn_size, image_target->section_align,
&raw_data, scn_size,
@@ -1402,6 +1418,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
GRUB_PE32_SCN_MEM_READ |
GRUB_PE32_SCN_MEM_WRITE);
+ if (sbat_path != NULL)
+ {
+ pe_sbat = pe_img + raw_data;
+ grub_util_load_image (sbat_path, pe_sbat);
+
+ section = init_pe_section (image_target, section, ".sbat",
+ &vma, sbat_size,
+ image_target->section_align,
+ &raw_data, sbat_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_READ);
+ }
+
scn_size = layout.reloc_size;
PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma);
PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size);
--
2.26.2

View File

@ -1,84 +0,0 @@
From 427bbc05c7fe8c01872cdba3d1d59d27fc1b9e5b Mon Sep 17 00:00:00 2001
From: Dimitri John Ledkov <xnox@ubuntu.com>
Date: Mon, 22 Feb 2021 17:05:25 +0000
Subject: [PATCH 39/46] grub-install-common: Add --sbat option
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
include/grub/util/install.h | 5 ++++-
util/grub-install-common.c | 12 ++++++++++--
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 6ee3b4516..2207b54d7 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -63,6 +63,8 @@
/* TRANSLATORS: "embed" is a verb (command description). "*/ \
{ "pubkey", 'k', N_("FILE"), 0, \
N_("embed FILE as public key for signature checking"), 0}, \
+ { "sbat", GRUB_INSTALL_OPTIONS_SBAT, N_("FILE"), 0, \
+ N_("SBAT metadata"), 0 }, \
{ "verbose", 'v', 0, 0, \
N_("print verbose messages."), 1 }
@@ -123,7 +125,8 @@ enum grub_install_options {
GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY,
GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
- GRUB_INSTALL_OPTIONS_DTB
+ GRUB_INSTALL_OPTIONS_DTB,
+ GRUB_INSTALL_OPTIONS_SBAT
};
extern char *grub_install_source_directory;
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 052f3ef3d..4efee002f 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -342,6 +342,7 @@ handle_install_list (struct install_list *il, const char *val,
static char **pubkeys;
static size_t npubkeys;
+static char *sbat;
static grub_compression_t compression;
int
@@ -372,6 +373,12 @@ grub_install_parse (int key, char *arg)
* (npubkeys + 1));
pubkeys[npubkeys++] = xstrdup (arg);
return 1;
+ case GRUB_INSTALL_OPTIONS_SBAT:
+ if (sbat)
+ free (sbat);
+
+ sbat = xstrdup (arg);
+ return 1;
case GRUB_INSTALL_OPTIONS_VERBOSITY:
verbosity++;
@@ -533,9 +540,10 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'"
" --output '%s' "
" --dtb '%s' "
+ "--sbat '%s' "
"--format '%s' --compression '%s' %s %s\n",
dir, prefix,
- outname, dtb ? : "", mkimage_target,
+ outname, dtb ? : "", sbat ? : "", mkimage_target,
compnames[compression], note ? "--note" : "", s);
free (s);
@@ -546,7 +554,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
grub_install_generate_image (dir, prefix, fp, outname,
modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt,
- note, compression, dtb, NULL);
+ note, compression, dtb, sbat);
while (dc--)
grub_install_pop_module ();
}
--
2.26.2

View File

@ -1,268 +0,0 @@
From d9f12b9f37280aa54e8ef4b8c2a2163721d28360 Mon Sep 17 00:00:00 2001
From: Dimitri John Ledkov <xnox@ubuntu.com>
Date: Sat, 20 Feb 2021 17:10:34 +0000
Subject: [PATCH 40/46] shim_lock: Only skip loading shim_lock verifier with
explicit consent
Commit 32ddc42c (efi: Only register shim_lock verifier if shim_lock
protocol is found and SB enabled) reintroduced CVE-2020-15705 which
previously only existed in the out-of-tree linuxefi patches and was
fixed as part of the BootHole patch series.
Under Secure Boot enforce loading shim_lock verifier. Allow skipping
shim_lock verifier if SecureBoot/MokSBState EFI variables indicate
skipping validations, or if GRUB image is built with --disable-shim-lock.
Fixes: 132ddc42c (efi: Only register shim_lock verifier if shim_lock
protocol is found and SB enabled)
Fixes: CVE-2020-15705
Reported-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Dimitri John Ledkov <xnox@ubuntu.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 5 ++++-
grub-core/kern/efi/sb.c | 17 ++++++++++++++++-
include/grub/kernel.h | 3 ++-
include/grub/util/install.h | 7 +++++--
util/grub-install-common.c | 12 +++++++++---
util/grub-mkimage.c | 8 +++++++-
util/mkimage.c | 15 ++++++++++++++-
7 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index fa0b49737..b82f32382 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5783,7 +5783,10 @@ secure boot chain.
The GRUB, except the @command{chainloader} command, works with the UEFI secure
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.
+enabled. The @samp{shim_lock} variable is set to @samp{y} when shim_lock verifier
+is registered. If it is desired to use UEFI secure boot without shim, one can
+disable shim_lock by disabling shim verification with MokSbState UEFI variable
+or by building grub image with @samp{--disable-shim-lock} option.
All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables,
Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
index 5d7210a82..41dadcd14 100644
--- a/grub-core/kern/efi/sb.c
+++ b/grub-core/kern/efi/sb.c
@@ -21,9 +21,11 @@
#include <grub/efi/efi.h>
#include <grub/efi/pe32.h>
#include <grub/efi/sb.h>
+#include <grub/env.h>
#include <grub/err.h>
#include <grub/file.h>
#include <grub/i386/linux.h>
+#include <grub/kernel.h>
#include <grub/mm.h>
#include <grub/types.h>
#include <grub/verify.h>
@@ -160,14 +162,27 @@ struct grub_file_verifier shim_lock_verifier =
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)
- return;
+ {
+ FOR_MODULES (header)
+ {
+ if (header->type == OBJ_TYPE_DISABLE_SHIM_LOCK)
+ return;
+ }
+ }
+ /* Secure Boot is off. Do not load shim_lock. */
if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
return;
+ /* Enforce shim_lock_verifier. */
grub_verifier_register (&shim_lock_verifier);
+
+ grub_env_set ("shim_lock", "y");
+ grub_env_export ("shim_lock");
}
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index 133a37c8d..abbca5ea3 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -29,7 +29,8 @@ enum
OBJ_TYPE_CONFIG,
OBJ_TYPE_PREFIX,
OBJ_TYPE_PUBKEY,
- OBJ_TYPE_DTB
+ OBJ_TYPE_DTB,
+ OBJ_TYPE_DISABLE_SHIM_LOCK
};
/* The module header. */
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 2207b54d7..0992aecbe 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -65,6 +65,8 @@
N_("embed FILE as public key for signature checking"), 0}, \
{ "sbat", GRUB_INSTALL_OPTIONS_SBAT, N_("FILE"), 0, \
N_("SBAT metadata"), 0 }, \
+ { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \
+ N_("disable shim_lock verifier"), 0 }, \
{ "verbose", 'v', 0, 0, \
N_("print verbose messages."), 1 }
@@ -126,7 +128,8 @@ enum grub_install_options {
GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
GRUB_INSTALL_OPTIONS_DTB,
- GRUB_INSTALL_OPTIONS_SBAT
+ GRUB_INSTALL_OPTIONS_SBAT,
+ GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK
};
extern char *grub_install_source_directory;
@@ -188,7 +191,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
const struct grub_install_image_target_desc *image_target,
int note,
grub_compression_t comp, const char *dtb_file,
- const char *sbat_path);
+ const char *sbat_path, const int disable_shim_lock);
const struct grub_install_image_target_desc *
grub_install_get_image_target (const char *arg);
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 4efee002f..c7b824789 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -343,6 +343,7 @@ handle_install_list (struct install_list *il, const char *val,
static char **pubkeys;
static size_t npubkeys;
static char *sbat;
+static int disable_shim_lock;
static grub_compression_t compression;
int
@@ -379,6 +380,9 @@ grub_install_parse (int key, char *arg)
sbat = xstrdup (arg);
return 1;
+ case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
+ disable_shim_lock = 1;
+ return 1;
case GRUB_INSTALL_OPTIONS_VERBOSITY:
verbosity++;
@@ -541,10 +545,11 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
" --output '%s' "
" --dtb '%s' "
"--sbat '%s' "
- "--format '%s' --compression '%s' %s %s\n",
+ "--format '%s' --compression '%s' %s %s %s\n",
dir, prefix,
outname, dtb ? : "", sbat ? : "", mkimage_target,
- compnames[compression], note ? "--note" : "", s);
+ compnames[compression], note ? "--note" : "",
+ disable_shim_lock ? "--disable-shim-lock" : "", s);
free (s);
tgt = grub_install_get_image_target (mkimage_target);
@@ -554,7 +559,8 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
grub_install_generate_image (dir, prefix, fp, outname,
modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt,
- note, compression, dtb, sbat);
+ note, compression, dtb, sbat,
+ disable_shim_lock);
while (dc--)
grub_install_pop_module ();
}
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index 75b884710..c0d559937 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -82,6 +82,7 @@ static struct argp_option options[] = {
{"format", 'O', N_("FORMAT"), 0, 0, 0},
{"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
{"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
+ {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
{ 0, 0, 0, 0, 0, 0 }
};
@@ -126,6 +127,7 @@ struct arguments
char *config;
char *sbat;
int note;
+ int disable_shim_lock;
const struct grub_install_image_target_desc *image_target;
grub_compression_t comp;
};
@@ -233,6 +235,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
arguments->sbat = xstrdup (arg);
break;
+ case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
+ arguments->disable_shim_lock = 1;
+ break;
+
case 'v':
verbosity++;
break;
@@ -319,7 +325,7 @@ main (int argc, char *argv[])
arguments.npubkeys, arguments.config,
arguments.image_target, arguments.note,
arguments.comp, arguments.dtb,
- arguments.sbat);
+ arguments.sbat, arguments.disable_shim_lock);
if (grub_util_file_sync (fp) < 0)
grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
diff --git a/util/mkimage.c b/util/mkimage.c
index b354ec1d9..a26cf76f7 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -870,7 +870,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc *image_target,
int note, grub_compression_t comp, const char *dtb_path,
- const char *sbat_path)
+ const char *sbat_path, int disable_shim_lock)
{
char *kernel_img, *core_img;
size_t total_module_size, core_size;
@@ -929,6 +929,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
if (sbat_path != NULL && image_target->id != IMAGE_EFI)
grub_util_error (_(".sbat section can be embedded into EFI images only"));
+ if (disable_shim_lock)
+ total_module_size += sizeof (struct grub_module_header);
+
if (config_path)
{
config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@@ -1065,6 +1068,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
offset += dtb_size;
}
+ if (disable_shim_lock)
+ {
+ struct grub_module_header *header;
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ header->type = grub_host_to_target32 (OBJ_TYPE_DISABLE_SHIM_LOCK);
+ header->size = grub_host_to_target32 (sizeof (*header));
+ offset += sizeof (*header);
+ }
+
if (config_path)
{
struct grub_module_header *header;
--
2.26.2

View File

@ -1,92 +0,0 @@
From 50f063f61eec3a99565db5f964970a872b642b27 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 11 Dec 2020 22:33:52 +0800
Subject: [PATCH 41/46] squash! Add secureboot support on efi chainloader
Use grub_efi_get_secureboot to get secure boot status
---
grub-core/loader/efi/chainloader.c | 54 ++----------------------------
1 file changed, 2 insertions(+), 52 deletions(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 8272df3cd..559247abf 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -46,6 +46,7 @@
#ifdef SUPPORT_SECURE_BOOT
#include <grub/efi/pe32.h>
+#include <grub/efi/sb.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
@@ -282,57 +283,6 @@ grub_secure_validate (void *data, grub_efi_uint32_t size)
return 0;
}
-static grub_efi_boolean_t
-grub_secure_mode (void)
-{
- grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
- grub_uint8_t *data;
- grub_size_t datasize;
-
- data = grub_efi_get_variable ("SecureBoot", &efi_var_guid, &datasize);
-
- if (data)
- {
- grub_dprintf ("chain", "SecureBoot: %d, datasize %d\n", (int)*data, (int)datasize);
- }
-
- if (data && (datasize == 1))
- {
- if (*data != 1)
- {
- grub_dprintf ("chain", "secure boot not enabled\n");
- return 0;
- }
- }
- else
- {
- grub_dprintf ("chain", "unknown secure boot status\n");
- return 0;
- }
-
- grub_free (data);
-
- data = grub_efi_get_variable ("SetupMode", &efi_var_guid, &datasize);
-
- if (data)
- {
- grub_dprintf ("chain", "SetupMode: %d, datasize %d\n", (int)*data, (int)datasize);
- }
-
- if (data && (datasize == 1))
- {
- if (*data == 1)
- {
- grub_dprintf ("chain", "platform in setup mode\n");
- return 0;
- }
- }
-
- grub_free (data);
-
- return 1;
-}
-
static grub_efi_boolean_t
read_header (void *data, grub_efi_uint32_t size, pe_coff_loader_image_context_t *context)
{
@@ -837,7 +787,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
#ifdef SUPPORT_SECURE_BOOT
/* FIXME is secure boot possible also with universal binaries? */
- if (debug_secureboot || (grub_secure_mode() && grub_secure_validate ((void *)address, fsize)))
+ if (debug_secureboot || (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED && grub_secure_validate ((void *)address, fsize)))
{
grub_file_close (file);
grub_loader_set (grub_secureboot_chainloader_boot, grub_secureboot_chainloader_unload, 0);
--
2.26.2

View File

@ -1,26 +0,0 @@
From 5673c583f3987350a51e39b64260a84342d9592a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 11 Dec 2020 22:39:54 +0800
Subject: [PATCH 42/46] squash! grub2-efi-chainload-harder
Use grub_efi_get_secureboot to get secure boot status
---
grub-core/loader/efi/chainloader.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
index 559247abf..7a910db44 100644
--- a/grub-core/loader/efi/chainloader.c
+++ b/grub-core/loader/efi/chainloader.c
@@ -799,7 +799,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
boot_image, fsize,
&image_handle);
#ifdef SUPPORT_SECURE_BOOT
- if (status == GRUB_EFI_SECURITY_VIOLATION && !grub_secure_mode())
+ if (status == GRUB_EFI_SECURITY_VIOLATION && grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
{
/* If it failed with security violation while not in secure boot mode,
the firmware might be broken. We try to workaround on that by forcing
--
2.26.2

View File

@ -1,88 +0,0 @@
From 768ab190a7c0a412bbec6142d12000655324daa0 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 11 Dec 2020 23:01:59 +0800
Subject: [PATCH 43/46] squash! Don't allow insmod when secure boot is enabled.
Use grub_efi_get_secureboot to get secure boot status
---
grub-core/kern/dl.c | 4 ++--
grub-core/kern/efi/efi.c | 28 ----------------------------
include/grub/efi/efi.h | 1 -
3 files changed, 2 insertions(+), 31 deletions(-)
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index e02f2afc5..93f08dfce 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -39,7 +39,7 @@
#endif
#ifdef GRUB_MACHINE_EFI
-#include <grub/efi/efi.h>
+#include <grub/efi/sb.h>
#endif
@@ -702,7 +702,7 @@ grub_dl_load_file (const char *filename)
grub_boot_time ("Loading module %s", filename);
#ifdef GRUB_MACHINE_EFI
- if (grub_efi_secure_boot ())
+ if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED)
{
#if 0
/* This is an error, but grub2-mkconfig still generates a pile of
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 92e99b441..32f1b2ec7 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -278,34 +278,6 @@ grub_efi_get_variable_with_attributes (const char *var,
return status;
}
-grub_efi_boolean_t
-grub_efi_secure_boot (void)
-{
- grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
- grub_size_t datasize;
- char *secure_boot = NULL;
- char *setup_mode = NULL;
- grub_efi_boolean_t ret = 0;
-
- secure_boot = grub_efi_get_variable("SecureBoot", &efi_var_guid, &datasize);
-
- if (datasize != 1 || !secure_boot)
- goto out;
-
- setup_mode = grub_efi_get_variable("SetupMode", &efi_var_guid, &datasize);
-
- if (datasize != 1 || !setup_mode)
- goto out;
-
- if (*secure_boot && !*setup_mode)
- ret = 1;
-
- out:
- grub_free (secure_boot);
- grub_free (setup_mode);
- return ret;
-}
-
grub_efi_status_t
grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
grub_size_t *datasize_out, void **data_out)
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 568d80030..08f6ee00a 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -91,7 +91,6 @@ EXPORT_FUNC (grub_efi_set_variable) (const char *var,
const grub_efi_guid_t *guid,
void *data,
grub_size_t datasize);
-grub_efi_boolean_t EXPORT_FUNC (grub_efi_secure_boot) (void);
int
EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
const grub_efi_device_path_t *dp2);
--
2.26.2

View File

@ -1,115 +0,0 @@
From 3c612287086a5f590f80d874e8c5c6042bf7f6a0 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 24 Feb 2021 23:51:38 +0800
Subject: [PATCH 44/46] squash! kern: Add lockdown support
Since the lockdown feature is efi specific, the
grub_{command,extcmd}_lockdown functions can be removed from other
platform for not taking up space in kernel image.
---
grub-core/commands/extcmd.c | 2 ++
grub-core/kern/command.c | 2 ++
include/grub/command.h | 11 +++++++++++
include/grub/extcmd.h | 13 +++++++++++++
4 files changed, 28 insertions(+)
diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c
index 90a5ca24a..4ac111a99 100644
--- a/grub-core/commands/extcmd.c
+++ b/grub-core/commands/extcmd.c
@@ -111,6 +111,7 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func,
summary, description, parser, 1);
}
+#ifdef GRUB_MACHINE_EFI
static grub_err_t
grub_extcmd_lockdown (grub_extcmd_context_t ctxt __attribute__ ((unused)),
int argc __attribute__ ((unused)),
@@ -132,6 +133,7 @@ grub_register_extcmd_lockdown (const char *name, grub_extcmd_func_t func,
return grub_register_extcmd (name, func, flags, summary, description, parser);
}
+#endif
void
grub_unregister_extcmd (grub_extcmd_t ext)
diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c
index 4aabcd4b5..17363af7b 100644
--- a/grub-core/kern/command.c
+++ b/grub-core/kern/command.c
@@ -78,6 +78,7 @@ grub_register_command_prio (const char *name,
return cmd;
}
+#ifdef GRUB_MACHINE_EFI
static grub_err_t
grub_cmd_lockdown (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
@@ -100,6 +101,7 @@ grub_register_command_lockdown (const char *name,
return grub_register_command_prio (name, func, summary, description, 0);
}
+#endif
void
grub_unregister_command (grub_command_t cmd)
diff --git a/include/grub/command.h b/include/grub/command.h
index 2a6f7f846..b518e262e 100644
--- a/include/grub/command.h
+++ b/include/grub/command.h
@@ -86,11 +86,22 @@ EXPORT_FUNC(grub_register_command_prio) (const char *name,
const char *summary,
const char *description,
int prio);
+#ifdef GRUB_MACHINE_EFI
grub_command_t
EXPORT_FUNC(grub_register_command_lockdown) (const char *name,
grub_command_func_t func,
const char *summary,
const char *description);
+#else
+static inline grub_command_t
+grub_register_command_lockdown (const char *name,
+ grub_command_func_t func,
+ const char *summary,
+ const char *description)
+{
+ return grub_register_command_prio (name, func, summary, description, 0);
+}
+#endif
void EXPORT_FUNC(grub_unregister_command) (grub_command_t cmd);
static inline grub_command_t
diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h
index fe9248b8b..fa1328ea5 100644
--- a/include/grub/extcmd.h
+++ b/include/grub/extcmd.h
@@ -62,12 +62,25 @@ grub_extcmd_t EXPORT_FUNC(grub_register_extcmd) (const char *name,
const char *description,
const struct grub_arg_option *parser);
+#ifdef GRUB_MACHINE_EFI
grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_lockdown) (const char *name,
grub_extcmd_func_t func,
grub_command_flags_t flags,
const char *summary,
const char *description,
const struct grub_arg_option *parser);
+#else
+static inline grub_extcmd_t
+grub_register_extcmd_lockdown (const char *name,
+ grub_extcmd_func_t func,
+ grub_command_flags_t flags,
+ const char *summary,
+ const char *description,
+ const struct grub_arg_option *parser)
+{
+ return grub_register_extcmd (name, func, flags, summary, description, parser);
+}
+#endif
grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_prio) (const char *name,
grub_extcmd_func_t func,
--
2.26.2

View File

@ -1,68 +0,0 @@
From 601c838c4cf3e6bd3e8e19b9e7aa4331cac0dc25 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 25 Feb 2021 20:44:58 +0800
Subject: [PATCH 45/46] squash! Add support for Linux EFI stub loading on
aarch64.
The efi shim_lock verifier has been moved to grub core so local
shim_lock protocol is no longer needed here for aarch64 efi to verify
the loaded kernel image. From now on the framework will take care the
verificaion, consolidating the integration of various security verifiers
like secure boot, gpg and tpm.
---
grub-core/loader/arm64/efi/linux.c | 32 ------------------------------
1 file changed, 32 deletions(-)
diff --git a/grub-core/loader/arm64/efi/linux.c b/grub-core/loader/arm64/efi/linux.c
index 8549e555b..b73105347 100644
--- a/grub-core/loader/arm64/efi/linux.c
+++ b/grub-core/loader/arm64/efi/linux.c
@@ -49,32 +49,6 @@ static grub_uint32_t cmdline_size;
static grub_addr_t initrd_start;
static grub_addr_t initrd_end;
-#define SHIM_LOCK_GUID \
- { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }
-
-struct grub_efi_shim_lock
-{
- grub_efi_status_t (*verify) (void *buffer, grub_uint32_t size);
-};
-typedef struct grub_efi_shim_lock grub_efi_shim_lock_t;
-
-static grub_efi_boolean_t
-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;
-
- shim_lock = grub_efi_locate_protocol(&guid, NULL);
-
- if (!shim_lock)
- return 1;
-
- if (shim_lock->verify(data, size) == GRUB_EFI_SUCCESS)
- return 1;
-
- return 0;
-}
-
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -443,12 +417,6 @@ 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))
- {
- grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
- goto fail;
- }
-
pe = (void *)((unsigned long)kernel_addr + lh.hdr_offset);
handover_offset = pe->opt.entry_addr;
--
2.26.2

View File

@ -1,153 +0,0 @@
From 59ac440754a43c6e964e924a086af066e04e753e Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Fri, 26 Feb 2021 19:43:14 +0800
Subject: [PATCH 46/46] squash! verifiers: Move verifiers API to kernel image
In case there's broken i386-pc setup running inconsistent installs for
module in filesystem and core image on the disk, keeping the verifiers
as module for i386-pc to avoid potential issue of looking up symbols.
---
configure.ac | 1 +
grub-core/Makefile.am | 2 ++
grub-core/Makefile.core.def | 8 +++++++-
grub-core/kern/main.c | 4 ++++
grub-core/kern/verifiers.c | 11 +++++++++++
include/grub/verify.h | 9 +++++++++
6 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index c39e8379f..530da4b01 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1913,6 +1913,7 @@ AM_CONDITIONAL([COND_real_platform], [test x$platform != xnone])
AM_CONDITIONAL([COND_emu], [test x$platform = xemu])
AM_CONDITIONAL([COND_NOT_emu], [test x$platform != xemu])
AM_CONDITIONAL([COND_i386_pc], [test x$target_cpu = xi386 -a x$platform = xpc])
+AM_CONDITIONAL([COND_NOT_i386_pc], [test x$target_cpu != xi386 -o x$platform != xpc])
AM_CONDITIONAL([COND_i386_efi], [test x$target_cpu = xi386 -a x$platform = xefi])
AM_CONDITIONAL([COND_ia64_efi], [test x$target_cpu = xia64 -a x$platform = xefi])
AM_CONDITIONAL([COND_i386_qemu], [test x$target_cpu = xi386 -a x$platform = xqemu])
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 6b2e5e139..47c91e35d 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -92,7 +92,9 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
+if COND_NOT_i386_pc
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/verify.h
+endif
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index eac42a7b7..893044538 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -141,7 +141,7 @@ kernel = {
common = kern/rescue_parser.c;
common = kern/rescue_reader.c;
common = kern/term.c;
- common = kern/verifiers.c;
+ nopc = kern/verifiers.c;
noemu = kern/compiler-rt.c;
noemu = kern/mm.c;
@@ -946,6 +946,12 @@ module = {
cppflags = '-I$(srcdir)/lib/posix_wrap';
};
+module = {
+ name = verifiers;
+ common = kern/verifiers.c;
+ enable = i386_pc;
+};
+
module = {
name = hdparm;
common = commands/hdparm.c;
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 73967e2f5..c7c6d2d0b 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -29,7 +29,9 @@
#include <grub/command.h>
#include <grub/reader.h>
#include <grub/parser.h>
+#ifndef GRUB_MACHINE_PCBIOS
#include <grub/verify.h>
+#endif
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/memory.h>
@@ -275,8 +277,10 @@ grub_main (void)
grub_printf ("Welcome to GRUB!\n\n");
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+#ifndef GRUB_MACHINE_PCBIOS
/* Init verifiers API. */
grub_verifiers_init ();
+#endif
grub_load_config ();
diff --git a/grub-core/kern/verifiers.c b/grub-core/kern/verifiers.c
index 3d19bffd1..479253351 100644
--- a/grub-core/kern/verifiers.c
+++ b/grub-core/kern/verifiers.c
@@ -218,8 +218,19 @@ grub_verify_string (char *str, enum grub_verify_string_type type)
return GRUB_ERR_NONE;
}
+#ifdef GRUB_MACHINE_PCBIOS
+GRUB_MOD_INIT(verifiers)
+#else
void
grub_verifiers_init (void)
+#endif
{
grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open);
}
+
+#ifdef GRUB_MACHINE_PCBIOS
+GRUB_MOD_FINI(verifiers)
+{
+ grub_file_filter_unregister (GRUB_FILE_FILTER_VERIFY);
+}
+#endif
diff --git a/include/grub/verify.h b/include/grub/verify.h
index cd129c398..6fde244fc 100644
--- a/include/grub/verify.h
+++ b/include/grub/verify.h
@@ -64,10 +64,14 @@ struct grub_file_verifier
grub_err_t (*verify_string) (char *str, enum grub_verify_string_type type);
};
+#ifdef GRUB_MACHINE_PCBIOS
+extern struct grub_file_verifier *grub_file_verifiers;
+#else
extern struct grub_file_verifier *EXPORT_VAR (grub_file_verifiers);
extern void
grub_verifiers_init (void);
+#endif
static inline void
grub_verifier_register (struct grub_file_verifier *ver)
@@ -81,7 +85,12 @@ grub_verifier_unregister (struct grub_file_verifier *ver)
grub_list_remove (GRUB_AS_LIST (ver));
}
+#ifdef GRUB_MACHINE_PCBIOS
+grub_err_t
+grub_verify_string (char *str, enum grub_verify_string_type type);
+#else
extern grub_err_t
EXPORT_FUNC (grub_verify_string) (char *str, enum grub_verify_string_type type);
+#endif
#endif /* ! GRUB_VERIFY_HEADER */
--
2.26.2

View File

@ -1,73 +1,3 @@
-------------------------------------------------------------------
Fri Mar 5 09:41:07 UTC 2021 - Michael Chang <mchang@suse.com>
- Fix chainloading windows on dual boot machine (bsc#1183073)
* 0001-Add-chainloaded-image-as-shim-s-verifiable-object.patch
-------------------------------------------------------------------
Fri Feb 26 06:52:18 UTC 2021 - Michael Chang <mchang@suse.com>
- 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
* 0004-efi-Add-a-function-to-read-EFI-variables-with-attrib.patch
* 0005-efi-Add-secure-boot-detection.patch
* 0006-efi-Only-register-shim_lock-verifier-if-shim_lock-pr.patch
* 0007-verifiers-Move-verifiers-API-to-kernel-image.patch
* 0008-efi-Move-the-shim_lock-verifier-to-the-GRUB-core.patch
* 0009-kern-Add-lockdown-support.patch
* 0010-kern-lockdown-Set-a-variable-if-the-GRUB-is-locked-d.patch
* 0011-efi-Lockdown-the-GRUB-when-the-UEFI-Secure-Boot-is-e.patch
* 0012-efi-Use-grub_is_lockdown-instead-of-hardcoding-a-dis.patch
* 0013-acpi-Don-t-register-the-acpi-command-when-locked-dow.patch
* 0014-mmap-Don-t-register-cutmem-and-badram-commands-when-.patch
* 0015-commands-Restrict-commands-that-can-load-BIOS-or-DT-.patch
* 0016-commands-setpci-Restrict-setpci-command-when-locked-.patch
* 0017-commands-hdparm-Restrict-hdparm-command-when-locked-.patch
* 0018-gdb-Restrict-GDB-access-when-locked-down.patch
* 0019-loader-xnu-Don-t-allow-loading-extension-and-package.patch
* 0040-shim_lock-Only-skip-loading-shim_lock-verifier-with-.patch
* 0041-squash-Add-secureboot-support-on-efi-chainloader.patch
* 0042-squash-grub2-efi-chainload-harder.patch
* 0043-squash-Don-t-allow-insmod-when-secure-boot-is-enable.patch
* 0044-squash-kern-Add-lockdown-support.patch
* 0045-squash-Add-support-for-Linux-EFI-stub-loading-on-aar.patch
* 0046-squash-verifiers-Move-verifiers-API-to-kernel-image.patch
- Drop patch supersceded by the new backport
* 0001-linuxefi-fail-kernel-validation-without-shim-protoco.patch
* 0001-shim_lock-Disable-GRUB_VERIFY_FLAGS_DEFER_AUTH-if-se.patch
* 0007-linuxefi-fail-kernel-validation-without-shim-protoco.patch
- Add SBAT metadata section to grub.efi
- Drop shim_lock module as it is part of core of grub.efi
* grub2.spec
-------------------------------------------------------------------
Mon Feb 22 12:49:48 UTC 2021 - Michael Chang <mchang@suse.com>

View File

@ -321,12 +321,16 @@ Patch712: 0009-script-Avoid-a-use-after-free-when-redefining-a-func.patch
# overflows in initrd size handling
Patch713: 0010-linux-Fix-integer-overflows-in-initrd-size-handling.patch
Patch714: 0001-kern-mm.c-Make-grub_calloc-inline.patch
# bsc#1174421 VUL-0: CVE-2020-15705: grub2: linuxefi: fail kernel validation
# without shim protocol
Patch715: 0001-linuxefi-fail-kernel-validation-without-shim-protoco.patch
Patch716: 0002-cmdline-Provide-cmdline-functions-as-module.patch
# bsc#1172745 L3: SLES 12 SP4 - Slow boot of system after updated kernel -
# takes 45 minutes after grub to start loading kernel
Patch717: 0001-ieee1275-powerpc-implements-fibre-channel-discovery-.patch
Patch718: 0002-ieee1275-powerpc-enables-device-mapper-discovery.patch
Patch719: 0001-Unify-the-check-to-enable-btrfs-relative-path.patch
Patch720: 0001-shim_lock-Disable-GRUB_VERIFY_FLAGS_DEFER_AUTH-if-se.patch
Patch721: 0001-efi-linux-provide-linux-command.patch
# Improve the error handling when grub2-install fails with short mbr gap
# (bsc#1176062)
@ -339,58 +343,11 @@ Patch732: 0003-Make-grub_error-more-verbose.patch
Patch733: 0004-arm-arm64-loader-Better-memory-allocation-and-error-.patch
Patch734: 0005-Make-linux_arm_kernel_header.hdr_offset-be-at-the-ri.patch
Patch735: 0006-efi-Set-image-base-address-before-jumping-to-the-PE-.patch
Patch736: 0007-linuxefi-fail-kernel-validation-without-shim-protoco.patch
Patch737: 0008-squash-Add-support-for-Linux-EFI-stub-loading-on-aar.patch
Patch738: 0009-squash-Add-support-for-linuxefi.patch
Patch739: 0001-Fix-build-error-in-binutils-2.36.patch
Patch740: 0001-emu-fix-executable-stack-marking.patch
# Boothole2
Patch741: 0001-include-grub-i386-linux.h-Include-missing-grub-types.patch
Patch742: 0002-efi-Make-shim_lock-GUID-and-protocol-type-public.patch
Patch743: 0003-efi-Return-grub_efi_status_t-from-grub_efi_get_varia.patch
Patch744: 0004-efi-Add-a-function-to-read-EFI-variables-with-attrib.patch
Patch745: 0005-efi-Add-secure-boot-detection.patch
Patch746: 0006-efi-Only-register-shim_lock-verifier-if-shim_lock-pr.patch
Patch747: 0007-verifiers-Move-verifiers-API-to-kernel-image.patch
Patch748: 0008-efi-Move-the-shim_lock-verifier-to-the-GRUB-core.patch
Patch749: 0009-kern-Add-lockdown-support.patch
Patch750: 0010-kern-lockdown-Set-a-variable-if-the-GRUB-is-locked-d.patch
Patch751: 0011-efi-Lockdown-the-GRUB-when-the-UEFI-Secure-Boot-is-e.patch
Patch752: 0012-efi-Use-grub_is_lockdown-instead-of-hardcoding-a-dis.patch
Patch753: 0013-acpi-Don-t-register-the-acpi-command-when-locked-dow.patch
Patch754: 0014-mmap-Don-t-register-cutmem-and-badram-commands-when-.patch
Patch755: 0015-commands-Restrict-commands-that-can-load-BIOS-or-DT-.patch
Patch756: 0016-commands-setpci-Restrict-setpci-command-when-locked-.patch
Patch757: 0017-commands-hdparm-Restrict-hdparm-command-when-locked-.patch
Patch758: 0018-gdb-Restrict-GDB-access-when-locked-down.patch
Patch759: 0019-loader-xnu-Don-t-allow-loading-extension-and-package.patch
Patch760: 0020-dl-Only-allow-unloading-modules-that-are-not-depende.patch
Patch761: 0021-usb-Avoid-possible-out-of-bound-accesses-caused-by-m.patch
Patch762: 0022-lib-arg-Block-repeated-short-options-that-require-an.patch
Patch763: 0023-commands-menuentry-Fix-quoting-in-setparams_prefix.patch
Patch764: 0024-kern-parser-Fix-resource-leak-if-argc-0.patch
Patch765: 0025-kern-parser-Fix-a-memory-leak.patch
Patch766: 0026-kern-parser-Introduce-process_char-helper.patch
Patch767: 0027-kern-parser-Introduce-terminate_arg-helper.patch
Patch768: 0028-kern-parser-Refactor-grub_parser_split_cmdline-clean.patch
Patch769: 0029-kern-buffer-Add-variable-sized-heap-buffer.patch
Patch770: 0030-kern-parser-Fix-a-stack-buffer-overflow.patch
Patch771: 0031-util-mkimage-Remove-unused-code-to-add-BSS-section.patch
Patch772: 0032-util-mkimage-Use-grub_host_to_target32-instead-of-gr.patch
Patch773: 0033-util-mkimage-Always-use-grub_host_to_target32-to-ini.patch
Patch774: 0034-util-mkimage-Unify-more-of-the-PE32-and-PE32-header-.patch
Patch775: 0035-util-mkimage-Reorder-PE-optional-header-fields-set-u.patch
Patch776: 0036-util-mkimage-Improve-data_size-value-calculation.patch
Patch777: 0037-util-mkimage-Refactor-section-setup-to-use-a-helper.patch
Patch778: 0038-util-mkimage-Add-an-option-to-import-SBAT-metadata-i.patch
Patch779: 0039-grub-install-common-Add-sbat-option.patch
Patch780: 0040-shim_lock-Only-skip-loading-shim_lock-verifier-with-.patch
Patch781: 0041-squash-Add-secureboot-support-on-efi-chainloader.patch
Patch782: 0042-squash-grub2-efi-chainload-harder.patch
Patch783: 0043-squash-Don-t-allow-insmod-when-secure-boot-is-enable.patch
Patch784: 0044-squash-kern-Add-lockdown-support.patch
Patch785: 0045-squash-Add-support-for-Linux-EFI-stub-loading-on-aar.patch
Patch786: 0046-squash-verifiers-Move-verifiers-API-to-kernel-image.patch
Patch787: 0001-Add-chainloaded-image-as-shim-s-verifiable-object.patch
Requires: gettext-runtime
%if 0%{?suse_version} >= 1140
@ -707,10 +664,12 @@ swap partition while in resuming
%patch712 -p1
%patch713 -p1
%patch714 -p1
%patch715 -p1
%patch716 -p1
%patch717 -p1
%patch718 -p1
%patch719 -p1
%patch720 -p1
%patch721 -p1
%patch722 -p1
%patch723 -p1
@ -720,57 +679,11 @@ swap partition while in resuming
%patch733 -p1
%patch734 -p1
%patch735 -p1
%patch736 -p1
%patch737 -p1
%patch738 -p1
%patch739 -p1
%patch740 -p1
%patch741 -p1
%patch742 -p1
%patch743 -p1
%patch744 -p1
%patch745 -p1
%patch746 -p1
%patch747 -p1
%patch748 -p1
%patch749 -p1
%patch750 -p1
%patch751 -p1
%patch752 -p1
%patch753 -p1
%patch754 -p1
%patch755 -p1
%patch756 -p1
%patch757 -p1
%patch758 -p1
%patch759 -p1
%patch760 -p1
%patch761 -p1
%patch762 -p1
%patch763 -p1
%patch764 -p1
%patch765 -p1
%patch766 -p1
%patch767 -p1
%patch768 -p1
%patch769 -p1
%patch770 -p1
%patch771 -p1
%patch772 -p1
%patch773 -p1
%patch774 -p1
%patch775 -p1
%patch776 -p1
%patch777 -p1
%patch778 -p1
%patch779 -p1
%patch780 -p1
%patch781 -p1
%patch782 -p1
%patch783 -p1
%patch784 -p1
%patch785 -p1
%patch786 -p1
%patch787 -p1
%build
# collect evidence to debug spurious build failure on SLE15
@ -876,30 +789,16 @@ PXE_MODULES="efinet tftp http"
CRYPTO_MODULES="luks gcry_rijndael gcry_sha1 gcry_sha256"
%ifarch x86_64
CD_MODULES="${CD_MODULES} linuxefi"
CD_MODULES="${CD_MODULES} shim_lock linuxefi"
%else
CD_MODULES="${CD_MODULES} linux"
%endif
# SBAT metadata
%if 0%{?is_opensuse} == 1
distro_id="opensuse"
distro_name="The openSUSE Project"
%else
distro_id="sle"
distro_name="SUSE Linux Enterprise"
%endif
upstream_sbat=1
distro_sbat=1
echo "sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md" > sbat.csv
echo "grub,${upstream_sbat},Free Software Foundation,grub,%{version},https://www.gnu.org/software/grub/" >> sbat.csv
echo "grub.${distro_id},${distro_sbat},${distro_name},%{name},%{version},mail:security-team@suse.de" >> sbat.csv
GRUB_MODULES="${CD_MODULES} ${FS_MODULES} ${PXE_MODULES} ${CRYPTO_MODULES} mdraid09 mdraid1x lvm serial"
./grub-mkimage -O %{grubefiarch} -o grub.efi --prefix= --sbat sbat.csv \
./grub-mkimage -O %{grubefiarch} -o grub.efi --prefix= \
-d grub-core ${GRUB_MODULES}
%ifarch x86_64
./grub-mkimage -O %{grubefiarch} -o grub-tpm.efi --prefix= --sbat sbat.csv \
./grub-mkimage -O %{grubefiarch} -o grub-tpm.efi --prefix= \
-d grub-core ${GRUB_MODULES} tpm
%endif