From e4e452562cf441752bdc0bb9da046cbc082c9f30 Mon Sep 17 00:00:00 2001 From: Nicolas Frayer Date: Tue, 28 May 2024 12:13:38 +0200 Subject: [PATCH] cmd/search: Rework of CVE-2023-4001 fix Resolves: #RHEL-36249 Resolves: #RHEL-36186 Signed-off-by: Nicolas Frayer --- ...d-search-Rework-of-CVE-2023-4001-fix.patch | 182 ++++++++++++++++++ grub.patches | 1 + grub2.spec | 7 +- 3 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 0345-cmd-search-Rework-of-CVE-2023-4001-fix.patch diff --git a/0345-cmd-search-Rework-of-CVE-2023-4001-fix.patch b/0345-cmd-search-Rework-of-CVE-2023-4001-fix.patch new file mode 100644 index 00000000..068bc77b --- /dev/null +++ b/0345-cmd-search-Rework-of-CVE-2023-4001-fix.patch @@ -0,0 +1,182 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nicolas Frayer +Date: Thu, 16 May 2024 10:58:32 +0200 +Subject: [PATCH] cmd/search: Rework of CVE-2023-4001 fix + +The initial fix implemented a new flag that forces the grub cfg +stub to be located on the same disk as grub. This created several +issues such as RAID machines not being able to boot as their +partition names under grub were different from the partition where +grub is located. It also simply means that any machines with the +/boot partition located on a disk other than the one containing grub +won't boot. +This commit denies booting if the grub cfg stub is located on a USB +drive with a duplicated UUID (UUID being the same as the partition +containing the actual grub cfg stub) + +Signed-off-by: Nicolas Frayer +--- + grub-core/commands/search.c | 136 +++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 127 insertions(+), 9 deletions(-) + +diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c +index 94fe8b2872a1..c052cb098c36 100644 +--- a/grub-core/commands/search.c ++++ b/grub-core/commands/search.c +@@ -30,6 +30,8 @@ + #include + #include + #include ++#include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -54,6 +56,100 @@ struct search_ctx + int is_cache; + }; + ++static int ++is_device_usb (const char *name) ++{ ++ int ret = 0; ++ ++ grub_device_t dev = grub_device_open(name); ++ ++ if (dev) ++ { ++ struct grub_efidisk_data ++ { ++ grub_efi_handle_t handle; ++ grub_efi_device_path_t *device_path; ++ grub_efi_device_path_t *last_device_path; ++ grub_efi_block_io_t *block_io; ++ struct grub_efidisk_data *next; ++ }; ++ ++ if (dev->disk && dev->disk->data) ++ { ++ struct grub_efidisk_data *dp = dev->disk->data; ++ ++ if ( GRUB_EFI_DEVICE_PATH_TYPE (dp->last_device_path) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE && ++ GRUB_EFI_DEVICE_PATH_SUBTYPE (dp->last_device_path) == GRUB_EFI_USB_DEVICE_PATH_SUBTYPE) ++ { ++ ret = 1; ++ } ++ } ++ grub_device_close(dev); ++ } ++ ++ return ret; ++} ++ ++static int ++get_device_uuid(const char *name, char** quid) ++{ ++ int ret = 0; ++ ++ grub_device_t dev_part = grub_device_open(name); ++ ++ if (dev_part) ++ { ++ grub_fs_t fs; ++ ++ fs = grub_fs_probe (dev_part); ++ ++#ifdef DO_SEARCH_FS_UUID ++#define read_fn fs_uuid ++#else ++#define read_fn fs_label ++#endif ++ if (fs && fs->read_fn) ++ { ++ fs->read_fn (dev_part, quid); ++ ++ if (grub_errno == GRUB_ERR_NONE && *quid) ++ { ++ ret = 1; ++ } ++ ++ } ++ grub_device_close (dev_part); ++ } ++ ++ return ret; ++} ++struct uuid_context { ++ char* name; ++ char* uuid; ++}; ++ ++static int ++check_for_duplicate (const char *name, void *data) ++{ ++ int ret = 0; ++ struct uuid_context * uuid_ctx = (struct uuid_context *)data; ++ char *quid = 0; ++ ++ get_device_uuid(name, &quid); ++ ++ if (quid == NULL) ++ return 0; ++ ++ if (!grub_strcasecmp(quid, uuid_ctx->uuid) && grub_strcasecmp(name, uuid_ctx->name)) ++ { ++ ret = 1; ++ } ++ ++ grub_free(quid); ++ ++ return ret; ++} ++ + /* Helper for FUNC_NAME. */ + static int + iterate_device (const char *name, void *data) +@@ -104,15 +200,37 @@ iterate_device (const char *name, void *data) + grub_str_sep (root_dev, root_disk, ',', rem_1); + grub_str_sep (name, name_disk, ',', rem_2); + if (root_disk != NULL && *root_disk != '\0' && +- name_disk != NULL && *name_disk != '\0') +- if (grub_strcmp(root_disk, name_disk) != 0) +- { +- grub_free (root_disk); +- grub_free (name_disk); +- grub_free (rem_1); +- grub_free (rem_2); +- return 0; +- } ++ name_disk != NULL && *name_disk != '\0') ++ { ++ grub_device_t dev, dev_part; ++ ++ if (is_device_usb(name) && !is_device_usb(root_dev)) ++ { ++ char *quid_name = NULL; ++ int longlist = 0; ++ struct uuid_context uuid_ctx; ++ int ret = 0; ++ ++ get_device_uuid(name, &quid_name); ++ if (!grub_strcmp(quid_name, ctx->key)) ++ { ++ uuid_ctx.name = name; ++ uuid_ctx.uuid = quid_name; ++ ++ ret = grub_device_iterate (check_for_duplicate, &uuid_ctx); ++ ++ if (ret) ++ { ++ grub_printf("Duplicated media UUID found, rebooting ...\n"); ++ grub_sleep(10); ++ grub_reboot(); ++ } ++ } ++ ++ if (quid_name) grub_free (quid_name); ++ ++ } ++ } + } + grub_free (root_disk); + grub_free (name_disk); diff --git a/grub.patches b/grub.patches index 98bdc3b1..ba10b274 100644 --- a/grub.patches +++ b/grub.patches @@ -342,3 +342,4 @@ Patch0341: 0341-grub_dl_set_mem_attrs-fix-format-string.patch Patch0342: 0342-grub_dl_set_mem_attrs-add-self-check-for-the-tramp-G.patch Patch0343: 0343-grub_dl_load_segments-page-align-the-tramp-GOT-areas.patch Patch0344: 0344-grub-install-on-EFI-if-forced.patch +Patch0345: 0345-cmd-search-Rework-of-CVE-2023-4001-fix.patch diff --git a/grub2.spec b/grub2.spec index d61257fc..a2f1d984 100644 --- a/grub2.spec +++ b/grub2.spec @@ -16,7 +16,7 @@ Name: grub2 Epoch: 1 Version: 2.06 -Release: 78%{?dist} +Release: 79%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -533,6 +533,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Tue May 28 2024 Nicolas Frayer - 2.06-79 +- cmd/search: Rework of CVE-2023-4001 fix +- Resolves: #RHEL-36249 +- Resolves: #RHEL-36186 + * Thu Feb 22 2024 Nicolas Frayer - 2.06-78 - util: grub-install on EFI if forced - Resolves: #RHEL-20443