block: partitions: bound sysv68 slice table count
A message that is not in the archive (sent off-list or not yet received): [email protected]
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.
--- block/partitions/sysv68.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
block/partitions/sysv68.c +7 -4
@@ -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, §); + data =read_part_sector (state, slice_sector, §);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
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 trustsios_slccntfrom disk and walks that many entries after skipping the synthetic whole-disk slice. A crafted image can setios_slccntlarger 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")Reported-by Yuan Tan <[email protected]>Reported-by Zhengchuan Liang <[email protected]>Reported-by Xin Liu <[email protected]>Assisted-by Codex:GPT-5.4Signed-off-by Zhao Zhang <[email protected]>Signed-off-by Ren Wei <[email protected]>--- block/partitions/sysv68.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)block/partitions/sysv68.c +7
-4@@ -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, §); + data =read_part_sector (state, slice_sector, §);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