Fedora Account System
Red Hat Associate
Red Hat Customer
present_clear_window_notifies() does not unlink notify entries from the per-window list before freeing window_priv. When the window is subsequently destroyed or reused, the stale list entries are traversed, resulting in a use-after-free. An authenticated X client can trigger this by creating cross-window Present notifies and then destroying the target window. Both the Present and SYNC extensions must be enabled (they are by default). The use-after-free can lead to denial of service (crash) or potentially information disclosure. Fixed in: xorg-server-21.1.25 and xwayland-24.1.14 * Patch From 4ce3e830831dbeae1a54e510b78c4e09fb294605 Mon Sep 17 00:00:00 2001 From: Peter Hutterer <peter.hutterer> Date: Wed, 26 Aug 2026 17:04:47 +1000 Subject: [PATCH xserver] present: unlink notifies from window list in present_clear_window_notifies When a window is destroyed, present_clear_window_notifies() does not remove the notify list node from the window. The notify may then be freed as part of the window_priv, leaving dangling pointers in place. When the vblank owning the notify is later torn down, present_free_window_notify() calls xorg_list_del() which writes through these dangling pointers (use-after-free write). This happens when Present cross-window notifies are used: a PresentPixmap on window A can reference window B as a notify target. An untriggered wait_fence keeps the vblank alive so that B can be destroyed first, creating the dangling-pointer window. Fix this by calling the free function we have (and moving the window reset into that function too). present_clear_window_notifies is only called from one place anyway. This vulnerability was discovered by: Anonymous working with TrendAI Zero Day Initiative ZDI-CAN-31830 CVE-2026-93515 Assisted-by: Claude:claude-opus-4-6 #+begin_src diff --- present/present_notify.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/present/present_notify.c b/present/present_notify.c index 1f9ff7474145..7cb0ad5b2dc8 100644 --- a/present/present_notify.c +++ b/present/present_notify.c @@ -25,34 +25,35 @@ /* ,* Mark all pending notifies for 'window' as invalid when ,* the window is destroyed ,*/ void present_clear_window_notifies(WindowPtr window) { - present_notify_ptr notify; + present_notify_ptr notify, tmp; present_window_priv_ptr window_priv = present_window_priv(window); if (!window_priv) return; - xorg_list_for_each_entry(notify, &window_priv->notifies, window_list) { - notify->window = NULL; + xorg_list_for_each_entry_safe(notify, tmp, &window_priv->notifies, window_list) { + present_free_window_notify(notify); } } /* ,* 'notify' is being freed; remove it from the window's notify list ,*/ void present_free_window_notify(present_notify_ptr notify) { + notify->window = NULL; xorg_list_del(¬ify->window_list); } /* ,* 'notify' is new; add it to the specified window ,*/ int -- 2.55.0 #+end_src