Commit bbb361fc authored by Jann Horn's avatar Jann Horn Committed by Long Li
Browse files

partitions: mac: fix handling of bogus partition table

mainline inclusion
from mainline-v6.10-rc2
commit 80e648042e512d5a767da251d44132553fe04ae0
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBPC5K
CVE: CVE-2025-21772

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=80e648042e512d5a767da251d44132553fe04ae0



--------------------------------

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: default avatarJann Horn <jannh@google.com>
Link: https://lore.kernel.org/r/20250214-partition-mac-v1-1-c1c626dffbd5@google.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarLong Li <leo.lilong@huawei.com>
parent 3e8e3ea7
Loading
Loading
Loading
Loading
+15 −3
Original line number Original line Diff line number Diff line
@@ -51,13 +51,25 @@ int mac_partition(struct parsed_partitions *state)
	}
	}
	secsize = be16_to_cpu(md->block_size);
	secsize = be16_to_cpu(md->block_size);
	put_dev_sector(sect);
	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);
	datasize = round_down(secsize, 512);
	data = read_part_sector(state, datasize / 512, &sect);
	data = read_part_sector(state, datasize / 512, &sect);
	if (!data)
	if (!data)
		return -1;
		return -1;
	partoffset = secsize % 512;
	partoffset = secsize % 512;
	if (partoffset + sizeof(*part) > datasize)
	if (partoffset + sizeof(*part) > datasize) {
		put_dev_sector(sect);
		return -1;
		return -1;
	}
	part = (struct mac_partition *) (data + partoffset);
	part = (struct mac_partition *) (data + partoffset);
	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
		put_dev_sector(sect);
		put_dev_sector(sect);
@@ -110,8 +122,8 @@ int mac_partition(struct parsed_partitions *state)
				int i, l;
				int i, l;


				goodness++;
				goodness++;
				l = strlen(part->name);
				l = strnlen(part->name, sizeof(part->name));
				if (strcmp(part->name, "/") == 0)
				if (strncmp(part->name, "/", sizeof(part->name)) == 0)
					goodness++;
					goodness++;
				for (i = 0; i <= l - 4; ++i) {
				for (i = 0; i <= l - 4; ++i) {
					if (strncasecmp(part->name + i, "root",
					if (strncasecmp(part->name + i, "root",