grub-devel
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]