linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report
       [not found] <20260916135822.32584-1-me@fxti.xyz>
@ 2026-09-16 13:58 ` ZHOU Jiaxiang
  2026-09-17  2:28   ` Martin K. Petersen (Oracle)
  2026-09-17  2:49   ` Damien Le Moal
  2026-09-16 13:58 ` [PATCH v4 2/2] scsi: sd_zbc: reject disks with too many zones ZHOU Jiaxiang
  1 sibling, 2 replies; 5+ messages in thread
From: ZHOU Jiaxiang @ 2026-09-16 13:58 UTC (permalink / raw)
  To: Damien Le Moal, Jens Axboe; +Cc: linux-block, Martin K . Petersen, linux-scsi

blk_revalidate_disk_zones() sizes the zones_cond array from the disk
capacity and zone size, but the index used by blk_revalidate_zone_cond()
comes from the device-driven report_zones() walk and is never checked
against the array size. A device reporting more zones than fit the
array makes blk_zone_set_cond() write out of bounds.

One way to reach this is a zone count exceeding 32 bits: both
blk_revalidate_zone_args.nr_zones and struct zoned_disk_info.nr_zones
are unsigned int, so a disk advertising more than UINT_MAX zones (e.g.
2^32 + 1024 zones of one 512-byte logical block) gets its zone count
truncated to a small value, undersizing the array while the report
walk keeps counting upward.

Check the index against the array size before storing the zone
condition, and refuse to revalidate when the zone count does not fit
32 bits.

Fixes: 6e945ffb6555 ("block: use zone condition to determine conventional zones")
Signed-off-by: ZHOU Jiaxiang <me@fxti.xyz>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
---
 block/blk-zoned.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index a5afb842b..475aa16bc 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -2018,12 +2018,17 @@ static int disk_revalidate_zone_resources(struct gendisk *disk,
 				struct blk_revalidate_zone_args *args)
 {
 	struct queue_limits *lim = &disk->queue->limits;
+	unsigned long long nr_zones;
 	unsigned int pool_size;
 	int ret = 0;
 
 	args->disk = disk;
-	args->nr_zones =
-		DIV_ROUND_UP_ULL(get_capacity(disk), lim->chunk_sectors);
+	nr_zones = DIV_ROUND_UP_ULL(get_capacity(disk), lim->chunk_sectors);
+	if (nr_zones > UINT_MAX) {
+		pr_warn("%s: Too many zones (%llu)\n", disk->disk_name, nr_zones);
+		return -EINVAL;
+	}
+	args->nr_zones = nr_zones;
 
 	/* Cached zone conditions: 1 byte per zone */
 	args->zones_cond = kzalloc(args->nr_zones, GFP_NOIO);
@@ -2131,6 +2136,12 @@ static int blk_revalidate_zone_cond(struct blk_zone *zone, unsigned int idx,
 {
 	enum blk_zone_cond cond = zone->cond;
 
+	if (idx >= args->nr_zones) {
+		pr_warn("%s: Zone report index %u exceeds zone count %u\n",
+			args->disk->disk_name, idx, args->nr_zones);
+		return -EINVAL;
+	}
+
 	/* Check that the zone condition is consistent with the zone type. */
 	switch (cond) {
 	case BLK_ZONE_COND_NOT_WP:
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v4 2/2] scsi: sd_zbc: reject disks with too many zones
       [not found] <20260916135822.32584-1-me@fxti.xyz>
  2026-09-16 13:58 ` [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report ZHOU Jiaxiang
@ 2026-09-16 13:58 ` ZHOU Jiaxiang
  1 sibling, 0 replies; 5+ messages in thread
From: ZHOU Jiaxiang @ 2026-09-16 13:58 UTC (permalink / raw)
  To: Damien Le Moal, Jens Axboe; +Cc: linux-block, Martin K . Petersen, linux-scsi

sd_zbc_read_zones() computes the number of zones with 64-bit
arithmetic and stores the result in the unsigned int nr_zones field
of struct zoned_disk_info, silently truncating counts that exceed 32
bits. The truncated count is later used to size per-zone resources,
while the device may still report more zones than fit.

Moreover, sd_zbc_report_zones() counts the reported zones with a
signed int zone_idx, which overflows past INT_MAX. Reject devices
reporting more than INT_MAX zones at scan time; such a device is not
realistic for any medium that exists today, and accepting it produces
inconsistent zone bookkeeping.

Fixes: 89d947561077 ("sd: Implement support for ZBC devices")
Signed-off-by: ZHOU Jiaxiang <me@fxti.xyz>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
---
 drivers/scsi/sd_zbc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 56e455fb5..456beaf2e 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -589,7 +589,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
 int sd_zbc_read_zones(struct scsi_disk *sdkp, struct queue_limits *lim,
 		u8 buf[SD_BUF_SIZE])
 {
-	unsigned int nr_zones;
+	u64 nr_zones;
 	u32 zone_blocks = 0;
 	int ret;
 
@@ -621,6 +621,12 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, struct queue_limits *lim,
 		goto err;
 
 	nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks);
+	if (nr_zones > INT_MAX) {
+		sd_printk(KERN_ERR, sdkp, "Too many zones (%llu)\n",
+			  nr_zones);
+		ret = -EINVAL;
+		goto err;
+	}
 	sdkp->early_zone_info.nr_zones = nr_zones;
 	sdkp->early_zone_info.zone_blocks = zone_blocks;
 
-- 
2.50.1 (Apple Git-155)


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report
  2026-09-16 13:58 ` [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report ZHOU Jiaxiang
@ 2026-09-17  2:28   ` Martin K. Petersen (Oracle)
  2026-09-17  2:50     ` Damien Le Moal
  2026-09-17  2:49   ` Damien Le Moal
  1 sibling, 1 reply; 5+ messages in thread
From: Martin K. Petersen (Oracle) @ 2026-09-17  2:28 UTC (permalink / raw)
  To: Damien Le Moal, Jens Axboe, ZHOU Jiaxiang
  Cc: Martin K . Petersen, linux-block, linux-scsi

On Wed, 16 Sep 2026 21:58:21 +0800, ZHOU Jiaxiang wrote:

> blk_revalidate_disk_zones() sizes the zones_cond array from the disk
> capacity and zone size, but the index used by blk_revalidate_zone_cond()
> comes from the device-driven report_zones() walk and is never checked
> against the array size. A device reporting more zones than fit the
> array makes blk_zone_set_cond() write out of bounds.
> 
> One way to reach this is a zone count exceeding 32 bits: both
> blk_revalidate_zone_args.nr_zones and struct zoned_disk_info.nr_zones
> are unsigned int, so a disk advertising more than UINT_MAX zones (e.g.
> 2^32 + 1024 zones of one 512-byte logical block) gets its zone count
> truncated to a small value, undersizing the array while the report
> walk keeps counting upward.
> 
> [...]

Applied to 7.3/scsi-fixes, thanks!

[1/2] block: fix zones_cond out-of-bounds write on zone report
      https://git.kernel.org/mkp/scsi/c/7c431d61b69a
[2/2] scsi: sd_zbc: reject disks with too many zones
      https://git.kernel.org/mkp/scsi/c/b6ec0f797459

-- 
Martin K. Petersen

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report
  2026-09-16 13:58 ` [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report ZHOU Jiaxiang
  2026-09-17  2:28   ` Martin K. Petersen (Oracle)
@ 2026-09-17  2:49   ` Damien Le Moal
  1 sibling, 0 replies; 5+ messages in thread
From: Damien Le Moal @ 2026-09-17  2:49 UTC (permalink / raw)
  To: ZHOU Jiaxiang, Jens Axboe; +Cc: linux-block, Martin K . Petersen, linux-scsi

On 2026/09/16 20:58, ZHOU Jiaxiang wrote:
> blk_revalidate_disk_zones() sizes the zones_cond array from the disk
> capacity and zone size, but the index used by blk_revalidate_zone_cond()
> comes from the device-driven report_zones() walk and is never checked
> against the array size. A device reporting more zones than fit the
> array makes blk_zone_set_cond() write out of bounds.
> 
> One way to reach this is a zone count exceeding 32 bits: both
> blk_revalidate_zone_args.nr_zones and struct zoned_disk_info.nr_zones
> are unsigned int, so a disk advertising more than UINT_MAX zones (e.g.
> 2^32 + 1024 zones of one 512-byte logical block) gets its zone count
> truncated to a small value, undersizing the array while the report
> walk keeps counting upward.
> 
> Check the index against the array size before storing the zone
> condition, and refuse to revalidate when the zone count does not fit
> 32 bits.
> 
> Fixes: 6e945ffb6555 ("block: use zone condition to determine conventional zones")
> Signed-off-by: ZHOU Jiaxiang <me@fxti.xyz>
> Reviewed-by: Damien Le Moal <dlemoal@kernel.org>

This review stands if this is applied as a fix to the current code. However,
applying this will create a conflict with the changes in this area that are
queued in block/for-bext.

Jens,

How do you want to proceed? Applying this as a fix and do a rebase of
block/for-next? Or rebase this on block/for-next ?

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report
  2026-09-17  2:28   ` Martin K. Petersen (Oracle)
@ 2026-09-17  2:50     ` Damien Le Moal
  0 siblings, 0 replies; 5+ messages in thread
From: Damien Le Moal @ 2026-09-17  2:50 UTC (permalink / raw)
  To: Martin K. Petersen (Oracle), Jens Axboe, ZHOU Jiaxiang
  Cc: linux-block, linux-scsi

On 2026/09/17 9:28, Martin K. Petersen (Oracle) wrote:
> On Wed, 16 Sep 2026 21:58:21 +0800, ZHOU Jiaxiang wrote:
> 
>> blk_revalidate_disk_zones() sizes the zones_cond array from the disk
>> capacity and zone size, but the index used by blk_revalidate_zone_cond()
>> comes from the device-driven report_zones() walk and is never checked
>> against the array size. A device reporting more zones than fit the
>> array makes blk_zone_set_cond() write out of bounds.
>>
>> One way to reach this is a zone count exceeding 32 bits: both
>> blk_revalidate_zone_args.nr_zones and struct zoned_disk_info.nr_zones
>> are unsigned int, so a disk advertising more than UINT_MAX zones (e.g.
>> 2^32 + 1024 zones of one 512-byte logical block) gets its zone count
>> truncated to a small value, undersizing the array while the report
>> walk keeps counting upward.
>>
>> [...]
> 
> Applied to 7.3/scsi-fixes, thanks!
> 
> [1/2] block: fix zones_cond out-of-bounds write on zone report
>       https://git.kernel.org/mkp/scsi/c/7c431d61b69a
> [2/2] scsi: sd_zbc: reject disks with too many zones
>       https://git.kernel.org/mkp/scsi/c/b6ec0f797459
> 

I just asked about this :)
We will have a conflict in Linux-next with this unless Jens does a rebase of
block/for-next.

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-17  2:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260916135822.32584-1-me@fxti.xyz>
2026-09-16 13:58 ` [PATCH v4 1/2] block: fix zones_cond out-of-bounds write on zone report ZHOU Jiaxiang
2026-09-17  2:28   ` Martin K. Petersen (Oracle)
2026-09-17  2:50     ` Damien Le Moal
2026-09-17  2:49   ` Damien Le Moal
2026-09-16 13:58 ` [PATCH v4 2/2] scsi: sd_zbc: reject disks with too many zones ZHOU Jiaxiang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).