Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

partitions: mac: fix handling of bogus partition table

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>

authored by

Jann Horn and committed by
Jens Axboe
80e64804 1f47ed29

+15 -3
+15 -3
block/partitions/mac.c
··· 53 53 } 54 54 secsize = be16_to_cpu(md->block_size); 55 55 put_dev_sector(sect); 56 + 57 + /* 58 + * If the "block size" is not a power of 2, things get weird - we might 59 + * end up with a partition straddling a sector boundary, so we wouldn't 60 + * be able to read a partition entry with read_part_sector(). 61 + * Real block sizes are probably (?) powers of two, so just require 62 + * that. 63 + */ 64 + if (!is_power_of_2(secsize)) 65 + return -1; 56 66 datasize = round_down(secsize, 512); 57 67 data = read_part_sector(state, datasize / 512, &sect); 58 68 if (!data) 59 69 return -1; 60 70 partoffset = secsize % 512; 61 - if (partoffset + sizeof(*part) > datasize) 71 + if (partoffset + sizeof(*part) > datasize) { 72 + put_dev_sector(sect); 62 73 return -1; 74 + } 63 75 part = (struct mac_partition *) (data + partoffset); 64 76 if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { 65 77 put_dev_sector(sect); ··· 124 112 int i, l; 125 113 126 114 goodness++; 127 - l = strlen(part->name); 128 - if (strcmp(part->name, "/") == 0) 115 + l = strnlen(part->name, sizeof(part->name)); 116 + if (strncmp(part->name, "/", sizeof(part->name)) == 0) 129 117 goodness++; 130 118 for (i = 0; i <= l - 4; ++i) { 131 119 if (strncasecmp(part->name + i, "root",