fix UAF: NULL last_hovered_view when view is destroyed

W_ViewDestroyedFn hook clears last_hovered_view when the pointed-to
view is destroyed. Prevents use-after-free in motion handler when
the hovering over a view inside a dialog that is then closed.
This commit is contained in:
lkn 2026-06-24 00:20:07 +02:00
parent 9c954de71e
commit 144b089dff
4 changed files with 17 additions and 0 deletions

View File

@ -46,6 +46,7 @@ void (*W_DragIconHideFn)(void) = NULL;
* cursor changes. accepted=True means the view accepts the drop. */
void (*W_DragCursorFeedbackFn)(Bool accepted) = NULL;
void (*W_SetCursorImageFn)(const char *name) = NULL;
void (*W_ViewDestroyedFn)(struct W_View *view) = NULL;
extern void wl_view_destroy_backing_impl(unsigned long id);
@ -487,6 +488,7 @@ static void wl_destroy(void *vctx, W_View *view)
pixman_image_t *img = (pixman_image_t *)W_GetViewBacking(view->window);
if (img)
pixman_image_unref(img);
if (W_ViewDestroyedFn) W_ViewDestroyedFn(view);
view_table_remove(view->window);
}

View File

@ -475,6 +475,10 @@ wl_display_open(const char *name)
extern void wl_set_cursor_image(const char *name);
W_SetCursorImageFn = wl_set_cursor_image;
extern void (*W_ViewDestroyedFn)(struct W_View *view);
extern void wl_view_destroyed_hook(struct W_View *v);
W_ViewDestroyedFn = wl_view_destroyed_hook;
extern int (*W_WLPointerGrabFn)(WNativeWindow, WNativeWindow,
unsigned int, int, int, unsigned long);
extern void (*W_WLPointerUngrabFn)(unsigned long);

View File

@ -394,6 +394,11 @@ wl_view_scene_node_set_enabled(unsigned long id, int enabled)
void wl_view_destroy_backing_impl(unsigned long id)
{
/* NULL out last_hovered_view if it points to this dying view.
* Avoids UAF when the motion handler reads the stale pointer. */
if (wl_state.last_hovered_view
&& (unsigned long)wl_state.last_hovered_view->window == id)
wl_state.last_hovered_view = NULL;
struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)id);
if (!fb) return;
wl_list_remove(&fb->link);

View File

@ -16,6 +16,12 @@
/* Forward declarations for functions defined in other wl_*.c files */
void W_WL_EnqueueEvent(struct W_Screen *scr, const WMEvent *ev, struct W_View *target);
extern void (*W_SetCursorImageFn)(const char *name);
void wl_view_destroyed_hook(struct W_View *v)
{
if (wl_state.last_hovered_view == v)
wl_state.last_hovered_view = NULL;
}
void wl_grab_apply_motion(void);
void wl_update_pointer_focus(uint32_t time_msec);
WMScreen *wl_get_wmscreen(void);