Hi On Sat, Jul 25, 2026 at 7:46 PM Michael S. Tsirkin <[email protected]> wrote: > > On Fri, Jul 10, 2026 at 05:47:19PM +0400, [email protected] wrote: > > From: Marc-André Lureau <[email protected]> > > > > A malicious guest can trigger a heap buffer overflow in the > > vhost-user-gpu backend by sending a VIRTIO_GPU_CMD_RESOURCE_CREATE_2D > > with large width and height values (e.g. 65537x65537). The allocation > > size width * height * 4 silently wraps in uint32_t arithmetic, > > resulting in a much smaller allocation than expected. Subsequent > > VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D writes past the heap buffer. > > > > The in-tree virtio-gpu device (hw/display/virtio-gpu.c) already handles > > this via calc_image_hostmem() with uint64_t arithmetic and an overflow > > check. Apply the same approach to the vhost-user-gpu contrib backend: > > > > - Add an overflow check in vugbm_buffer_create() rejecting dimensions > > where width * height * 4 exceeds UINT32_MAX > > - Promote the size arithmetic to uint64_t in mem_alloc_bo() and > > udmabuf_get_size() > > - Check the return value of vugbm_buffer_create() in > > vg_resource_create_2d(), which was previously ignored > > > > Fixes: CVE-2026-15264 > > Reported-by: "Vulnerability Report" <[email protected]> > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3940 > > Signed-off-by: Marc-Andre Lureau <[email protected]> > > --- > > contrib/vhost-user-gpu/vhost-user-gpu.c | 8 +++++++- > > contrib/vhost-user-gpu/vugbm.c | 11 +++++++++-- > > 2 files changed, 16 insertions(+), 3 deletions(-) > > > > diff --git a/contrib/vhost-user-gpu/vhost-user-gpu.c > > b/contrib/vhost-user-gpu/vhost-user-gpu.c > > index bb41758e345..ee9858c397c 100644 > > --- a/contrib/vhost-user-gpu/vhost-user-gpu.c > > +++ b/contrib/vhost-user-gpu/vhost-user-gpu.c > > @@ -388,7 +388,13 @@ vg_resource_create_2d(VuGpu *g, > > cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; > > return; > > } > > - vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height); > > + if (!vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, > > c2d.height)) { > > + g_critical("%s: buffer creation failed %d %d %d", > > + __func__, c2d.resource_id, c2d.width, c2d.height); > > + g_free(res); > > + cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; > > + return; > > + } > > res->image = pixman_image_create_bits(pformat, > > c2d.width, > > c2d.height, > > diff --git a/contrib/vhost-user-gpu/vugbm.c b/contrib/vhost-user-gpu/vugbm.c > > index 503d0a4566f..710d5452977 100644 > > --- a/contrib/vhost-user-gpu/vugbm.c > > +++ b/contrib/vhost-user-gpu/vugbm.c > > @@ -13,7 +13,7 @@ > > static bool > > mem_alloc_bo(struct vugbm_buffer *buf) > > { > > - buf->mmap = g_malloc(buf->width * buf->height * 4); > > + buf->mmap = g_malloc((uint64_t)buf->width * buf->height * 4); > > buf->stride = buf->width * 4; > > return true; > > } > > > I apologise but we are still allocating up to 2Gbytes is that really > sane? Isn't there a limit on these things? Like the size of the screen? > > And width * 4 can still wrap around and then will it really behave > correctly? >
By default, builtin-in virtio-gpu has a cumulative max hostmem=256mb (https://www.qemu.org/docs/master/system/devices/virtio/virtio-gpu.html#virtio-gpu-virglrenderer). For 3d/gpu resources this may be considered very low in today's usages. Vulkan 1.4+ requires 8192 in dimensions and has VK_FORMAT_R64G64B64A64_SFLOAT = 256bpp https://docs.vulkan.org/refpages/latest/refpages/source/Required_Limits.html#limits-required So pretty much vulkan 1.4+ requires that a graphics card "accepts" 4Gb allocations. I don't think the virtio-gpu spec should impose a maximum limit. The qemu vhost-user-gpu implementation could benefit from having a hostmem tracking, similar to the built-in device. > > > @@ -53,7 +53,8 @@ struct udmabuf_create { > > static size_t > > udmabuf_get_size(struct vugbm_buffer *buf) > > { > > - return ROUND_UP(buf->width * buf->height * 4, > > qemu_real_host_page_size()); > > + return ROUND_UP((uint64_t)buf->width * buf->height * 4, > > + qemu_real_host_page_size()); > > } > > > > static bool > > @@ -293,6 +294,12 @@ bool > > vugbm_buffer_create(struct vugbm_buffer *buffer, struct vugbm_device *dev, > > uint32_t width, uint32_t height) > > { > > + uint64_t size = (uint64_t)width * height * 4; > > + if (size > UINT32_MAX) { > > + g_warning("buffer dimensions too large: %ux%u", width, height); > > + return false; > > + } > > + > > buffer->dev = dev; > > buffer->width = width; > > buffer->height = height; > > -- > > 2.55.0 > >
