On Thu, Jul 16, 2026 at 12:11 AM <[email protected]> wrote: > > From: Marc-André Lureau <[email protected]> > > Validate that the framebuffer stride is at least width * bytes_per_pixel > in both virtio_gpu_scanout_blob_to_fb() and virtio_gpu_do_set_scanout(). > > A guest can set a very small stride while using a large width. The total > size check (offset + stride * height <= blob_size) passes because > stride * height is small, but pixman reads width * bytes_per_pixel per > row, causing heap OOB reads. The leaked data is rendered to the host > display. > > The check is added in virtio_gpu_do_set_scanout() to cover all paths: > blob scanout, non-blob scanout and migration post_load. The additional > early check in virtio_gpu_scanout_blob_to_fb() rejects invalid blob > configurations early. > > Fixes: CVE-2026-63109 > Fixes: 144bd171c837 ("virtio-gpu: Support blob scanout using dmabuf fd")
+ Reported-by: Tristan @TristanInSec > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3989 > Signed-off-by: Marc-André Lureau <[email protected]> > --- > hw/display/virtio-gpu.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c > index 89a73793a42..1d4b8ee4192 100644 > --- a/hw/display/virtio-gpu.c > +++ b/hw/display/virtio-gpu.c > @@ -647,6 +647,14 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g, > return false; > } > > + if (fb->stride < (uint64_t)fb->width * fb->bytes_pp) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: stride %u too small for width %u at %u bpp\n", > + __func__, fb->stride, fb->width, fb->bytes_pp); > + *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; > + return false; > + } > + > g->parent_obj.enable = 1; > > if (res->blob) { > @@ -754,6 +762,14 @@ bool virtio_gpu_scanout_blob_to_fb(struct > virtio_gpu_framebuffer *fb, > fb->width = ss->width; > fb->height = ss->height; > fb->stride = ss->strides[0]; > + > + if (fb->stride < (uint64_t)fb->width * fb->bytes_pp) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "%s: stride %u too small for width %u at %u bpp\n", > + __func__, fb->stride, fb->width, fb->bytes_pp); > + return false; > + } > + > fb->offset = ss->offsets[0] + ss->r.x * fb->bytes_pp + ss->r.y * > fb->stride; > > fbend = fb->offset; > -- > 2.55.0 > >
