On Wed, Oct 07, 2026 at 08:14:30PM +0530, Chinmay Rath wrote: > vscsi_send_adapter_info() used the guest-supplied common.length > field directly as the size argument to spapr_vio_dma_write(). > Since common.length is controlled by the guest, a value larger > than sizeof(struct mad_adapter_info_data) (148 bytes) caused > dma_memory_write() to read past the end of the stack-allocated info > struct, leaking arbitrary host stack contents into guest memory. > > Fix this by clamping the write length to sizeof(info), then using > spapr_vio_dma_set() to zero-fill any remaining bytes the guest > requested beyond that size. This mirrors the existing pattern in > vscsi_send_capabilities(). > > Closes: https://gitlab.com/qemu-project/qemu/-/work_items/4626 > Reported-by: Guthrie McAfee Armstrong <[email protected]> > Signed-off-by: Chinmay Rath <[email protected]> > --- > hw/scsi/spapr_vscsi.c | 18 ++++++++++++++++-- > 1 file changed, 16 insertions(+), 2 deletions(-) > > diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c > index b4c8f94d22..7ec780da79 100644 > --- a/hw/scsi/spapr_vscsi.c > +++ b/hw/scsi/spapr_vscsi.c > @@ -966,6 +966,8 @@ static int vscsi_send_adapter_info(VSCSIState *s, > vscsi_req *req) > { > struct viosrp_adapter_info *sinfo; > struct mad_adapter_info_data info; > + uint16_t len, req_len; > + uint64_t buffer; > int rc; > > sinfo = &req_iu(req)->mad.adapter_info; > @@ -985,11 +987,23 @@ static int vscsi_send_adapter_info(VSCSIState *s, > vscsi_req *req) > info.os_type = cpu_to_be32(2); > info.port_max_txu[0] = cpu_to_be32(VSCSI_MAX_SECTORS << 9); > > - rc = spapr_vio_dma_write(&s->vdev, be64_to_cpu(sinfo->buffer), > - &info, be16_to_cpu(sinfo->common.length)); > + req_len = len = be16_to_cpu(sinfo->common.length); > + buffer = be64_to_cpu(sinfo->buffer); > + if (len > sizeof(info)) { > + fprintf(stderr, "vscsi_send_adapter_info: adapter info size mismatch > !\n"); > + /* > + * Just read and populate the structure that is known. > + * Zero rest of the structure. > + */ > + len = sizeof(info); > + } > + rc = spapr_vio_dma_write(&s->vdev, buffer, &info, len); > if (rc) { > fprintf(stderr, "vscsi_send_adapter_info: DMA write failure !\n"); > } > + if (req_len > len) { > + spapr_vio_dma_set(&s->vdev, (buffer + len), 0, (req_len - len)); > + } > > sinfo->common.status = rc ? cpu_to_be32(1) : 0;
Reviewed-by: Gautam Menghani <[email protected]> Tested-by: Gautam Menghani <[email protected]>
