Skip to content

Commit 9e57d0e

Browse files
nfrayerSergiiDmytruk
authored andcommitted
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>
1 parent dc790eb commit 9e57d0e

File tree

1 file changed

+126
-8
lines changed

1 file changed

+126
-8
lines changed

grub-core/commands/search.c

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include <grub/i18n.h>
3131
#include <grub/disk.h>
3232
#include <grub/partition.h>
33+
#include <grub/efi/api.h>
34+
#include <grub/time.h>
3335

3436
GRUB_MOD_LICENSE ("GPLv3+");
3537

@@ -54,6 +56,100 @@ struct search_ctx
5456
int is_cache;
5557
};
5658

59+
static int
60+
is_device_usb (const char *name)
61+
{
62+
int ret = 0;
63+
64+
grub_device_t dev = grub_device_open(name);
65+
66+
if (dev)
67+
{
68+
struct grub_efidisk_data
69+
{
70+
grub_efi_handle_t handle;
71+
grub_efi_device_path_t *device_path;
72+
grub_efi_device_path_t *last_device_path;
73+
grub_efi_block_io_t *block_io;
74+
struct grub_efidisk_data *next;
75+
};
76+
77+
if (dev->disk && dev->disk->data)
78+
{
79+
struct grub_efidisk_data *dp = dev->disk->data;
80+
81+
if ( GRUB_EFI_DEVICE_PATH_TYPE (dp->last_device_path) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE &&
82+
GRUB_EFI_DEVICE_PATH_SUBTYPE (dp->last_device_path) == GRUB_EFI_USB_DEVICE_PATH_SUBTYPE)
83+
{
84+
ret = 1;
85+
}
86+
}
87+
grub_device_close(dev);
88+
}
89+
90+
return ret;
91+
}
92+
93+
static int
94+
get_device_uuid(const char *name, char** quid)
95+
{
96+
int ret = 0;
97+
98+
grub_device_t dev_part = grub_device_open(name);
99+
100+
if (dev_part)
101+
{
102+
grub_fs_t fs;
103+
104+
fs = grub_fs_probe (dev_part);
105+
106+
#ifdef DO_SEARCH_FS_UUID
107+
#define read_fn fs_uuid
108+
#else
109+
#define read_fn fs_label
110+
#endif
111+
if (fs && fs->read_fn)
112+
{
113+
fs->read_fn (dev_part, quid);
114+
115+
if (grub_errno == GRUB_ERR_NONE && *quid)
116+
{
117+
ret = 1;
118+
}
119+
120+
}
121+
grub_device_close (dev_part);
122+
}
123+
124+
return ret;
125+
}
126+
struct uuid_context {
127+
char* name;
128+
char* uuid;
129+
};
130+
131+
static int
132+
check_for_duplicate (const char *name, void *data)
133+
{
134+
int ret = 0;
135+
struct uuid_context * uuid_ctx = (struct uuid_context *)data;
136+
char *quid = 0;
137+
138+
get_device_uuid(name, &quid);
139+
140+
if (quid == NULL)
141+
return 0;
142+
143+
if (!grub_strcasecmp(quid, uuid_ctx->uuid) && grub_strcasecmp(name, uuid_ctx->name))
144+
{
145+
ret = 1;
146+
}
147+
148+
grub_free(quid);
149+
150+
return ret;
151+
}
152+
57153
/* Helper for FUNC_NAME. */
58154
static int
59155
iterate_device (const char *name, void *data)
@@ -106,14 +202,36 @@ iterate_device (const char *name, void *data)
106202
grub_str_sep (name, name_disk, ',', rem_2);
107203
if (root_disk != NULL && *root_disk != '\0' &&
108204
name_disk != NULL && *name_disk != '\0')
109-
if (grub_strcmp(root_disk, name_disk) != 0)
110-
{
111-
grub_free (root_disk);
112-
grub_free (name_disk);
113-
grub_free (rem_1);
114-
grub_free (rem_2);
115-
return 0;
116-
}
205+
{
206+
grub_device_t dev, dev_part;
207+
208+
if (is_device_usb(name) && !is_device_usb(root_dev))
209+
{
210+
char *quid_name = NULL;
211+
int longlist = 0;
212+
struct uuid_context uuid_ctx;
213+
int ret = 0;
214+
215+
get_device_uuid(name, &quid_name);
216+
if (!grub_strcmp(quid_name, ctx->key))
217+
{
218+
uuid_ctx.name = name;
219+
uuid_ctx.uuid = quid_name;
220+
221+
ret = grub_device_iterate (check_for_duplicate, &uuid_ctx);
222+
223+
if (ret)
224+
{
225+
grub_printf("Duplicated media UUID found, rebooting ...\n");
226+
grub_sleep(10);
227+
grub_reboot();
228+
}
229+
}
230+
231+
if (quid_name) grub_free (quid_name);
232+
233+
}
234+
}
117235
}
118236
grub_free (root_disk);
119237
grub_free (name_disk);

0 commit comments

Comments
 (0)