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

Related: #2224951
Resolved: #2263369
Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
This commit is contained in:
Nicolas Frayer 2024-05-23 10:58:35 +02:00
parent 434cc479bc
commit 92efc5d3cd
3 changed files with 190 additions and 4 deletions

View file

@ -0,0 +1,180 @@
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 | 134 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 126 insertions(+), 8 deletions(-)
diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
index 4735feefcde5..5956b39dca72 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)
@@ -106,14 +202,36 @@ iterate_device (const char *name, void *data)
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;
- }
+ {
+ 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

@ -358,3 +358,4 @@ Patch0357: 0357-fs-ntfs-Fix-an-OOB-read-when-parsing-bitmaps-for-ind.patch
Patch0358: 0358-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch Patch0358: 0358-fs-ntfs-Fix-an-OOB-read-when-parsing-a-volume-label.patch
Patch0359: 0359-fs-ntfs-Make-code-more-readable.patch Patch0359: 0359-fs-ntfs-Make-code-more-readable.patch
Patch0360: 0360-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch Patch0360: 0360-fs-xfs-Handle-non-continuous-data-blocks-in-director.patch
Patch0361: 0361-cmd-search-Rework-of-CVE-2023-4001-fix.patch

View file

@ -17,7 +17,7 @@
Name: grub2 Name: grub2
Epoch: 1 Epoch: 1
Version: 2.06 Version: 2.06
Release: 121%{?dist} Release: 122%{?dist}
Summary: Bootloader with support for Linux, Multiboot and more Summary: Bootloader with support for Linux, Multiboot and more
License: GPL-3.0-or-later License: GPL-3.0-or-later
URL: http://www.gnu.org/software/grub/ URL: http://www.gnu.org/software/grub/
@ -359,9 +359,11 @@ fi
if test ! -f ${EFI_HOME}/grub.cfg; then if test ! -f ${EFI_HOME}/grub.cfg; then
# there's no config in ESP, create one # there's no config in ESP, create one
grub2-mkconfig -o ${EFI_HOME}/grub.cfg grub2-mkconfig -o ${EFI_HOME}/grub.cfg
cp -a ${EFI_HOME}/grub.cfg ${EFI_HOME}/grub.cfg.rpmsave
cp -a ${EFI_HOME}/grub.cfg ${GRUB_HOME}/
fi fi
if ((grep -q "configfile" ${EFI_HOME}/grub.cfg || grep -q "source" ${EFI_HOME}/grub.cfg) && ! grep -q "# It is automatically generated by grub2-mkconfig using templates" ${EFI_HOME}/grub.cfg); then if (((grep -q "configfile" ${EFI_HOME}/grub.cfg && grep -q "root-dev-only" ${EFI_HOME}/grub.cfg) || grep -q "source" ${EFI_HOME}/grub.cfg) && ! grep -q "# It is automatically generated by grub2-mkconfig using templates" ${EFI_HOME}/grub.cfg); then
exit 0 #Already unified exit 0 #Already unified
fi fi
@ -381,8 +383,6 @@ if test -f ${EFI_HOME}/grubenv; then
mv --force ${EFI_HOME}/grubenv ${GRUB_HOME}/grubenv mv --force ${EFI_HOME}/grubenv ${GRUB_HOME}/grubenv
fi fi
cp -a ${EFI_HOME}/grub.cfg ${EFI_HOME}/grub.cfg.rpmsave
cp -a ${EFI_HOME}/grub.cfg ${GRUB_HOME}/
mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
%files common -f grub.lang %files common -f grub.lang
@ -555,6 +555,11 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
%endif %endif
%changelog %changelog
* Thu May 23 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-122
- cmd/search: Rework of CVE-2023-4001 fix
- Related: #2224951
- Resolved: #2263369
* Fri Apr 12 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-121 * Fri Apr 12 2024 Nicolas Frayer <nfrayer@redhat.com> - 2.06-121
- fs/xfs: Handle non-continuous data blocks in directory extents - fs/xfs: Handle non-continuous data blocks in directory extents
- Related: #2254370 - Related: #2254370