cmd/search: Rework of CVE-2023-4001 fix

Resolves: #RHEL-36249
Resolves: #RHEL-36186
Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
This commit is contained in:
Nicolas Frayer 2024-05-28 12:13:38 +02:00
parent 6c0546793a
commit e4e452562c
3 changed files with 189 additions and 1 deletions

View File

@ -0,0 +1,182 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nicolas Frayer <nfrayer@redhat.com>
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 <nfrayer@redhat.com>
---
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 <grub/i18n.h>
#include <grub/disk.h>
#include <grub/partition.h>
+#include <grub/efi/api.h>
+#include <grub/time.h>
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);

View File

@ -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

View File

@ -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 <nfrayer@redhat.com> - 2.06-79
- cmd/search: Rework of CVE-2023-4001 fix
- Resolves: #RHEL-36249
- Resolves: #RHEL-36186
* Thu Feb 22 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-78
- util: grub-install on EFI if forced
- Resolves: #RHEL-20443