From 53b627a98b78ac06e7cba29c3614464469e7c11f Mon Sep 17 00:00:00 2001 From: tangbinzy Date: Mon, 25 Mar 2024 08:14:12 +0000 Subject: [PATCH] scsi-disk: fix overflow when block size is not a multiple of BDRV_SECTOR_SIZE mainline inclusion commit 54a53a006ed9c1fe027fd89045d6de1e9128d7f4 category: bugfix --------------------------------------------------------------- In scsi_disk_emulate_write_same() the number of host sectors to transfer is calculated as (s->qdev.blocksize / BDRV_SECTOR_SIZE) which is then used to copy data in block size chunks to the iov buffer. Since the loop copying the data to the iov buffer uses a fixed increment of s->qdev.blocksize then using a block size that isn't a multiple of BDRV_SECTOR_SIZE introduces a rounding error in the iov buffer size calculation such that the iov buffer copy overflows the space allocated. Update the iov buffer copy for() loop so that it will use the smallest of either the current block size or the remaining transfer count to prevent the overflow. Signed-off-by: Mark Cave-Ayland Message-Id: <20220730122656.253448-2-mark.cave-ayland@ilande.co.uk> Signed-off-by: Paolo Bonzini Signed-off-by: tangbinzy --- hw/scsi/scsi-disk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index a66d2b0a98..edd2f895e7 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1800,7 +1800,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) uint32_t nb_sectors = scsi_data_cdb_xfer(r->req.cmd.buf); WriteSameCBData *data; uint8_t *buf; - int i; + int i, l; /* Fail if PBDATA=1 or LBDATA=1 or ANCHOR=1. */ if (nb_sectors == 0 || (req->cmd.buf[1] & 0x16)) { @@ -1842,8 +1842,9 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) data->iov.iov_len); qemu_iovec_init_external(&data->qiov, &data->iov, 1); - for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) { - memcpy(&buf[i], inbuf, s->qdev.blocksize); + for (i = 0; i < data->iov.iov_len; i += l) { + l = MIN(s->qdev.blocksize, data->iov.iov_len - i); + memcpy(&buf[i], inbuf, l); } scsi_req_ref(&r->req); -- 2.27.0