From: Stefan Hajnoczi <[email protected]> Check that the iovec containing struct virtio_scsi_inhdr is large enough before storing an error value there.
Feifan Qian <[email protected]> pointed out that this can be used to corrupt heap memory when the descriptor uses an MMIO address and a length of 1, forcing QEMU to allocate a 1-byte heap bounce buffer. virtio_stl_p() stores 4 bytes and therefore corrupts whatever is beyond the bounce buffer. Fixes: CVE-2026-48914 Fixes: f34e73cd69bd ("virtio-blk: report non-zero status when failing SG_IO requests") Reported-by: Feifan Qian <[email protected]> Cc: Paolo Bonzini <[email protected]> Signed-off-by: Stefan Hajnoczi <[email protected]> Message-ID: <[email protected]> Reviewed-by: Kevin Wolf <[email protected]> Signed-off-by: Kevin Wolf <[email protected]> --- hw/block/virtio-blk.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 9cb9f1fb2b2..6b92066aff4 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -199,10 +199,16 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req) /* * The scsi inhdr is placed in the second-to-last input segment, just - * before the regular inhdr. + * before the regular inhdr. VIRTIO implementations normally do not rely on + * the precise message framing, but legacy implementations did and so we do + * too for the legacy virtio-blk SCSI request type. * * Just put anything nonzero so that the ioctl fails in the guest. */ + if (elem->in_sg[elem->in_num - 2].iov_len != sizeof(*scsi)) { + status = VIRTIO_BLK_S_IOERR; + goto fail; + } scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base; virtio_stl_p(vdev, &scsi->errors, 255); status = VIRTIO_BLK_S_UNSUPP; -- 2.54.0
