Skip to content

Commit e1324ec

Browse files
elmarcoMichael Tokarev
authored andcommitted
ui/win32: fix potential use-after-free with dbus shared memory
DisplaySurface may be free before the pixman image is freed, since the image is refcounted and used by different objects, including pending dbus messages. Furthermore, setting the destroy function in create_displaysurface_from() isn't appropriate, as it may not be used, and may be overriden as in ramfb. Set the destroy function when the shared handle is set, use the HANDLE directly for destroy data, using a single common helper qemu_pixman_win32_image_destroy(). Signed-off-by: Marc-André Lureau <[email protected]> Reviewed-by: Akihiko Odaki <[email protected]> Message-ID: <[email protected]> (cherry picked from commit 330ef31) Signed-off-by: Michael Tokarev <[email protected]>
1 parent 9391f41 commit e1324ec

File tree

4 files changed

+21
-34
lines changed

4 files changed

+21
-34
lines changed

hw/display/virtio-gpu.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,16 +238,6 @@ static uint32_t calc_image_hostmem(pixman_format_code_t pformat,
238238
return height * stride;
239239
}
240240

241-
#ifdef WIN32
242-
static void
243-
win32_pixman_image_destroy(pixman_image_t *image, void *data)
244-
{
245-
HANDLE handle = data;
246-
247-
qemu_win32_map_free(pixman_image_get_data(image), handle, &error_warn);
248-
}
249-
#endif
250-
251241
static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
252242
struct virtio_gpu_ctrl_command *cmd)
253243
{
@@ -308,7 +298,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
308298
bits, c2d.height ? res->hostmem / c2d.height : 0);
309299
#ifdef WIN32
310300
if (res->image) {
311-
pixman_image_set_destroy_function(res->image, win32_pixman_image_destroy, res->handle);
301+
pixman_image_set_destroy_function(res->image, qemu_pixman_win32_image_destroy, res->handle);
312302
}
313303
#endif
314304
}
@@ -1327,7 +1317,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
13271317
return -EINVAL;
13281318
}
13291319
#ifdef WIN32
1330-
pixman_image_set_destroy_function(res->image, win32_pixman_image_destroy, res->handle);
1320+
pixman_image_set_destroy_function(res->image, qemu_pixman_win32_image_destroy, res->handle);
13311321
#endif
13321322

13331323
res->addrs = g_new(uint64_t, res->iov_cnt);

include/ui/qemu-pixman.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ void qemu_pixman_glyph_render(pixman_image_t *glyph,
9797

9898
void qemu_pixman_image_unref(pixman_image_t *image);
9999

100+
void qemu_pixman_win32_image_destroy(pixman_image_t *image, void *data);
101+
100102
G_DEFINE_AUTOPTR_CLEANUP_FUNC(pixman_image_t, qemu_pixman_image_unref)
101103

102104
#endif /* QEMU_PIXMAN_H */

ui/console.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -461,24 +461,6 @@ void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
461461
surface->handle = h;
462462
surface->handle_offset = offset;
463463
}
464-
465-
static void
466-
win32_pixman_image_destroy(pixman_image_t *image, void *data)
467-
{
468-
DisplaySurface *surface = data;
469-
470-
if (!surface->handle) {
471-
return;
472-
}
473-
474-
assert(surface->handle_offset == 0);
475-
476-
qemu_win32_map_free(
477-
pixman_image_get_data(surface->image),
478-
surface->handle,
479-
&error_warn
480-
);
481-
}
482464
#endif
483465

484466
DisplaySurface *qemu_create_displaysurface(int width, int height)
@@ -504,6 +486,8 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
504486

505487
#ifdef WIN32
506488
qemu_displaysurface_win32_set_handle(surface, handle, 0);
489+
pixman_image_set_destroy_function(surface->image,
490+
qemu_pixman_win32_image_destroy, handle);
507491
#endif
508492
return surface;
509493
}
@@ -519,10 +503,6 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
519503
width, height,
520504
(void *)data, linesize);
521505
assert(surface->image != NULL);
522-
#ifdef WIN32
523-
pixman_image_set_destroy_function(surface->image,
524-
win32_pixman_image_destroy, surface);
525-
#endif
526506

527507
return surface;
528508
}

ui/qemu-pixman.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
#include "qemu/osdep.h"
7+
#include "qapi/error.h"
78
#include "ui/console.h"
89
#include "standard-headers/drm/drm_fourcc.h"
910
#include "trace.h"
@@ -268,3 +269,17 @@ void qemu_pixman_glyph_render(pixman_image_t *glyph,
268269
pixman_image_unref(ibg);
269270
}
270271
#endif /* CONFIG_PIXMAN */
272+
273+
#ifdef WIN32
274+
void
275+
qemu_pixman_win32_image_destroy(pixman_image_t *image, void *data)
276+
{
277+
HANDLE handle = data;
278+
279+
qemu_win32_map_free(
280+
pixman_image_get_data(image),
281+
handle,
282+
&error_warn
283+
);
284+
}
285+
#endif

0 commit comments

Comments
 (0)