From: Marc-André Lureau <[email protected]>
virtio_gpu_scanout_blob_to_fb() computes the framebuffer offset from
guest-controlled offsets[0], r.x, r.y and stride using uint32_t
arithmetic. When the sum exceeds UINT32_MAX, silent wraparound lets
the guest steer the scanout to an arbitrary in-bounds region of the
blob instead of the intended rectangle.
Compute the offset in uint64_t, reject values exceeding UINT32_MAX
(the width of fb->offset), and only store into fb->offset once both
range checks pass.
("[PATCH] hw/display/virtio-gpu: Remove the bytes_pp field")
Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3871
Based-on: <[email protected]>
Reported-by: Cyber_black <[email protected]>
Reviewed-by: Akihiko Odaki <[email protected]>
Signed-off-by: Marc-André Lureau <[email protected]>
Message-ID: <[email protected]>
(cherry picked from commit b8ef970532c30da2f3fa8985867a74f898ce96aa)
Signed-off-by: Michael Tokarev <[email protected]>
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 34b8bb053dc..bd32543dc70 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -773,7 +773,7 @@ bool virtio_gpu_scanout_blob_to_fb(struct
virtio_gpu_framebuffer *fb,
struct virtio_gpu_set_scanout_blob *ss,
uint64_t blob_size)
{
- uint64_t fbend;
+ uint64_t fbend, offset;
uint32_t bytes_pp;
fb->format = virtio_gpu_get_pixman_format(ss->format);
@@ -803,18 +803,20 @@ bool virtio_gpu_scanout_blob_to_fb(struct
virtio_gpu_framebuffer *fb,
return false;
}
- fb->offset = ss->offsets[0] + ss->r.x * bytes_pp + ss->r.y * fb->stride;
+ offset = (uint64_t)ss->offsets[0] + (uint64_t)ss->r.x * bytes_pp +
+ (uint64_t)ss->r.y * fb->stride;
- fbend = fb->offset;
- fbend += (uint64_t) fb->stride * ss->r.height;
+ fbend = offset + (uint64_t)fb->stride * ss->r.height;
- if (fbend > blob_size) {
+ if (offset > UINT32_MAX || fbend > blob_size) {
qemu_log_mask(LOG_GUEST_ERROR,
- "%s: fb end out of range\n",
+ "%s: invalid fb bounds\n",
__func__);
return false;
}
+ fb->offset = offset;
+
return true;
}
--
2.47.3