@samitouri / QOSamiQemu / commits / 48f12f521d

virtio-gpu: Fix scanout dmabuf cleanup during resource destruction

When a virtio-gpu resource is destroyed, any associated udmabuf must be properly torn down. Currently, the code may leave dangling references to dmabuf file descriptors in the scanout primary buffers. This patch updates virtio_gpu_fini_udmabuf to: 1. Iterate through all active scanouts. 2. Identify dmabufs that match the resource's file descriptor. 3. Close the dmabuf and invalidate the resource's FD reference to prevent use-after-free or double-close scenarios. 4. Finally, trigger the underlying udmabuf destruction. This ensures that the display backend does not attempt to access memory or FDs that have been released by the guest or the host. Cc: Alex Bennée <alex.bennee@linaro.org> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Marc-André Lureau <marcandre.lureau@redhat.com> Cc: Vivek Kasireddy <vivek.kasireddy@intel.com> Signed-off-by: Dongwon Kim <dongwon.kim@intel.com> Message-ID: <20260304203230.1955266-1-dongwon.kim@intel.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

Dongwon Kim committed Mar 4, 2026 at 12:32 UTC 48f12f521dd12e8756c3138121fa4bf6d8337cb8
4 files changed +24 -10
hw/display/virtio-gpu-udmabuf-stubs.c
+1 -1
@@ -12,7 +12,7 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
12 /* nothing (stub) */
13 }
14
15 -void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
15 +void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res)
16 {
17 /* nothing (stub) */
18 }
hw/display/virtio-gpu-udmabuf.c
+20 -7
@@ -151,13 +151,6 @@ void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
151 res->blob = pdata;
152 }
153
154 -void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
155 -{
156 - if (res->remapped) {
157 - virtio_gpu_destroy_udmabuf(res);
158 - }
159 -}
160 -
154 static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
155 {
156 struct virtio_gpu_scanout *scanout;
@@ -169,6 +162,26 @@ static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
162 g_free(dmabuf);
163 }
164
165 +void virtio_gpu_fini_udmabuf(VirtIOGPU *g, struct virtio_gpu_simple_resource *res)
166 +{
167 + int max_outputs = g->parent_obj.conf.max_outputs;
168 + int i;
169 +
170 + for (i = 0; i < max_outputs; i++) {
171 + VGPUDMABuf *dmabuf = g->dmabuf.primary[i];
172 +
173 + if (dmabuf &&
174 + qemu_dmabuf_get_num_planes(dmabuf->buf) > 0 &&
175 + qemu_dmabuf_get_fds(dmabuf->buf, NULL)[0] == res->dmabuf_fd &&
176 + res->dmabuf_fd != -1) {
177 + qemu_dmabuf_close(dmabuf->buf);
178 + res->dmabuf_fd = -1;
179 + }
180 + }
181 +
182 + virtio_gpu_destroy_udmabuf(res);
183 +}
184 +
185 static VGPUDMABuf
186 *virtio_gpu_create_dmabuf(VirtIOGPU *g,
187 uint32_t scanout_id,
hw/display/virtio-gpu.c
+1 -1
@@ -902,7 +902,7 @@ void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
902 res->addrs = NULL;
903
904 if (res->blob) {
905 - virtio_gpu_fini_udmabuf(res);
905 + virtio_gpu_fini_udmabuf(g, res);
906 }
907 }
908
include/hw/virtio/virtio-gpu.h
+2 -1
@@ -357,7 +357,8 @@ bool virtio_gpu_scanout_blob_to_fb(struct virtio_gpu_framebuffer *fb,
357 /* virtio-gpu-udmabuf.c */
358 bool virtio_gpu_have_udmabuf(void);
359 void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
360 -void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
360 +void virtio_gpu_fini_udmabuf(VirtIOGPU *g,
361 + struct virtio_gpu_simple_resource *res);
362 int virtio_gpu_update_dmabuf(VirtIOGPU *g,
363 uint32_t scanout_id,
364 struct virtio_gpu_simple_resource *res,