From: Niklas Cassel <cassel@kernel.org>
To: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
"Martin K. Petersen" <mkp@kernel.org>
Cc: linux-scsi@vger.kernel.org, Damien Le Moal <dlemoal@kernel.org>,
John Garry <john.garry@linux.dev>,
Niklas Cassel <cassel@kernel.org>
Subject: [PATCH v11 06/13] scsi: scsi_debug: Avoid 32-bit overflow in WRITE SCATTERED offsets
Date: Tue, 29 Sep 2026 10:25:03 +0200 [thread overview]
Message-ID: <20260929082456.857423-21-cassel@kernel.org> (raw)
In-Reply-To: <20260929082456.857423-15-cassel@kernel.org>
resp_write_scat() computes the length of an LBA range in bytes as a
32-bit product, num_by = num * lb_size, and adds it to sg_off, the
32-bit offset of the next range in the data-out buffer. The product
wraps for a range of 4 GiB or more, which check_device_access_params()
allows once the store is that large, and sg_off wraps once the ranges
add up to 4 GiB, which neither their number nor their overlap prevents.
The ranges that follow are then written from the wrong offset in the
buffer.
Make num_by and sg_off 64-bit, and pass do_device_access() sg_off
capped at the length of the buffer. An offset at the end of the buffer
copies nothing, and sg_copy_buffer(), which takes it as an off_t, is
never given one larger than the buffer that it copies.
Assisted-by: LLM
Fixes: 481b5e5c7949 ("scsi: scsi_debug: add resp_write_scat function")
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
Tested with:
modprobe scsi_debug sector_size=512 dev_size_mb=128
issuing a WRITE SCATTERED (16) through SG_IO with 33 LBA range
descriptors: 32 of 262144 blocks at LBA 0, which add up to 4 GiB, and
one of 8 blocks at LBA 200000. The 9728 byte buffer holds the parameter
list and 16 blocks, so the first range consumes all of it. Before this
patch the offset wrapped, and the last range was written with the data
of the first; after it the last range is left as it was.
Changes since v10: sg_off is capped at the length of the buffer rather
than at U32_MAX, which becomes -1 as an off_t on 32-bit architectures,
and the commit message no longer claims that the store has to be 4 GiB.
---
drivers/scsi/scsi_debug.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 92458bf1568b..879746c2ed7d 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -5197,7 +5197,8 @@ static int resp_write_scat(struct scsi_cmnd *scp,
struct sdeb_store_info *sip = devip2sip(devip, true);
u8 wrprotect;
u16 lbdof, num_lrd, k;
- u32 num, num_by, bt_len, lbdof_blen, sg_off, cum_lb;
+ u32 num, bt_len, lbdof_blen, cum_lb;
+ u64 num_by, sg_off;
u32 lb_size = sdebug_sector_size;
u32 ei_lba;
u64 lba;
@@ -5273,14 +5274,14 @@ static int resp_write_scat(struct scsi_cmnd *scp,
num = get_unaligned_be32(up + 8);
if (sdebug_verbose)
sdev_printk(KERN_INFO, scp->device,
- "%s: k=%d LBA=0x%llx num=%u sg_off=%u\n",
+ "%s: k=%d LBA=0x%llx num=%u sg_off=%llu\n",
my_name, k, lba, num, sg_off);
if (num == 0)
continue;
ret = check_device_access_params(scp, lba, num, true);
if (ret)
goto err_out_unlock;
- num_by = num * lb_size;
+ num_by = (u64)num * lb_size;
ei_lba = is_16 ? 0 : get_unaligned_be32(up + 12);
if ((cum_lb + num) > bt_len) {
@@ -5311,7 +5312,9 @@ static int resp_write_scat(struct scsi_cmnd *scp,
* Write ranges atomically to keep as close to pre-atomic
* writes behaviour as possible.
*/
- ret = do_device_access(sip, scp, sg_off, lba, num, group, true, true);
+ ret = do_device_access(sip, scp,
+ min_t(u64, sg_off, scsi_bufflen(scp)),
+ lba, num, group, true, true);
/* If ZBC zone then bump its write pointer */
if (sdebug_dev_is_zoned(devip))
zbc_inc_wp(devip, lba, num);
@@ -5322,7 +5325,7 @@ static int resp_write_scat(struct scsi_cmnd *scp,
goto err_out_unlock;
} else if (unlikely(sdebug_verbose && (ret < num_by)))
sdev_printk(KERN_INFO, scp->device,
- "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
+ "%s: write: cdb indicated=%llu, IO sent=%d bytes\n",
my_name, num_by, ret);
if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) &&
--
2.55.0
next prev parent reply other threads:[~2026-09-29 8:26 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 8:24 [PATCH v11 00/13] scsi: scsi_debug: fix zoned write validation Niklas Cassel
2026-09-29 8:24 ` [PATCH v11 01/13] scsi: scsi_debug: Refuse a zoned device with a non-zero lowest aligned LBA Niklas Cassel
2026-09-29 8:24 ` [PATCH v11 02/13] scsi: scsi_debug: Make atomic writes and ZBC emulation mutually exclusive Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 03/13] scsi: scsi_debug: Refuse a negative physblk_exp Niklas Cassel
2026-09-29 13:34 ` Damien Le Moal
2026-09-29 8:25 ` [PATCH v11 04/13] scsi: scsi_debug: Take the zone metadata lock before the data lock Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 05/13] scsi: scsi_debug: Evaluate scsi_debug_lbp() only once Niklas Cassel
2026-09-29 8:25 ` Niklas Cassel [this message]
2026-09-29 13:39 ` [PATCH v11 06/13] scsi: scsi_debug: Avoid 32-bit overflow in WRITE SCATTERED offsets Damien Le Moal
2026-09-29 8:25 ` [PATCH v11 07/13] scsi: scsi_debug: Report the residual of a write Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 08/13] scsi: scsi_debug: Enforce physical block alignment of zoned writes Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 09/13] scsi: scsi_debug: Do not write a partial physical block to a zoned device Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 10/13] scsi: scsi_debug: Advance the write pointer over the data written Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 11/13] scsi: scsi_debug: Refuse a short WRITE ATOMIC (16) before writing it Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 12/13] scsi: scsi_debug: Map the region written by WRITE ATOMIC (16) Niklas Cassel
2026-09-29 8:25 ` [PATCH v11 13/13] scsi: scsi_debug: Validate the access parameters of " Niklas Cassel
2026-10-03 14:23 ` [PATCH v11 00/13] scsi: scsi_debug: fix zoned write validation Martin K. Petersen (Oracle)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260929082456.857423-21-cassel@kernel.org \
--to=cassel@kernel.org \
--cc=James.Bottomley@HansenPartnership.com \
--cc=dlemoal@kernel.org \
--cc=john.garry@linux.dev \
--cc=linux-scsi@vger.kernel.org \
--cc=mkp@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox