Skip to contentSkip to conversation

block: partitions: bound sysv68 slice table count

PATCH In review Ren Wei 2 participants 2 messages Jun 10 – Jun 16 1 message not in the archive Block layer

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Ren Wei

author
#1 lore raw

PATCH 1/1 block: partitions: bound sysv68 slice table count

From: Zhao Zhang <[email protected]>

sysv68_partition() reads a single sector for the slice table, but it trusts ios_slccnt from disk and walks that many entries after skipping the synthetic whole-disk slice. A crafted image can set ios_slccnt larger than the 64 struct slice records that fit in one sector and trigger an out-of-bounds read while scanning partitions.

Limit the slice count to the number of records that fit in the sector returned by read_part_sector(), then drop the whole-disk entry only when the bounded count is non-zero.

Fixes 19d0e8ce856a ("partition: add support for sysv68 partitions")
Assisted-by Codex:GPT-5.4
---
 block/partitions/sysv68.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
block/partitions/sysv68.c +7 -4
index 470e0f9de7be..5110ed83c541 100644
@@ -48,7 +48,8 @@ struct slice {
 
 int sysv68_partition(struct parsed_partitions *state)
 {
-	int i, slices;
+	sector_t slice_sector;
+	unsigned int i, slices;
 	int slot = 1;
 	Sector sect;
 	unsigned char *data;
@@ -65,14 +66,16 @@ int sysv68_partition(struct parsed_partitions *state)
 		return 0;
 	}
 	slices = be16_to_cpu(b->dk_ios.ios_slccnt);
-	i = be32_to_cpu(b->dk_ios.ios_slcblk);
+	slice_sector = be32_to_cpu(b->dk_ios.ios_slcblk);
 	put_dev_sector(sect);
 
-	data = read_part_sector(state, i, &sect);
+	data = read_part_sector(state, slice_sector, &sect);
 	if (!data)
 		return -1;
 
-	slices -= 1; /* last slice is the whole disk */
+	slices = min_t(unsigned int, slices, SECTOR_SIZE / sizeof(*slice));
+	if (slices)
+		slices -= 1; /* last slice is the whole disk */
 	seq_buf_printf(&state->pp_buf, "sysV68: %s(s%u)", state->name, slices);
 	slice = (struct slice *)data;
 	for (i = 0; i < slices; i++, slice++) {
Signature · 1 line
2.47.3
Reviewed-by on v1 1/1
#2 lore raw

Hi Ren Wei,

Quoted 60 lines · Ren Wei

From: Zhao Zhang <[email protected]>

sysv68_partition() reads a single sector for the slice table, but it trusts ios_slccnt from disk and walks that many entries after skipping the synthetic whole-disk slice. A crafted image can set ios_slccnt larger than the 64 struct slice records that fit in one sector and trigger an out-of-bounds read while scanning partitions.

Limit the slice count to the number of records that fit in the sector returned by read_part_sector(), then drop the whole-disk entry only when the bounded count is non-zero.

Fixes 19d0e8ce856a ("partition: add support for sysv68 partitions")
Assisted-by Codex:GPT-5.4
---
 block/partitions/sysv68.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
block/partitions/sysv68.c +7 -4
index 470e0f9de7be..5110ed83c541 100644
@@ -48,7 +48,8 @@ struct slice {
 
 int sysv68_partition(struct parsed_partitions *state)
 {
-	int i, slices;
+	sector_t slice_sector;
+	unsigned int i, slices;
 	int slot = 1;
 	Sector sect;
 	unsigned char *data;
@@ -65,14 +66,16 @@ int sysv68_partition(struct parsed_partitions *state)
 		return 0;
 	}
 	slices = be16_to_cpu(b->dk_ios.ios_slccnt);
-	i = be32_to_cpu(b->dk_ios.ios_slcblk);
+	slice_sector = be32_to_cpu(b->dk_ios.ios_slcblk);
 	put_dev_sector(sect);
 
-	data = read_part_sector(state, i, &sect);
+	data = read_part_sector(state, slice_sector, &sect);
 	if (!data)
 		return -1;
 
-	slices -= 1; /* last slice is the whole disk */
+	slices = min_t(unsigned int, slices, SECTOR_SIZE / sizeof(*slice));
+	if (slices)
+		slices -= 1; /* last slice is the whole disk */
 	seq_buf_printf(&state->pp_buf, "sysV68: %s(s%u)", state->name, slices);
 	slice = (struct slice *)data;
 	for (i = 0; i < slices; i++, slice++) {
Signature · 1 line
2.47.3

That does the job. IIRC 'last slice' had number 7, so ios_slccnt had to be
8. I do not have such a partition handy at the moment, so

Best regards

Philippe