From: zackattackz Subject: [PATCH] systray: fix iterator UAF in on_change_systray Patch adapted for original tint2 (o9000/tint2) by danieln@maboxlinux.org on_change_systray() iterates systray.list_icons and calls reparent_icon() for each icon not yet reparented. If the XEMBED handshake fails, reparent_icon() calls remove_icon(), which g_slist_remove()s and g_free()s the current node. The loop then advances via l = l->next on the freed node, and the next iteration dereferences l->data on garbage memory (SIGSEGV). Trigger: any tray client that requests dock then destroys its window before the embed completes — e.g. Steam's transient 200x200 loader icon, Electron apps (Vesktop/Discord) that tear down their GdkWindow mid-embed. Fix: capture l->next at the top of the loop body, before any call that might free the current node. remove_icon() only frees the current node, so the pre-captured next pointer stays valid. This is the same iterator-invalidation pattern fixed in uevent_handler() by the glib2.76 patch (issue #4). That fix addressed one occurrence; this is the missed sibling in systraybar.c. Tested with a reproducer that queues N_SYSTEM_TRAY_REQUEST_DOCK events then destroys the windows before on_change_systray can reparent them: unpatched → SIGSEGV within a few rounds; patched → all rounds survive. --- src/systray/systraybar.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/systray/systraybar.c b/src/systray/systraybar.c index 2a9fafe..5eb5c6f 100644 --- a/src/systray/systraybar.c +++ b/src/systray/systraybar.c @@ -292,9 +292,10 @@ void on_change_systray(void *obj) } TrayWindow *traywin; - GSList *l; + GSList *l, *next; int i; - for (i = 1, l = systray.list_icons; l; i++, l = l->next) { + for (i = 1, l = systray.list_icons; l; i++, l = next) { + next = l->next; traywin = (TrayWindow *)l->data; traywin->y = posy;