From nobody Mon Sep 28 01:18:00 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=rsg.ci.i.u-tokyo.ac.jp ARC-Seal: i=1; a=rsa-sha256; t=1785746808; cv=none; d=zohomail.com; s=zohoarc; b=X86EaOBw8s9o1zXpI23nCxD+GOGAyVEdEJzo9RjDQ/qiPSIEYEq+sZJLA/mIrfzD+eQSSNRew1qurnquyjNPJpW+Et1Eizyh9yoDpMGcfJEHfcTOm0e2ypvS5Ko98al6JutWpAZL/S0tA9rXrRPBLapKjWk4Pb+EBjxVVbtFJMU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785746808; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=/n1Y4udR3p70a7efRtD8QoF3yraKqrO4yBgCmSRJc/k=; b=ZDTs290ijpkH8eaUzMpXsNuWl/J2oWNEq309kSkxiBdeZsH0iOQLDTsI/xd+JJ4GdQpD3HH4oaz3fYaraSOR6TV4zkHfgOkojBFenH71N+drQZJoXEefWuKCQuyLQD2V/pA8XtqSoBtpLueEg0/iUoM2kTqmXERXl5N67OjYQyc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1785746807775164.7316440495497; Mon, 3 Aug 2026 01:46:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wqoJ4-0001zL-J2; Mon, 03 Aug 2026 04:45:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wqoJ2-0001zA-EB for qemu-devel@nongnu.org; Mon, 03 Aug 2026 04:45:56 -0400 Received: from www3579.sakura.ne.jp ([49.212.243.89]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wqoIz-0007W3-N1 for qemu-devel@nongnu.org; Mon, 03 Aug 2026 04:45:56 -0400 Received: from h183.csg.ci.i.u-tokyo.ac.jp (h183.csg.ci.i.u-tokyo.ac.jp [133.11.54.183]) (authenticated bits=0) by www3579.sakura.ne.jp (8.16.1/8.16.1) with ESMTPSA id 6738jbOn026885 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 3 Aug 2026 17:45:39 +0900 (JST) (envelope-from odaki@rsg.ci.i.u-tokyo.ac.jp) DKIM-Signature: a=rsa-sha256; bh=/n1Y4udR3p70a7efRtD8QoF3yraKqrO4yBgCmSRJc/k=; c=relaxed/relaxed; d=rsg.ci.i.u-tokyo.ac.jp; h=From:Message-Id:To:Subject:Date; s=rs20250326; t=1785746739; v=1; b=j3S3nLEOOyIkV1N+llQLNY7TYiAJ2NOfVMlt+3noMy3IJO98BG2GnqPRegL2mSE9 QgKJHR5MEMSN3JG8//7YgPkTjjGFobBJ70NW22DqOsK3TM0WgI45qE3PsWjeTwWj tfrfD1jvEhr0DaImwhVckxkmQiaIVwDnCjpTtCQ1P5rGprCOAYHxSebcQY+MoygU iqTDPg3g1xVxyIAHEwD4JSZatc2WUty3rHJ6ZzKSvZ66RDFWaPdS9UCEzIj4ZCmk wZArBDP1me0FUNpqauizIg4GAkzBbdJFiOGLBjlztkwk72UBIHWvN/uHizZSpllt xPTiVfNVBN9IaHAUbhWXpQ== From: Akihiko Odaki Date: Mon, 03 Aug 2026 17:45:25 +0900 Subject: [PATCH] hw/display/virtio-gpu: Always reject invalid scanout bounds MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260803-scanout-v1-1-c9831dafdab2@rsg.ci.i.u-tokyo.ac.jp> X-B4-Tracking: v=1; b=H4sIAAAAAAAC/yXMQQ5AMBCF4avIrDWpSihXEQvGYCxKOioScXfF8 kv+9y4Q8kwCdXKBp4OFVxeRpQng3LmJFA/RYLQptNW5EuzcGnaFJY7GYmYrTRDrzdPI5/fUtL8 l9Avh/s7hvh8gZ+rNawAAAA== X-Change-ID: 20260803-scanout-c7cf28c1890e To: qemu-devel@nongnu.org Cc: "Michael S. Tsirkin" , =?utf-8?q?Alex_Benn=C3=A9e?= , Dmitry Osipenko , Akihiko Odaki X-Mailer: b4 0.16-dev-925f5 X-Developer-Signature: v=1; a=openpgp-sha256; l=7029; i=odaki@rsg.ci.i.u-tokyo.ac.jp; h=from:subject:message-id; bh=RLFDNKk8UtS2ny7VvGaG0piI28YqqELWzMQUAnpgoTg=; b=owGbwMvMwCWmMbc20y1CyJDxtFoSQ1ZBqPHJ+kr9rf8zuG/Pn1O+4dMBy++L/E//Kny5osrs9 afFv739OkpZGMS4GGTFFFlSinZza0TXfipMiG+BmcPKBDKEgYtTACbC9JKR4X9nTvqW2Hsir+// Nn77ekoQq6ziPQ+JU1sCOSd9uVN0/wnDP5tmH5Ot4vG1xU+uRqm+Pvvu05GpzlGrg/QPvVh/U/r dZz4A X-Developer-Key: i=odaki@rsg.ci.i.u-tokyo.ac.jp; a=openpgp; fpr=AEDC03C9AF734F2EC26A7BFFA4BAEAA73536753C Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=49.212.243.89; envelope-from=odaki@rsg.ci.i.u-tokyo.ac.jp; helo=www3579.sakura.ne.jp X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @rsg.ci.i.u-tokyo.ac.jp) X-ZM-MESSAGEID: 1785746812314158500 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 gfxstre= am") Signed-off-by: Akihiko Odaki Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- 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/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 2f60c72078b3..287262228d33 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -363,6 +363,11 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g, struct virtio_gpu_scanout *s, uint32_t resource_id); =20 +bool virtio_gpu_check_scanout_bounds(uint32_t scanout_id, uint32_t resourc= e_id, + uint32_t width, uint32_t height, + const struct virtio_gpu_rect *r, + uint32_t *error); + /** * virtio_gpu_scanout_blob_to_fb() - fill out fb based on scanout data * fb: the frame-buffer descriptor to fill out diff --git a/hw/display/virtio-gpu-rutabaga.c b/hw/display/virtio-gpu-rutab= aga.c index e28aad94eead..a054f8117f14 100644 --- a/hw/display/virtio-gpu-rutabaga.c +++ b/hw/display/virtio-gpu-rutabaga.c @@ -315,6 +315,12 @@ rutabaga_cmd_set_scanout(VirtIOGPU *g, struct virtio_g= pu_ctrl_command *cmd) res =3D virtio_gpu_find_resource(g, ss.resource_id); CHECK(res, cmd); =20 + if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id, + res->width, res->height, &ss.r, + &cmd->error)) { + return; + } + if (!res->image) { pixman_format_code_t pformat; pformat =3D virtio_gpu_get_pixman_format(res->format); diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index d9e5b0110497..6e298f997d66 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -560,7 +560,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, } g->parent_obj.enable =3D 1; =20 - if (ss.resource_id && ss.r.width && ss.r.height) { + if (ss.resource_id) { struct virgl_renderer_resource_info info; void *d3d_tex2d =3D NULL; =20 @@ -581,6 +581,11 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, cmd->error =3D VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; return; } + if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id, + info.width, info.height, &ss.= r, + &cmd->error)) { + return; + } qemu_console_resize(g->parent_obj.scanout[ss.scanout_id].con, ss.r.width, ss.r.height); virgl_renderer_force_ctx_0(); @@ -987,16 +992,9 @@ static void virgl_cmd_set_scanout_blob(VirtIOGPU *g, return; } =20 - if (ss.width < 16 || - ss.height < 16 || - ss.r.x + ss.r.width > ss.width || - ss.r.y + ss.r.height > ss.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__, ss.scanout_id, ss.resource_id, - ss.r.x, ss.r.y, ss.r.width, ss.r.height, - ss.width, ss.height); - cmd->error =3D VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; + if (!virtio_gpu_check_scanout_bounds(ss.scanout_id, ss.resource_id, + ss.width, ss.height, &ss.r, + &cmd->error)) { return; } =20 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_form= at_code_t format) return DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8); } =20 +bool virtio_gpu_check_scanout_bounds(uint32_t scanout_id, uint32_t resourc= e_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, + r->x, r->y, r->width, r->height); + *error =3D 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, =20 scanout =3D &g->parent_obj.scanout[scanout_id]; =20 - if (r->x > fb->width || - r->y > fb->height || - r->width < 16 || - r->height < 16 || - r->width > fb->width || - r->height > fb->height || - 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 =3D 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; } =20 --- base-commit: 299e7557ed15a9a325620698add379a3ce2d1d95 change-id: 20260803-scanout-c7cf28c1890e Best regards, -- =20 Akihiko Odaki