grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Patch] Discard incorrect nested partitions (fixes #29956)


From: Grégoire Sutre
Subject: [Patch] Discard incorrect nested partitions (fixes #29956)
Date: Fri, 28 May 2010 02:49:59 +0200
User-agent: Thunderbird 2.0.0.23 (X11/20091027)

Hi,

Regarding the nested partition code, there is an implicit assumption
that each partition should be contained in its parent, i.e. its sectors
 should also be sectors of its parent.

This ``physical nesting'' is checked in grub_disk_read, but it would
be better to check it before that.

The attached patch discards partitions that are invalid w.r.t. physical
nesting.  This solves, in particular, a problem related to NetBSD (and
OpenBSD) disklabels.

With this patch, ``external'' partitions in a disklabel simply do not
show up as BSD partitions.  For instance (see bug #29956 for an image):

MBR Partition table:
0: NetBSD    start 32, size 1000
1: DOS       start 1040, size 1000

NetBSD Disklabel (stored in MBR partition 0)
5 partitions:
#        size    offset     fstype [fsize bsize cpg/sgs]
 a:      1000        32     4.2BSD
 c:      1000        32     unused
 d:      2048         0     unused
 e:      1000      1040      MSDOS


The e: partition is external: it is not contained in MBR NetBSD
partition.

Without the patch, we get:

$ grub-probe -m /dev/null -t drive -d /dev/rvnd0e
(/dev/rvnd0d,1,5)   # this is (/dev/rvnd0d,msdos1,bsd5)
$ grub-probe -m /dev/null -t fs -d /dev/rvnd0e
grub-probe: error: unknown filesystem.

With the patch, we get:

niagara# grub-probe -m /dev/null -t drive -d /dev/rvnd0e
(/dev/rvnd0d,2)   # this is (/dev/rvnd0d,msdos2)
niagara# grub-probe -m /dev/null -t fs -d /dev/rvnd0e
fat


The patch still accepts sub-partitions that start at the same
(absolute) offset as the parent.  For instance, in the above example,
ls -l in grub gives both (hd1,msdos1) and (hd1,msdos1,bsd1).  Should
we discard (hd0,msdos1,bsd1), i.e. require that sub-partitions start
at a strictly positive relative offset?

Grégoire

--- grub_trunk/kern/partition.c 2010-05-28 01:50:37.000000000 +0200
+++ grub_trunk_new/kern/partition.c     2010-05-28 01:53:13.000000000 +0200
@@ -16,32 +16,50 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <grub/misc.h>
 #include <grub/mm.h>
 #include <grub/partition.h>
 #include <grub/disk.h>
 
 grub_partition_map_t grub_partition_map_list;
 
+/*
+ * Checks that a partition is contained in its parent.
+ */
+static int
+grub_partition_validate (const grub_disk_t disk,
+                        const grub_partition_t partition)
+{
+  grub_disk_addr_t parent_len;
+
+  if (disk->partition)
+    parent_len = grub_partition_get_len (disk->partition);
+  else
+    parent_len = disk->total_sectors;
+
+  return (partition->start + partition->len <= parent_len);
+}
+
 static grub_partition_t
 grub_partition_map_probe (const grub_partition_map_t partmap,
                          grub_disk_t disk, int partnum)
 {
   grub_partition_t p = 0;
 
   auto int find_func (grub_disk_t d, const grub_partition_t partition);
 
-  int find_func (grub_disk_t d __attribute__ ((unused)),
+  int find_func (grub_disk_t dsk,
                 const grub_partition_t partition)
     {
-      if (partnum == partition->number)
+      if (partnum == partition->number &&
+         grub_partition_validate (dsk, partition))
        {
          p = (grub_partition_t) grub_malloc (sizeof (*p));
          if (! p)
            return 1;
 
          grub_memcpy (p, partition, sizeof (*p));
          return 1;
        }
 
       return 0;
@@ -131,20 +149,24 @@ grub_partition_iterate (struct grub_disk
                                     const grub_partition_t partition))
 {
   int ret = 0;
 
   auto int part_iterate (grub_disk_t dsk, const grub_partition_t p);
 
   int part_iterate (grub_disk_t dsk,
                    const grub_partition_t partition)
     {
       struct grub_partition p = *partition;
+
+      if (!(grub_partition_validate (dsk, partition)))
+       return 0;
+
       p.parent = dsk->partition;
       dsk->partition = 0;
       if (hook (dsk, &p))
        {
          ret = 1;
          return 1;
        }
       if (p.start != 0)
        {
          const struct grub_partition_map *partmap;
--- grub_trunk/partmap/bsdlabel.c       2010-05-28 01:50:39.000000000 +0200
+++ grub_trunk_new/partmap/bsdlabel.c   2010-05-28 02:10:26.000000000 +0200
@@ -47,39 +47,46 @@ bsdlabel_partition_map_iterate (grub_dis
 
   /* Check if it is valid.  */
   if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
     return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
 
   pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
     * GRUB_DISK_SECTOR_SIZE;
 
   for (p.number = 0;
        p.number < grub_cpu_to_le16 (label.num_partitions);
-       p.number++)
+       p.number++, pos += sizeof (struct grub_partition_bsd_entry))
     {
       struct grub_partition_bsd_entry be;
 
       p.offset = pos / GRUB_DISK_SECTOR_SIZE;
       p.index = pos % GRUB_DISK_SECTOR_SIZE;
 
       if (grub_disk_read (disk, p.offset, p.index, sizeof (be),  &be))
        return grub_errno;
 
-      p.start = grub_le_to_cpu32 (be.offset) - delta;
+      p.start = grub_le_to_cpu32 (be.offset);
+      if (p.start < delta)
+       continue;
+      p.start -= delta;
       p.len = grub_le_to_cpu32 (be.size);
       p.partmap = &grub_bsdlabel_partition_map;
 
+      grub_dprintf ("partition",
+                   "partition %d: type 0x%x, start 0x%llx, len 0x%llx\n",
+                   p.number, be.fs_type,
+                   (unsigned long long) p.start,
+                   (unsigned long long) p.len);
+
       if (be.fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED)
        if (hook (disk, &p))
          return grub_errno;
-
-      pos += sizeof (struct grub_partition_bsd_entry);
     }
 
   return GRUB_ERR_NONE;
 }
 
 
 /* Partition map type.  */
 static struct grub_partition_map grub_bsdlabel_partition_map =
   {
     .name = "bsd",

reply via email to

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