From 0fcbe20cad5ebbac635195672467b4dc8d25debb Mon Sep 17 00:00:00 2001 From: lkn Date: Tue, 23 Jun 2026 22:50:27 +0200 Subject: [PATCH] fix UAF: get WApplication before wUnmanageWindow frees wwin wApplicationOf must be called before wUnmanageWindow because the latter frees the WWindow struct. Accessing app->main_window_desc afterward is a use-after-free. --- src/backend/wayland/wl_xdg.c | 10 +--------- src/dock.c | 3 +-- src/window.c | 10 ++++++++++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/backend/wayland/wl_xdg.c b/src/backend/wayland/wl_xdg.c index d2a315c..cabd0e6 100644 --- a/src/backend/wayland/wl_xdg.c +++ b/src/backend/wayland/wl_xdg.c @@ -402,16 +402,8 @@ handle_toplevel_unmap(struct wl_listener *listener, void *data) WObjDescriptor *desc = wm_backend->context_find(view->id, WM_CTX_CLIENT_WIN); if (desc && desc->parent_type == WCLASS_WINDOW) { WWindow *wwin = (WWindow *)desc->parent; - WNativeWindow main_win = wwin->main_window; + wwin->flags.destroyed = 1; wUnmanageWindow(wwin, False, True); - /* Destroy the WApplication (and its appicon) if this was the - * main window. Mirrors handleDestroyNotify in event.c. */ - WApplication *app = wApplicationOf(main_win); - if (app) { - if (main_win == app->main_window) - app->refcount = 0; - wApplicationDestroy(app); - } } } } diff --git a/src/dock.c b/src/dock.c index ace8466..d77fd6d 100644 --- a/src/dock.c +++ b/src/dock.c @@ -3534,8 +3534,7 @@ static void iconDblClick(WObjDescriptor *desc, WMEvent *event) if (btn->icon->owner && !(event->u.button.state & WM_MOD_CONTROL)) { wapp = wApplicationOf(btn->icon->owner->main_window); - - assert(wapp != NULL); + if (!wapp) return; unhideHere = (event->u.button.state & WM_MOD_SHIFT); diff --git a/src/window.c b/src/window.c index 4c1a559..2204422 100644 --- a/src/window.c +++ b/src/window.c @@ -1655,6 +1655,16 @@ void wUnmanageWindow(WWindow *wwin, Bool restore, Bool destroyed) wm_backend->netwm_cleanup_frame_extents(wwin); + /* NULL out appicon owner before freeing so dock icon handlers + * (iconDblClick) don't access freed memory on Wayland where + * toplevel unmap fires synchronously during event dispatch. */ + if (wwin->main_window) { + WApplication *oapp = wApplicationOf(wwin->main_window); + if (oapp && oapp->app_icon && oapp->app_icon->icon + && oapp->app_icon->icon->owner == wwin) + oapp->app_icon->icon->owner = NULL; + } + wWindowDestroy(wwin); wm_backend->event_flush(); }