From b67052742980fd3ec669100048da71e09aa61358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 19 Jun 2020 18:10:18 +0200 Subject: [PATCH] xwayland: Free all remaining events in xwl_present_cleanup These events aren't reachable after xwl_present_cleanup, so they're leaked if we don't free them first. This requires storing the pixmap pointer in struct xwl_present_window. Luckily, the buffer pointer isn't used for anything, so just replace that. v2: * Bump pixmap reference count in xwl_present_flip and drop it in xwl_present_free_event, fixes use-after-free in the latter due to the pixmap already being destroyed. Reviewed-by: Dave Airlie --- hw/xwayland/xwayland-present.c | 33 +++++++++++++++++---------------- hw/xwayland/xwayland-present.h | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index 30835b030..181e923b9 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -120,6 +120,16 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) static void xwl_present_free_event(struct xwl_present_event *event) { + if (!event) + return; + + if (event->pixmap) { + if (!event->buffer_released) + xwl_pixmap_del_buffer_release_cb(event->pixmap); + + dixDestroyPixmap(event->pixmap, event->pixmap->drawable.id); + } + xorg_list_del(&event->list); free(event); } @@ -144,21 +154,10 @@ xwl_present_cleanup(WindowPtr window) xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->event_list, list) xwl_present_free_event(event); - /* Clear remaining buffer releases and inform Present about free ressources */ - event = xwl_present_window->sync_flip; - xwl_present_window->sync_flip = NULL; - if (event) { - if (event->buffer_released) { - xwl_present_free_event(event); - } else { - event->pending = FALSE; - event->abort = TRUE; - } - } - xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_queue, list) { - xorg_list_del(&event->list); - event->abort = TRUE; - } + xwl_present_free_event(xwl_present_window->sync_flip); + + xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_queue, list) + xwl_present_free_event(event); /* Clear timer */ xwl_present_free_timer(xwl_present_window); @@ -356,6 +355,7 @@ xwl_present_queue_vblank(WindowPtr present_window, return BadAlloc; event->event_id = event_id; + event->pixmap = NULL; event->xwl_present_window = xwl_present_window; event->target_msc = msc; @@ -459,11 +459,12 @@ xwl_present_flip(WindowPtr present_window, if (!event) return FALSE; + pixmap->refcnt++; buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, NULL); event->event_id = event_id; event->xwl_present_window = xwl_present_window; - event->buffer = buffer; + event->pixmap = pixmap; event->target_msc = target_msc; event->pending = TRUE; event->abort = FALSE; diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h index d29430205..a3de1a523 100644 --- a/hw/xwayland/xwayland-present.h +++ b/hw/xwayland/xwayland-present.h @@ -59,7 +59,7 @@ struct xwl_present_event { Bool buffer_released; struct xwl_present_window *xwl_present_window; - struct wl_buffer *buffer; + PixmapPtr pixmap; struct xorg_list list; };