-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
boot/grub2: backport fixes for numerous CVEs
Grub 2.06 is affected by a number of CVEs, which have been fixed in the master branch of Grub, but are not yet part of any release (there is a 2.12-rc1 release, but nothing else between 2.06 and 2.12-rc1). So this patch backports the relevant fixes for CVE-2022-28736, CVE-2022-28735, CVE-2021-3695, CVE-2021-3696, CVE-2021-3697, CVE-2022-28733, CVE-2022-28734, CVE-2022-2601 and CVE-2022-3775. It should be noted that CVE-2021-3695, CVE-2021-3696, CVE-2021-3697 are not reported as affecting Grub by our CVE matching logic because the NVD database uses an incorrect CPE ID in those CVEs: it uses "grub" as the product instead of "grub2" like all other CVEs for grub. This issue has been reported to the NVD maintainers. This requires backporting a lot of patches, but jumping from 2.06 to 2.12-rc1 implies getting 592 commits, which is quite a lot. All Grub test cases are working fine: https://gitlab.com/tpetazzoni/buildroot/-/pipelines/984500585 https://gitlab.com/tpetazzoni/buildroot/-/pipelines/984500679 Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> [Arnout: fix check-package warning in patch 0002] Signed-off-by: Arnout Vandecappelle <arnout@mind.be>
- Loading branch information
1 parent
60f50a5
commit 65c9939
Showing
19 changed files
with
2,170 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
boot/grub2/0003-loader-efi-chainloader-Simplify-the-loader-state.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
From dfdc742bdb22be468035f96cce0be5fee23b6df5 Mon Sep 17 00:00:00 2001 | ||
From: Chris Coulson <chris.coulson@canonical.com> | ||
Date: Tue, 5 Apr 2022 10:02:04 +0100 | ||
Subject: [PATCH] loader/efi/chainloader: Simplify the loader state | ||
|
||
The chainloader command retains the source buffer and device path passed | ||
to LoadImage(), requiring the unload hook passed to grub_loader_set() to | ||
free them. It isn't required to retain this state though - they aren't | ||
required by StartImage() or anything else in the boot hook, so clean them | ||
up before grub_cmd_chainloader() finishes. | ||
|
||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com> | ||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | ||
Upstream: 1469983ebb9674753ad333d37087fb8cb20e1dce | ||
[Thomas: needed to cherry-pick | ||
04c86e0bb7b58fc2f913f798cdb18934933e532d which fixes CVE-2022-28736] | ||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> | ||
--- | ||
grub-core/loader/efi/chainloader.c | 38 +++++++++++++++++------------- | ||
1 file changed, 21 insertions(+), 17 deletions(-) | ||
|
||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c | ||
index 2bd80f4db..d1602c89b 100644 | ||
--- a/grub-core/loader/efi/chainloader.c | ||
+++ b/grub-core/loader/efi/chainloader.c | ||
@@ -44,25 +44,20 @@ GRUB_MOD_LICENSE ("GPLv3+"); | ||
|
||
static grub_dl_t my_mod; | ||
|
||
-static grub_efi_physical_address_t address; | ||
-static grub_efi_uintn_t pages; | ||
-static grub_efi_device_path_t *file_path; | ||
static grub_efi_handle_t image_handle; | ||
-static grub_efi_char16_t *cmdline; | ||
|
||
static grub_err_t | ||
grub_chainloader_unload (void) | ||
{ | ||
+ grub_efi_loaded_image_t *loaded_image; | ||
grub_efi_boot_services_t *b; | ||
|
||
+ loaded_image = grub_efi_get_loaded_image (image_handle); | ||
+ if (loaded_image != NULL) | ||
+ grub_free (loaded_image->load_options); | ||
+ | ||
b = grub_efi_system_table->boot_services; | ||
efi_call_1 (b->unload_image, image_handle); | ||
- efi_call_2 (b->free_pages, address, pages); | ||
- | ||
- grub_free (file_path); | ||
- grub_free (cmdline); | ||
- cmdline = 0; | ||
- file_path = 0; | ||
|
||
grub_dl_unref (my_mod); | ||
return GRUB_ERR_NONE; | ||
@@ -140,7 +135,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename) | ||
char *dir_start; | ||
char *dir_end; | ||
grub_size_t size; | ||
- grub_efi_device_path_t *d; | ||
+ grub_efi_device_path_t *d, *file_path; | ||
|
||
dir_start = grub_strchr (filename, ')'); | ||
if (! dir_start) | ||
@@ -222,11 +217,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
grub_efi_status_t status; | ||
grub_efi_boot_services_t *b; | ||
grub_device_t dev = 0; | ||
- grub_efi_device_path_t *dp = 0; | ||
+ grub_efi_device_path_t *dp = NULL, *file_path = NULL; | ||
grub_efi_loaded_image_t *loaded_image; | ||
char *filename; | ||
void *boot_image = 0; | ||
grub_efi_handle_t dev_handle = 0; | ||
+ grub_efi_physical_address_t address = 0; | ||
+ grub_efi_uintn_t pages = 0; | ||
+ grub_efi_char16_t *cmdline = NULL; | ||
|
||
if (argc == 0) | ||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); | ||
@@ -234,11 +232,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
|
||
grub_dl_ref (my_mod); | ||
|
||
- /* Initialize some global variables. */ | ||
- address = 0; | ||
- image_handle = 0; | ||
- file_path = 0; | ||
- | ||
b = grub_efi_system_table->boot_services; | ||
|
||
file = grub_file_open (filename, GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE); | ||
@@ -408,6 +401,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
grub_file_close (file); | ||
grub_device_close (dev); | ||
|
||
+ /* We're finished with the source image buffer and file path now. */ | ||
+ efi_call_2 (b->free_pages, address, pages); | ||
+ grub_free (file_path); | ||
+ | ||
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); | ||
return 0; | ||
|
||
@@ -419,11 +416,18 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), | ||
if (file) | ||
grub_file_close (file); | ||
|
||
+ grub_free (cmdline); | ||
grub_free (file_path); | ||
|
||
if (address) | ||
efi_call_2 (b->free_pages, address, pages); | ||
|
||
+ if (image_handle != NULL) | ||
+ { | ||
+ efi_call_1 (b->unload_image, image_handle); | ||
+ image_handle = NULL; | ||
+ } | ||
+ | ||
grub_dl_unref (my_mod); | ||
|
||
return grub_errno; | ||
-- | ||
2.41.0 | ||
|
165 changes: 165 additions & 0 deletions
165
boot/grub2/0004-commands-boot-Add-API-to-pass-context-to-loader.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
From 8b6336696d93b51703c2015eff3e2d8a02145e43 Mon Sep 17 00:00:00 2001 | ||
From: Chris Coulson <chris.coulson@canonical.com> | ||
Date: Tue, 5 Apr 2022 10:58:28 +0100 | ||
Subject: [PATCH] commands/boot: Add API to pass context to loader | ||
|
||
Loaders rely on global variables for saving context which is consumed | ||
in the boot hook and freed in the unload hook. In the case where a loader | ||
command is executed twice, calling grub_loader_set() a second time executes | ||
the unload hook, but in some cases this runs when the loader's global | ||
context has already been updated, resulting in the updated context being | ||
freed and potential use-after-free bugs when the boot hook is subsequently | ||
called. | ||
|
||
This adds a new API, grub_loader_set_ex(), which allows a loader to specify | ||
context that is passed to its boot and unload hooks. This is an alternative | ||
to requiring that loaders call grub_loader_unset() before mutating their | ||
global context. | ||
|
||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com> | ||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | ||
Upstream: 14ceb3b3ff6db664649138442b6562c114dcf56e | ||
[Thomas: needed to backport 04c86e0bb7b58fc2f913f798cdb18934933e532d, | ||
which fixes CVE-2022-28736] | ||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> | ||
--- | ||
grub-core/commands/boot.c | 66 ++++++++++++++++++++++++++++++++++----- | ||
include/grub/loader.h | 5 +++ | ||
2 files changed, 63 insertions(+), 8 deletions(-) | ||
|
||
diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c | ||
index bbca81e94..61514788e 100644 | ||
--- a/grub-core/commands/boot.c | ||
+++ b/grub-core/commands/boot.c | ||
@@ -27,10 +27,20 @@ | ||
|
||
GRUB_MOD_LICENSE ("GPLv3+"); | ||
|
||
-static grub_err_t (*grub_loader_boot_func) (void); | ||
-static grub_err_t (*grub_loader_unload_func) (void); | ||
+static grub_err_t (*grub_loader_boot_func) (void *context); | ||
+static grub_err_t (*grub_loader_unload_func) (void *context); | ||
+static void *grub_loader_context; | ||
static int grub_loader_flags; | ||
|
||
+struct grub_simple_loader_hooks | ||
+{ | ||
+ grub_err_t (*boot) (void); | ||
+ grub_err_t (*unload) (void); | ||
+}; | ||
+ | ||
+/* Don't heap allocate this to avoid making grub_loader_set() fallible. */ | ||
+static struct grub_simple_loader_hooks simple_loader_hooks; | ||
+ | ||
struct grub_preboot | ||
{ | ||
grub_err_t (*preboot_func) (int); | ||
@@ -44,6 +54,29 @@ static int grub_loader_loaded; | ||
static struct grub_preboot *preboots_head = 0, | ||
*preboots_tail = 0; | ||
|
||
+static grub_err_t | ||
+grub_simple_boot_hook (void *context) | ||
+{ | ||
+ struct grub_simple_loader_hooks *hooks; | ||
+ | ||
+ hooks = (struct grub_simple_loader_hooks *) context; | ||
+ return hooks->boot (); | ||
+} | ||
+ | ||
+static grub_err_t | ||
+grub_simple_unload_hook (void *context) | ||
+{ | ||
+ struct grub_simple_loader_hooks *hooks; | ||
+ grub_err_t ret; | ||
+ | ||
+ hooks = (struct grub_simple_loader_hooks *) context; | ||
+ | ||
+ ret = hooks->unload (); | ||
+ grub_memset (hooks, 0, sizeof (*hooks)); | ||
+ | ||
+ return ret; | ||
+} | ||
+ | ||
int | ||
grub_loader_is_loaded (void) | ||
{ | ||
@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) | ||
} | ||
|
||
void | ||
-grub_loader_set (grub_err_t (*boot) (void), | ||
- grub_err_t (*unload) (void), | ||
- int flags) | ||
+grub_loader_set_ex (grub_err_t (*boot) (void *context), | ||
+ grub_err_t (*unload) (void *context), | ||
+ void *context, | ||
+ int flags) | ||
{ | ||
if (grub_loader_loaded && grub_loader_unload_func) | ||
- grub_loader_unload_func (); | ||
+ grub_loader_unload_func (grub_loader_context); | ||
|
||
grub_loader_boot_func = boot; | ||
grub_loader_unload_func = unload; | ||
+ grub_loader_context = context; | ||
grub_loader_flags = flags; | ||
|
||
grub_loader_loaded = 1; | ||
} | ||
|
||
+void | ||
+grub_loader_set (grub_err_t (*boot) (void), | ||
+ grub_err_t (*unload) (void), | ||
+ int flags) | ||
+{ | ||
+ grub_loader_set_ex (grub_simple_boot_hook, | ||
+ grub_simple_unload_hook, | ||
+ &simple_loader_hooks, | ||
+ flags); | ||
+ | ||
+ simple_loader_hooks.boot = boot; | ||
+ simple_loader_hooks.unload = unload; | ||
+} | ||
+ | ||
void | ||
grub_loader_unset(void) | ||
{ | ||
if (grub_loader_loaded && grub_loader_unload_func) | ||
- grub_loader_unload_func (); | ||
+ grub_loader_unload_func (grub_loader_context); | ||
|
||
grub_loader_boot_func = 0; | ||
grub_loader_unload_func = 0; | ||
+ grub_loader_context = 0; | ||
|
||
grub_loader_loaded = 0; | ||
} | ||
@@ -158,7 +208,7 @@ grub_loader_boot (void) | ||
return err; | ||
} | ||
} | ||
- err = (grub_loader_boot_func) (); | ||
+ err = (grub_loader_boot_func) (grub_loader_context); | ||
|
||
for (cur = preboots_tail; cur; cur = cur->prev) | ||
if (! err) | ||
diff --git a/include/grub/loader.h b/include/grub/loader.h | ||
index b20864282..97f231054 100644 | ||
--- a/include/grub/loader.h | ||
+++ b/include/grub/loader.h | ||
@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), | ||
grub_err_t (*unload) (void), | ||
int flags); | ||
|
||
+void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *context), | ||
+ grub_err_t (*unload) (void *context), | ||
+ void *context, | ||
+ int flags); | ||
+ | ||
/* Unset current loader, if any. */ | ||
void EXPORT_FUNC (grub_loader_unset) (void); | ||
|
||
-- | ||
2.41.0 | ||
|
Oops, something went wrong.