Package: src:gtk+3.0
Version: 3.24.49-3
Severity: important
Tags: upstream fixed-upstream patch
Forwarded: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8882

Hi,

Please backport one upstream commit to gtk+3.0 in trixie:

  Commit: a18367522093de5ae355c0203559c26fa88ee6aa
  Title:  "x11: Call DeqAsyncHandler() earlier."
  GTK MR: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8882
  First upstream release with the fix: GTK 3.24.51 (2025-09-29)

Note: I wrote that commit. I am also a Mozilla engineer. I work on
Firefox on Linux with GTK. That is how I found this bug.

What the patch does
-------------------

The bug is in gdk/x11/gdkasync.c. The function send_event_handler()
does two things in order:

  1. It schedules an idle callback. The idle callback runs on the
     main thread, uses `state`, and frees it.
  2. It calls DeqAsyncHandler(state->dpy, &state->async), which
     also reads `state`.

The idle callback can run on the main thread before
send_event_handler() reaches step 2. When that happens, `state` is
freed in step 1. Then DeqAsyncHandler() reads `state->dpy` and
`&state->async` after they were freed. That is the use-after-free.

The fix is simple. Call DeqAsyncHandler() before scheduling the
idle, so the dequeue is done before the callback can ever run.
Two lines move. Here is the diff:

    diff --git a/gdk/x11/gdkasync.c b/gdk/x11/gdkasync.c
    --- a/gdk/x11/gdkasync.c
    +++ b/gdk/x11/gdkasync.c
    @@ -166,6 +166,8 @@ send_event_handler (Display *dpy,
                                True);
            }

    +      DeqAsyncHandler(state->dpy, &state->async);
    +
           if (state->callback)
             {
               guint id;
    @@ -173,8 +175,6 @@ send_event_handler (Display *dpy,
               g_source_set_name_by_id (id, "[gtk+] callback_idle");
             }

    -      DeqAsyncHandler(state->dpy, &state->async);
    -
           return (rep->generic.type != X_Error);
         }

Why it shows up in Firefox
--------------------------

Firefox has a thread called WebRender. WebRender calls
eglMakeCurrent(). That call ends up in _XReply() on a non-main
thread. _XReply() then invokes send_event_handler(). But
send_event_handler() was built to run only on the main thread. So
it races with the idle callback that runs on the main thread.

How often it happens
--------------------

Mozilla crash-stats shows about 368 submitted crash reports for
this signature in the last 30 days. That is about 12 per day across
Firefox users on Linux/X11. Firefox's crash reporter is opt-in --
the user has to choose to send the report after a crash. So 368 is
a lower bound. We usually consider this a high volume.

Approximate share of the submitted reports by distro:

  Debian 13 (gtk+3.0 3.24.49-3): about 45 percent
  Ubuntu 24.04 (3.24.41):        about 25 percent
  Ubuntu 22.04 (3.24.33):        about 15 percent
  Other (Kali, Pop!_OS, etc.):   about 15 percent

Evidence the fix works
----------------------

Arch Linux shipped GTK 3.24.51 on 2025-09-29. Before that, Arch
users were about 60 percent of all the submitted reports for this
signature. One week after the update, Arch dropped to 0 percent.
The fix clears the crash. It also did not break anything in this
code path.

Debian status
-------------

The fix is already in unstable. Sid ships gtk+3.0 3.24.52-1. What we need is
a cherry-pick of commit a18367522093de5ae355c0203559c26fa88ee6aa
onto trixie's 3.24.49-3 source package. The target is
trixie-proposed-updates for the next point release.

Thanks,
Kui-Feng Lee

References:
  Upstream MR:    https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8882
  Upstream patch:
https://gitlab.gnome.org/GNOME/gtk/-/commit/a18367522093de5ae355c0203559c26fa88ee6aa
  Public crash search:
    https://crash-stats.mozilla.org/search/?signature=~send_event_handler

Reply via email to