@samitouri / QOSamiQemu / commits / 884363589b

hw/display/virtio-gpu: Validate resource per command

virtio_gpu_find_check_resource() checks if the resource has backing storage if require_backing is true, but the condition conflates backing storage attachment with host representation; it checks !res->iov || (!res->image && !res->blob), but !res->iov is sufficient. Furthermore, its callers passing true as require_backing have different requirements: - virtio_gpu_transfer_to_host_2d() requires a non-blob with backing storage. - virtio_gpu_set_scanout() requires a non-blob but does not require backing storage. - virtio_gpu_set_scanout_blob() requires a blob with backing storage. - virtio_gpu_resource_detach_backing() accepts any resource. Remove the require_backing parameter and open-code checks appropriate for each function instead. Fixes: 25c001a40346 ("virtio-gpu: Add virtio_gpu_find_check_resource") Fixes: e0933d91b1cd ("virtio-gpu: Add virtio_gpu_resource_create_blob") 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> Message-ID: <20260825-dmabuf-v2-5-b3d64d3b9a0e@rsg.ci.i.u-tokyo.ac.jp>

Akihiko Odaki committed Aug 25, 2026 at 16:28 UTC 884363589b68049cb344b8f8089464bada32a8e7
1 file changed +45 -21
hw/display/virtio-gpu.c
+45 -21
@@ -37,7 +37,6 @@
37
38 static struct virtio_gpu_simple_resource *
39 virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
40 - bool require_backing,
40 const char *caller, uint32_t *error);
41
42 static void virtio_gpu_reset_bh(void *opaque);
@@ -50,8 +49,7 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g,
49 uint32_t pixels;
50 void *data;
51
53 - res = virtio_gpu_find_check_resource(g, resource_id, false,
54 - __func__, NULL);
52 + res = virtio_gpu_find_check_resource(g, resource_id, __func__, NULL);
53 if (!res) {
54 return;
55 }
@@ -128,7 +126,6 @@ virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id)
126
127 static struct virtio_gpu_simple_resource *
128 virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
131 - bool require_backing,
129 const char *caller, uint32_t *error)
130 {
131 struct virtio_gpu_simple_resource *res;
@@ -143,17 +140,6 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
140 return NULL;
141 }
142
146 - if (require_backing) {
147 - if (!res->iov || (!res->image && !res->blob)) {
148 - qemu_log_mask(LOG_GUEST_ERROR, "%s: no backing storage %d\n",
149 - caller, resource_id);
150 - if (error) {
151 - *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
152 - }
153 - return NULL;
154 - }
155 - }
156 -
143 return res;
144 }
145
@@ -474,9 +460,24 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
460 virtio_gpu_t2d_bswap(&t2d);
461 trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
462
477 - res = virtio_gpu_find_check_resource(g, t2d.resource_id, true,
463 + res = virtio_gpu_find_check_resource(g, t2d.resource_id,
464 __func__, &cmd->error);
479 - if (!res || res->blob) {
465 + if (!res) {
466 + return;
467 + }
468 +
469 + if (!res->image) {
470 + qemu_log_mask(LOG_GUEST_ERROR, "%s: resource %d is a blob\n",
471 + __func__, t2d.resource_id);
472 + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
473 + return;
474 + }
475 +
476 + if (!res->iov) {
477 + qemu_log_mask(LOG_GUEST_ERROR,
478 + "%s: resource %d has no backing storage\n",
479 + __func__, t2d.resource_id);
480 + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
481 return;
482 }
483
@@ -533,7 +534,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
534 trace_virtio_gpu_cmd_res_flush(rf.resource_id,
535 rf.r.width, rf.r.height, rf.r.x, rf.r.y);
536
536 - res = virtio_gpu_find_check_resource(g, rf.resource_id, false,
537 + res = virtio_gpu_find_check_resource(g, rf.resource_id,
538 __func__, &cmd->error);
539 if (!res) {
540 return;
@@ -771,12 +772,19 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
772 return;
773 }
774
774 - res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
775 + res = virtio_gpu_find_check_resource(g, ss.resource_id,
776 __func__, &cmd->error);
777 if (!res) {
778 return;
779 }
780
781 + if (!res->image) {
782 + qemu_log_mask(LOG_GUEST_ERROR, "%s: resource %d is a blob\n",
783 + __func__, ss.resource_id);
784 + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
785 + return;
786 + }
787 +
788 fb.format = pixman_image_get_format(res->image);
789 bytes_pp = virtio_gpu_format_bytes_pp(fb.format);
790 fb.width = pixman_image_get_width(res->image);
@@ -866,12 +874,28 @@ static void virtio_gpu_set_scanout_blob(VirtIOGPU *g,
874 return;
875 }
876
869 - res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
877 + res = virtio_gpu_find_check_resource(g, ss.resource_id,
878 __func__, &cmd->error);
879 if (!res) {
880 return;
881 }
882
883 + if (res->image) {
884 + qemu_log_mask(LOG_GUEST_ERROR,
885 + "%s: resource %d is not a blob\n",
886 + __func__, ss.resource_id);
887 + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
888 + return;
889 + }
890 +
891 + if (!res->iov) {
892 + qemu_log_mask(LOG_GUEST_ERROR,
893 + "%s: resource %d has no backing storage\n",
894 + __func__, ss.resource_id);
895 + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
896 + return;
897 + }
898 +
899 if (!virtio_gpu_scanout_blob_to_fb(&fb, &ss, res->blob_size)) {
900 cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
901 return;
@@ -1067,7 +1091,7 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g,
1091 virtio_gpu_bswap_32(&detach, sizeof(detach));
1092 trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
1093
1070 - res = virtio_gpu_find_check_resource(g, detach.resource_id, true,
1094 + res = virtio_gpu_find_check_resource(g, detach.resource_id,
1095 __func__, &cmd->error);
1096 if (!res) {
1097 return;