diff options
Diffstat (limited to 'meta/recipes-bsp/grub/files/CVE-2022-28736.patch')
-rw-r--r-- | meta/recipes-bsp/grub/files/CVE-2022-28736.patch | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/meta/recipes-bsp/grub/files/CVE-2022-28736.patch b/meta/recipes-bsp/grub/files/CVE-2022-28736.patch new file mode 100644 index 0000000000..4fc9fdaf05 --- /dev/null +++ b/meta/recipes-bsp/grub/files/CVE-2022-28736.patch @@ -0,0 +1,275 @@ +From 431a111c60095fc973d83fe9209f26f29ce78784 Mon Sep 17 00:00:00 2001 +From: Hitendra Prajapati <hprajapati@mvista.com> +Date: Mon, 1 Aug 2022 11:17:17 +0530 +Subject: [PATCH] CVE-2022-28736 + +Upstream-Status: Backport [https://git.savannah.gnu.org/gitweb/?p=grub.git;a=commit;h=04c86e0bb7b58fc2f913f798cdb18934933e532d] +CVE: CVE-2022-28736 +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> + +loader/efi/chainloader: Use grub_loader_set_ex() + +This ports the EFI chainloader to use grub_loader_set_ex() in order to fix +a use-after-free bug that occurs when grub_cmd_chainloader() is executed +more than once before a boot attempt is performed. + +Fixes: CVE-2022-28736 + +Signed-off-by: Chris Coulson <chris.coulson@canonical.com> +Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> +--- + grub-core/commands/boot.c | 66 ++++++++++++++++++++++++++---- + grub-core/loader/efi/chainloader.c | 46 +++++++++++---------- + include/grub/loader.h | 5 +++ + 3 files changed, 87 insertions(+), 30 deletions(-) + +diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c +index bbca81e..6151478 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/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c +index a8d7b91..93a028a 100644 +--- a/grub-core/loader/efi/chainloader.c ++++ b/grub-core/loader/efi/chainloader.c +@@ -44,33 +44,28 @@ 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_chainloader_unload (void *context) + { ++ grub_efi_handle_t image_handle = (grub_efi_handle_t) context; ++ 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; + } + + static grub_err_t +-grub_chainloader_boot (void) ++grub_chainloader_boot (void *context) + { ++ grub_efi_handle_t image_handle = (grub_efi_handle_t) context; + grub_efi_boot_services_t *b; + grub_efi_status_t status; + grub_efi_uintn_t exit_data_size; +@@ -139,7 +134,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) +@@ -215,11 +210,15 @@ 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; ++ grub_efi_handle_t image_handle = NULL; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); +@@ -227,11 +226,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); +@@ -401,7 +395,11 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), + grub_file_close (file); + grub_device_close (dev); + +- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0); ++ /* 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_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0); + return 0; + + fail: +@@ -412,11 +410,15 @@ 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); ++ + grub_dl_unref (my_mod); + + return grub_errno; +diff --git a/include/grub/loader.h b/include/grub/loader.h +index 7f82a49..3071a50 100644 +--- a/include/grub/loader.h ++++ b/include/grub/loader.h +@@ -39,6 +39,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.25.1 + |