@samitouri / QOSamiQemu / commits / a113e0c53f

vhost-user-gpu: fix integer overflow in buffer allocation

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" <vr@darknavy.com> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3940 Signed-off-by: Marc-Andre Lureau <marcandre.lureau@redhat.com> Acked-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260710134720.2317856-1-marcandre.lureau@redhat.com>

Marc-André Lureau committed Jul 10, 2026 at 17:47 UTC a113e0c53fb50d78529fd5ea79e3b8313a7ddcaa
2 files changed +16 -3
contrib/vhost-user-gpu/vhost-user-gpu.c
+7 -1
@@ -388,7 +388,13 @@ vg_resource_create_2d(VuGpu *g,
388 cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
389 return;
390 }
391 - vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height);
391 + if (!vugbm_buffer_create(&res->buffer, &g->gdev, c2d.width, c2d.height)) {
392 + g_critical("%s: buffer creation failed %d %d %d",
393 + __func__, c2d.resource_id, c2d.width, c2d.height);
394 + g_free(res);
395 + cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
396 + return;
397 + }
398 res->image = pixman_image_create_bits(pformat,
399 c2d.width,
400 c2d.height,
contrib/vhost-user-gpu/vugbm.c
+9 -2
@@ -13,7 +13,7 @@
13 static bool
14 mem_alloc_bo(struct vugbm_buffer *buf)
15 {
16 - buf->mmap = g_malloc(buf->width * buf->height * 4);
16 + buf->mmap = g_malloc((uint64_t)buf->width * buf->height * 4);
17 buf->stride = buf->width * 4;
18 return true;
19 }
@@ -53,7 +53,8 @@ struct udmabuf_create {
53 static size_t
54 udmabuf_get_size(struct vugbm_buffer *buf)
55 {
56 - return ROUND_UP(buf->width * buf->height * 4, qemu_real_host_page_size());
56 + return ROUND_UP((uint64_t)buf->width * buf->height * 4,
57 + qemu_real_host_page_size());
58 }
59
60 static bool
@@ -293,6 +294,12 @@ bool
294 vugbm_buffer_create(struct vugbm_buffer *buffer, struct vugbm_device *dev,
295 uint32_t width, uint32_t height)
296 {
297 + uint64_t size = (uint64_t)width * height * 4;
298 + if (size > UINT32_MAX) {
299 + g_warning("buffer dimensions too large: %ux%u", width, height);
300 + return false;
301 + }
302 +
303 buffer->dev = dev;
304 buffer->width = width;
305 buffer->height = height;