Re: [PATCH] hw/display/virtio-gpu: Always reject invalid scanout bounds
Philippe Mathieu-Daudé <[email protected]> Mon, 3 Aug 2026 13:46:13 +0200
| Newsgroups | org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On 3/8/26 12:32, Akihiko Odaki wrote:
> On 2026/08/03 19:17, Philippe Mathieu-Daudé wrote:
>> Hi Akihiko,
>>
>> On 3/8/26 10:45, Akihiko Odaki wrote:
>>> virtio-gpu does not consistently check scanout bounds with wraparound
>>> handling. In the unchecked virgl SET_SCANOUT path, guest dimensions
>>> reach qemu_console_resize(), qemu_create_displaysurface(), and
>>> ultimately qemu_pixman_image_new_shareable(..., &error_abort), so an
>>> invalid rectangle can terminate QEMU. Implement a check with proper
>>> wraparound handling and apply it consistently.
>>>
>>> Fixes: 9d9e152136bd ("virtio-gpu: add 3d mode and virgl rendering
>>> support.")
>>> Fixes: 32db3c63ae11 ("virtio-gpu: Add virtio_gpu_set_scanout_blob")
>>> Fixes: 7c092f17ccee ("virtio-gpu: Handle resource blob commands")
>>> Fixes: 1dcc6adbc168 ("gfxstream + rutabaga: add initial support for
>>> gfxstream")
>>> Signed-off-by: Akihiko Odaki <[email protected]>
>>> ---
>>> include/hw/virtio/virtio-gpu.h | 5 +++++
>>> hw/display/virtio-gpu-rutabaga.c | 6 ++++++
>>> hw/display/virtio-gpu-virgl.c | 20 +++++++++-----------
>>> hw/display/virtio-gpu.c | 36 +++++++++++++++++++++
>>> +--------------
>>> 4 files changed, 42 insertions(+), 25 deletions(-)
>>
>>
>>> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
>>> index 4d46a4eb10fa..3c0e38c1def0 100644
>>> --- a/hw/display/virtio-gpu.c
>>> +++ b/hw/display/virtio-gpu.c
>>> @@ -622,6 +622,26 @@ static uint32_t
>>> virtio_gpu_format_bytes_pp(pixman_format_code_t format)
>>> return DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
>>> }
>>> +bool virtio_gpu_check_scanout_bounds(uint32_t scanout_id, uint32_t
>>> resource_id,
>>> + uint32_t width, uint32_t height,
>>> + const struct virtio_gpu_rect *r,
>>> + uint32_t *error)
>>> +{
>>> + if (r->width < 16 ||
>>> + r->height < 16 ||
>>> + (uint64_t)r->x + r->width > width ||
>>> + (uint64_t)r->y + r->height > height) {
>>> + qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d
>>> bounds for"
>>> + " resource %d, fb %d %d, rect (%d,%d)+%d,%d\n",
>>> + __func__, scanout_id, resource_id, width, height,
>>
>> __func__ will always be "virtio_gpu_check_scanout_bounds", maybe we
>> want the caller instead? Otherwise simply drop?
>>
>> Since we rework this code, in case we are debugging broken guest driver,
>> it could be more helpful to log one LOG_GUEST_ERROR per error type:
>>
>> if (r->width < 16) { ... }
>> if (r->height < 16) { ... }
>> ...
>
> I don't have a strong opinion here, but if I'm debugging a broken guest,
> probably I would use the printed function name to look up this code and
> then figure out what's wrong by comparing with the actual condition.
>
> This applies to other instances of LOG_GUEST_ERROR; ideally it would be
> nice if there is some sort of guideline, though I think people have
> different opinions what such a guideline should say.
Fine.
>
> Regards,
> Akihiko Odaki
>
>>
>>> + r->x, r->y, r->width, r->height);
>>> + *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
>>> + return false;
>>> + }
>>> +
>>> + return true;
>>> +}
>>> +
>>> static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
>>> uint32_t scanout_id,
>>> struct virtio_gpu_framebuffer
>>> *fb,
>>> @@ -635,20 +655,8 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
>>> scanout = &g->parent_obj.scanout[scanout_id];
>>> - if (r->x > fb->width ||
>>> - r->y > fb->height ||
>>
>> > - r->width > fb->width ||
>> > - r->height > fb->height ||
>>
>> Do we want to remove these checks?
I'm interested by your view on this, I might have misunderstood
part of the change.
Otherwise removing __func__:
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
>>
>>> - r->width < 16 ||
>>> - r->height < 16 ||
>>
>>> - r->x + r->width > fb->width ||
>>> - r->y + r->height > fb->height) {
>>> - qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d
>>> bounds for"
>>> - " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
>>> - __func__, scanout_id, res->resource_id,
>>> - r->x, r->y, r->width, r->height,
>>> - fb->width, fb->height);
>>> - *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
>>> + if (!virtio_gpu_check_scanout_bounds(scanout_id, res->resource_id,
>>> + fb->width, fb->height, r,
>>> error)) {
>>> return false;
>>> }
>>>
>>> ---
>>> base-commit: 299e7557ed15a9a325620698add379a3ce2d1d95
>>> change-id: 20260803-scanout-c7cf28c1890e
>>>
>>> Best regards,
>>> --
>>> Akihiko Odaki <[email protected]>
>>>
>>>
>>
>
>