]> www.infradead.org Git - nvme.git/commitdiff
partitions: mac: fix handling of bogus partition table
authorJann Horn <jannh@google.com>
Fri, 14 Feb 2025 01:39:50 +0000 (02:39 +0100)
committerJens Axboe <axboe@kernel.dk>
Fri, 14 Feb 2025 15:38:28 +0000 (08:38 -0700)
Fix several issues in partition probing:

 - The bailout for a bad partoffset must use put_dev_sector(), since the
   preceding read_part_sector() succeeded.
 - If the partition table claims a silly sector size like 0xfff bytes
   (which results in partition table entries straddling sector boundaries),
   bail out instead of accessing out-of-bounds memory.
 - We must not assume that the partition table contains proper NUL
   termination - use strnlen() and strncmp() instead of strlen() and
   strcmp().

Cc: stable@vger.kernel.org
Signed-off-by: Jann Horn <jannh@google.com>
Link: https://lore.kernel.org/r/20250214-partition-mac-v1-1-c1c626dffbd5@google.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/partitions/mac.c

index c80183156d68020e0e14974308ac751b3df84421..b02530d986297058de0db929fbf638a76fc44508 100644 (file)
@@ -53,13 +53,25 @@ int mac_partition(struct parsed_partitions *state)
        }
        secsize = be16_to_cpu(md->block_size);
        put_dev_sector(sect);
+
+       /*
+        * If the "block size" is not a power of 2, things get weird - we might
+        * end up with a partition straddling a sector boundary, so we wouldn't
+        * be able to read a partition entry with read_part_sector().
+        * Real block sizes are probably (?) powers of two, so just require
+        * that.
+        */
+       if (!is_power_of_2(secsize))
+               return -1;
        datasize = round_down(secsize, 512);
        data = read_part_sector(state, datasize / 512, &sect);
        if (!data)
                return -1;
        partoffset = secsize % 512;
-       if (partoffset + sizeof(*part) > datasize)
+       if (partoffset + sizeof(*part) > datasize) {
+               put_dev_sector(sect);
                return -1;
+       }
        part = (struct mac_partition *) (data + partoffset);
        if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
                put_dev_sector(sect);
@@ -112,8 +124,8 @@ int mac_partition(struct parsed_partitions *state)
                                int i, l;
 
                                goodness++;
-                               l = strlen(part->name);
-                               if (strcmp(part->name, "/") == 0)
+                               l = strnlen(part->name, sizeof(part->name));
+                               if (strncmp(part->name, "/", sizeof(part->name)) == 0)
                                        goodness++;
                                for (i = 0; i <= l - 4; ++i) {
                                        if (strncasecmp(part->name + i, "root",