[PATCH] hw/display/virtio-gpu: reject strides exceeding INT_MAX

Akihiko Odaki posted 1 patch 1 week, 1 day ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260717-int-v1-1-8aa05e1791a0@rsg.ci.i.u-tokyo.ac.jp
Maintainers: "Alex Bennée" <alex.bennee@linaro.org>, Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>, Dmitry Osipenko <dmitry.osipenko@collabora.com>, "Michael S. Tsirkin" <mst@redhat.com>
hw/display/virtio-gpu.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
[PATCH] hw/display/virtio-gpu: reject strides exceeding INT_MAX
Posted by Akihiko Odaki 1 week, 1 day ago
VIRTIO_GPU_CMD_SET_SCANOUT_BLOB supplies a guest-controlled uint32_t
stride, but some downstream consumers take it as int. They may interpret
a value greater than INT_MAX as negative and cause issues:

- pixman_image_create_bits() takes the stride as int, and Pixman may
  later access memory before the blob buffer.

- eglCreateImageKHR() also takes the stride as EGLint when importing the
  DMA-BUF, and Mesa rejects it.

Reject such strides before scanout.

The check in virtio_gpu_scanout_blob_to_fb() rejects unsupported blob
configurations early. The check added in virtio_gpu_do_set_scanout()
covers migration post_load.

Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
---
Based-on: <20260715201055.2465320-1-marcandre.lureau@redhat.com>
("[PATCH] hw/display/virtio-gpu: validate stride against width on scanout")
---
 hw/display/virtio-gpu.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index e00fb6effa50..9b54207feb37 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -654,6 +654,14 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
         return false;
     }
 
+    if (fb->stride > INT_MAX) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: stride is %" PRIu32
+                      ", larger than the supported maximum (%d)\n",
+                      __func__, fb->stride, INT_MAX);
+        *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return false;
+    }
+
     g->parent_obj.enable = 1;
 
     if (res->blob) {
@@ -769,6 +777,13 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
         return false;
     }
 
+    if (fb->stride > INT_MAX) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: stride is %" PRIu32
+                      ", larger than the supported maximum (%d)\n",
+                      __func__, fb->stride, INT_MAX);
+        return false;
+    }
+
     fb->offset = ss->offsets[0] + ss->r.x * fb->bytes_pp + ss->r.y * fb->stride;
 
     fbend = fb->offset;

---
base-commit: d25b8018680d762145d55ceed4fa7a3a47ac646e
change-id: 20260716-int-6c94d32875b1

Best regards,
--  
Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Re: [PATCH] hw/display/virtio-gpu: reject strides exceeding INT_MAX
Posted by Marc-André Lureau 1 week, 1 day ago
On Fri, Jul 17, 2026 at 11:43 AM Akihiko Odaki
<odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>
> VIRTIO_GPU_CMD_SET_SCANOUT_BLOB supplies a guest-controlled uint32_t
> stride, but some downstream consumers take it as int. They may interpret
> a value greater than INT_MAX as negative and cause issues:
>
> - pixman_image_create_bits() takes the stride as int, and Pixman may
>   later access memory before the blob buffer.
>
> - eglCreateImageKHR() also takes the stride as EGLint when importing the
>   DMA-BUF, and Mesa rejects it.
>
> Reject such strides before scanout.
>
> The check in virtio_gpu_scanout_blob_to_fb() rejects unsupported blob
> configurations early. The check added in virtio_gpu_do_set_scanout()
> covers migration post_load.
>
> Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
> Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>

> ---
> Based-on: <20260715201055.2465320-1-marcandre.lureau@redhat.com>
> ("[PATCH] hw/display/virtio-gpu: validate stride against width on scanout")
> ---
>  hw/display/virtio-gpu.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
>
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index e00fb6effa50..9b54207feb37 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -654,6 +654,14 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
>          return false;
>      }
>
> +    if (fb->stride > INT_MAX) {
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: stride is %" PRIu32
> +                      ", larger than the supported maximum (%d)\n",
> +                      __func__, fb->stride, INT_MAX);
> +        *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
> +        return false;
> +    }
> +
>      g->parent_obj.enable = 1;
>
>      if (res->blob) {
> @@ -769,6 +777,13 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
>          return false;
>      }
>
> +    if (fb->stride > INT_MAX) {
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: stride is %" PRIu32
> +                      ", larger than the supported maximum (%d)\n",
> +                      __func__, fb->stride, INT_MAX);
> +        return false;
> +    }
> +
>      fb->offset = ss->offsets[0] + ss->r.x * fb->bytes_pp + ss->r.y * fb->stride;
>
>      fbend = fb->offset;
>
> ---
> base-commit: d25b8018680d762145d55ceed4fa7a3a47ac646e
> change-id: 20260716-int-6c94d32875b1
>
> Best regards,
> --
> Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>
>


-- 
Marc-André Lureau