From 9bafb01b0447ec732b2136a64ead69f62456530d Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Tue, 14 Feb 2023 18:53:22 +0900 Subject: [PATCH] ecore_wl2_tbmsurface: Fix use after free This patch fixes the following problem +-----------------------------------------------------------------------+ |ERROR: AddressSanitizer: heap-use-after-free on address 0x007fa46ce840 | | at pc 0x007faaee4c68 bp 0x007fd4c23230 sp 0x007fd4c23248 | |READ of size 4 at 0x007fa46ce840 thread T0 | |#0 0x7faaee4c64 in _tbm_surface_queue_is_valid | |#1 0x7faaeee8a0 in tbm_surface_queue_release | |#2 0x7faded480c in buffer_release | |#3 0x7faa4d3fd4 in ffi_call_SYSV | |#4 0x7faa4d2ba0 in ffi_call_int | |#5 0x7fad00f720 in wl_closure_invoke | |#6 0x7fad002a58 in dispatch_event | | | |freed by thread T0 here: | |#1 0x7faaef1284 in tbm_surface_queue_destroy | |#2 0x7faded5a68 in _evas_tbmbuf_surface_destroy | |||#3 0x7faded3648 in ecore_wl2_surface_destroy | |#4 0x7fa3d395c0 in _evas_outbuf_free | |#5 0x7fa3d37d90 in evas_render_engine_software_generic_clean | |#6 0x7fa3d37d90 in eng_output_free | +-----------------------------------------------------------------------+ Change-Id: I1feda9e7d8fa0832dc0a0fe83af637d897a3ef8c --- src/lib/ecore_wl2/ecore_wl2_private.h | 1 + src/lib/ecore_wl2/ecore_wl2_tbmsurface.c | 31 ++++++++++++------------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/lib/ecore_wl2/ecore_wl2_private.h b/src/lib/ecore_wl2/ecore_wl2_private.h index ad96fb0..d9af9c3 100644 --- a/src/lib/ecore_wl2/ecore_wl2_private.h +++ b/src/lib/ecore_wl2/ecore_wl2_private.h @@ -816,6 +816,7 @@ typedef struct _Ecore_Wl2_Buffer struct wayland_tbm_client *tbm_client; tbm_surface_h tbm_surface; tbm_surface_info_s tbm_info; + Eina_List *attach_tbm_surfaces; void *tbm_queue; int wait_release; Eina_Bool resize : 1; diff --git a/src/lib/ecore_wl2/ecore_wl2_tbmsurface.c b/src/lib/ecore_wl2/ecore_wl2_tbmsurface.c index a539818..a2d84ba 100755 --- a/src/lib/ecore_wl2/ecore_wl2_tbmsurface.c +++ b/src/lib/ecore_wl2/ecore_wl2_tbmsurface.c @@ -106,16 +106,18 @@ static void buffer_release(void *data, struct wl_buffer *buffer EINA_UNUSED) { if (!data) return; - void *tbm_queue = NULL; tbm_surface_h tbm_surface = data; tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; + Ecore_Wl2_Buffer *surf = NULL; - tbm_surface_internal_get_user_data(tbm_surface, KEY_WINDOW, (void **)&tbm_queue); - if (tbm_queue) + tbm_surface_internal_get_user_data(tbm_surface, KEY_WINDOW, (void **)&surf); + if (surf && surf->tbm_queue) { - tsq_err = tbm_surface_queue_release(tbm_queue, tbm_surface); + tsq_err = tbm_surface_queue_release(surf->tbm_queue, tbm_surface); if (tsq_err != TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST) tbm_surface_internal_unref(tbm_surface); + + surf->attach_tbm_surfaces = eina_list_remove(surf->attach_tbm_surfaces, tbm_surface); } else tbm_surface_internal_unref(tbm_surface); @@ -209,7 +211,7 @@ _evas_tbmbuf_surface_assign(Ecore_Wl2_Surface *surface, void *priv_data) tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_WL_BUFFER, buffer); tbm_surface_internal_add_user_data(surf->tbm_surface, KEY_WINDOW, NULL); - tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_WINDOW, surf->tbm_queue); + tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_WINDOW, surf); wl_buffer_add_listener(buffer, &buffer_listener, surf->tbm_surface); } @@ -353,6 +355,7 @@ _evas_tbmbuf_surface_post(Ecore_Wl2_Surface *surface, void *priv_data, Eina_Rect /* pair with buffer release event */ tbm_surface_internal_ref(surf->tbm_surface); + surf->attach_tbm_surfaces = eina_list_append(surf->attach_tbm_surfaces, surf->tbm_surface); ecore_wl2_window_commit(surface->wl2_win, EINA_TRUE); ret = tbm_surface_queue_enqueue(surf->tbm_queue, surf->tbm_surface); @@ -371,8 +374,7 @@ _evas_tbmbuf_surface_destroy(Ecore_Wl2_Surface *surface, void *priv_data) { Ecore_Wl2_Buffer *surf = NULL; Ecore_Wl2_Tbmbuf_Private *p = priv_data; - int i, num_surface = 0; - tbm_surface_h *surfaces; + tbm_surface_h tbm_surface; if (!surface) return; if (!p) return; @@ -382,18 +384,9 @@ _evas_tbmbuf_surface_destroy(Ecore_Wl2_Surface *surface, void *priv_data) { if (surf->tbm_queue && tbm_queue_ref == 0) { - tbm_surface_queue_get_surfaces(surf->tbm_queue, NULL, &num_surface); - if (num_surface) - { - surfaces = calloc(num_surface, sizeof(*surfaces)); - if (surfaces) - { - tbm_surface_queue_get_surfaces(surf->tbm_queue, surfaces, &num_surface); - for (i = 0; i < num_surface; i++) - tbm_surface_internal_set_user_data(surfaces[i], KEY_WINDOW, NULL); - free(surfaces); - } - } + EINA_LIST_FREE(surf->attach_tbm_surfaces, tbm_surface) + tbm_surface_internal_set_user_data(tbm_surface, KEY_WINDOW, NULL); + tbm_surface_queue_destroy(surf->tbm_queue); surf->tbm_queue = NULL; } -- 2.7.4