@samitouri / QOSamiQemu / commits / b8ef970532

hw/display/virtio-gpu: fix offset wraparound in scanout_blob_to_fb

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: <20260719-bpp-v1-1-9b91946d6cf3@rsg.ci.i.u-tokyo.ac.jp> Reported-by: Cyber_black <Cyberblackk@proton.me> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260725122734.1775774-1-marcandre.lureau@redhat.com>

Marc-André Lureau committed Jul 25, 2026 at 16:27 UTC b8ef970532c30da2f3fa8985867a74f898ce96aa
1 file changed +8 -6
hw/display/virtio-gpu.c
+8 -6
@@ -777,7 +777,7 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
777 struct virtio_gpu_set_scanout_blob *ss,
778 uint64_t blob_size)
779 {
780 - uint64_t fbend;
780 + uint64_t fbend, offset;
781 uint32_t bytes_pp;
782
783 fb->format = virtio_gpu_get_pixman_format(ss->format);
@@ -807,18 +807,20 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
807 return false;
808 }
809
810 - fb->offset = ss->offsets[0] + ss->r.x * bytes_pp + ss->r.y * fb->stride;
810 + offset = (uint64_t)ss->offsets[0] + (uint64_t)ss->r.x * bytes_pp +
811 + (uint64_t)ss->r.y * fb->stride;
812
812 - fbend = fb->offset;
813 - fbend += (uint64_t) fb->stride * ss->r.height;
813 + fbend = offset + (uint64_t)fb->stride * ss->r.height;
814
815 - if (fbend > blob_size) {
815 + if (offset > UINT32_MAX || fbend > blob_size) {
816 qemu_log_mask(LOG_GUEST_ERROR,
817 - "%s: fb end out of range\n",
817 + "%s: invalid fb bounds\n",
818 __func__);
819 return false;
820 }
821
822 + fb->offset = offset;
823 +
824 return true;
825 }
826