* [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation
@ 2026-07-10 13:47 marcandre.lureau
2026-07-10 15:34 ` Philippe Mathieu-Daudé
2026-07-25 15:45 ` Michael S. Tsirkin
0 siblings, 2 replies; 5+ messages in thread
From: marcandre.lureau @ 2026-07-10 13:47 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau, Michael S. Tsirkin, Stefano Garzarella
From: Marc-André Lureau <marcandre.lureau@redhat.com>
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>
---
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;
}
@@ -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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation
2026-07-10 13:47 [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation marcandre.lureau
@ 2026-07-10 15:34 ` Philippe Mathieu-Daudé
2026-07-12 6:48 ` Marc-André Lureau
2026-07-25 15:45 ` Michael S. Tsirkin
1 sibling, 1 reply; 5+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-07-10 15:34 UTC (permalink / raw)
To: marcandre.lureau, qemu-devel; +Cc: Michael S. Tsirkin, Stefano Garzarella
On 10/7/26 15:47, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> 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>
> ---
> 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/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);
Just curious, would this also work safely?
buf->mmap = g_malloc_n(4, buf->width * buf->height);
The GLib description is:
This function is similar to g_malloc(),
allocating (n_blocks * n_block_bytes) bytes,
but care is taken to detect possible overflow
during multiplication.
> buf->stride = buf->width * 4;
> return true;
> }
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation
2026-07-10 15:34 ` Philippe Mathieu-Daudé
@ 2026-07-12 6:48 ` Marc-André Lureau
0 siblings, 0 replies; 5+ messages in thread
From: Marc-André Lureau @ 2026-07-12 6:48 UTC (permalink / raw)
To: Philippe Mathieu-Daudé
Cc: qemu-devel, Michael S. Tsirkin, Stefano Garzarella
Hi
On Fri, Jul 10, 2026 at 7:35 PM Philippe Mathieu-Daudé
<philmd@oss.qualcomm.com> wrote:
>
> On 10/7/26 15:47, marcandre.lureau@redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > 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>
> > ---
> > 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/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);
>
> Just curious, would this also work safely?
>
> buf->mmap = g_malloc_n(4, buf->width * buf->height);
>
> The GLib description is:
>
> This function is similar to g_malloc(),
> allocating (n_blocks * n_block_bytes) bytes,
> but care is taken to detect possible overflow
> during multiplication.
Yes, that would be similar.
thanks
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation
2026-07-10 13:47 [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation marcandre.lureau
2026-07-10 15:34 ` Philippe Mathieu-Daudé
@ 2026-07-25 15:45 ` Michael S. Tsirkin
2026-07-25 17:18 ` Marc-André Lureau
1 sibling, 1 reply; 5+ messages in thread
From: Michael S. Tsirkin @ 2026-07-25 15:45 UTC (permalink / raw)
To: marcandre.lureau; +Cc: qemu-devel, Stefano Garzarella
On Fri, Jul 10, 2026 at 05:47:19PM +0400, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> 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>
> ---
> 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?
> @@ -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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation
2026-07-25 15:45 ` Michael S. Tsirkin
@ 2026-07-25 17:18 ` Marc-André Lureau
0 siblings, 0 replies; 5+ messages in thread
From: Marc-André Lureau @ 2026-07-25 17:18 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: qemu-devel, Stefano Garzarella
Hi
On Sat, Jul 25, 2026 at 7:46 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> On Fri, Jul 10, 2026 at 05:47:19PM +0400, marcandre.lureau@redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > 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>
> > ---
> > 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
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-25 17:19 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10 13:47 [PATCH] vhost-user-gpu: fix integer overflow in buffer allocation marcandre.lureau
2026-07-10 15:34 ` Philippe Mathieu-Daudé
2026-07-12 6:48 ` Marc-André Lureau
2026-07-25 15:45 ` Michael S. Tsirkin
2026-07-25 17:18 ` Marc-André Lureau
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.