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]>


Reply via email to