[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Fix md RAID enumeration
From: |
Kees Cook |
Subject: |
[PATCH] Fix md RAID enumeration |
Date: |
Sat, 16 Jan 2021 09:27:28 -0800 |
In addition to the prior patch to avoid leaving holes in the returned
devicelist, the enumeration logic also needed fixing. GET_ARRAY_INFO's
info.nr_disks does not map to GET_DISK_INFO's disk.number, which is an
internal kernel index. If an array has had drives added, removed, etc,
there may be gaps in GET_DISK_INFO's results. Instead, do what mdadm does
and keep scanning until we find enough valid (major/minor != 0) disks.
Fixes: 2b00217369ac ("... Added support for RAID and LVM")
Fixes: https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1912043
Fixes: https://savannah.gnu.org/bugs/index.php?59887
Signed-off-by: Kees Cook <kees@ubuntu.com>
(This is intended to be applied on top of the earlier patch sent in
https://lists.gnu.org/archive/html/grub-devel/2021-01/msg00027.html)
Index: grub2-2.04/grub-core/osdep/linux/getroot.c
===================================================================
--- grub2-2.04.orig/grub-core/osdep/linux/getroot.c
+++ grub2-2.04/grub-core/osdep/linux/getroot.c
@@ -135,10 +135,18 @@ struct mountinfo_entry
char fstype[ESCAPED_PATH_MAX + 1], device[ESCAPED_PATH_MAX + 1];
};
+/* GET_ARRAY_INFO's info.nr_disks does not map to GET_DISK_INFO's
+ disk.number, which is an internal kernel index. Instead, do what mdadm
+ does and keep scanning until we find enough valid disks. The limit is
+ copied from there, which notes that it is sufficiently high given
+ that the on-disk metadata for v1.x can only support 1920. */
+#define MD_MAX_DISKS 4096
+
static char **
grub_util_raid_getmembers (const char *name, int bootable)
{
int fd, ret, i, j;
+ int remaining;
char **devicelist;
mdu_version_t version;
mdu_array_info_t info;
@@ -170,12 +178,17 @@ grub_util_raid_getmembers (const char *n
devicelist = xcalloc (info.nr_disks + 1, sizeof (char *));
- for (i = 0, j = 0; i < info.nr_disks; i++)
+ remaining = info.nr_disks;
+ for (i = 0, j = 0; i < MD_MAX_DISKS && remaining > 0; i++)
{
disk.number = i;
ret = ioctl (fd, GET_DISK_INFO, &disk);
if (ret != 0)
grub_util_error (_("ioctl GET_DISK_INFO error: %s"), strerror (errno));
+ /* Skip empty disk slot. */
+ if (disk.major == 0 && disk.minor == 0)
+ continue;
+ remaining--;
if (disk.state & (1 << MD_DISK_REMOVED))
continue;
--
Kees Cook @outflux.net
- [PATCH] Fix md RAID enumeration,
Kees Cook <=