From 8802f7f0d8137b631209eaee115acb88871859f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 15 Jun 2020 23:30:08 +0200
Subject: [PATCH] stage/x11: Check that message is WM_PROTOCOLS before assuming
 so

When a touch sequence was rejected, we'd update the event timestamps of
incoming touch events to help with implementing grabs. This was done by
sending a ClientMessage with a counter, and comparing the counter to
decide whether we're seing a replayed event or not.

This had the unforseen consequence that we would potentially end up
destroying all actors including the stage, since, when mutter receives a
ClientMessage event, it would assume that it's a WM_PROTOCOLS event, and
handle it as such. The problem with this approach is that it would
ignore fact that there might be other ClientMessage types sent to it,
for example the touch synchronization one. What could happen is that the
touch count value would match up with the value of the WM_DELETE_WINDOW
atom, clutter would treat this as WM_PROTOCOLS:WM_DELETE_WINDOW, which
it'd translate to clutter_actor_destroy(stage).

Destroying the stage in such a way is not expected, and caused wierd
crashes in different places depending on what was going on.

This commit make sure we only treat WM_PROTOCOLS client messages as
WM_PROTOCOLS client messages effectively avoiding the issue.

This fixes crashes such as:

 #0  meta_window_get_buffer_rect (window=0x0, rect=rect@entry=0x7ffd7fc62e40) at core/window.c:4396
 #1  0x00007f1e2634837f in get_top_visible_window_actor (compositor=0x297d700, compositor=0x297d700) at compositor/compositor.c:1059
 #2  meta_compositor_sync_stack (compositor=0x297d700, stack=<optimized out>, stack@entry=0x26e3140) at compositor/compositor.c:1176
 #3  0x00007f1e263757ac in meta_stack_tracker_sync_stack (tracker=0x297dbc0) at core/stack-tracker.c:871
 #4  0x00007f1e26375899 in stack_tracker_sync_stack_later (data=<optimized out>) at core/stack-tracker.c:881
 #5  0x00007f1e26376914 in run_repaint_laters (laters_list=0x7f1e2663b7d8 <laters+24>) at core/util.c:809
 #6  run_all_repaint_laters (data=<optimized out>) at core/util.c:826
 #7  0x00007f1e26b18325 in _clutter_run_repaint_functions (flags=flags@entry=CLUTTER_REPAINT_FLAGS_PRE_PAINT) at clutter-main.c:3448
 #8  0x00007f1e26b18fc5 in master_clock_update_stages (master_clock=0x32d6a80, stages=0x4e5a740) at clutter-master-clock-default.c:437
 #9  clutter_clock_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at clutter-master-clock-default.c:567
 #10 0x00007f1e27e48049 in g_main_dispatch (context=0x225b8d0) at gmain.c:3175
 #11 g_main_context_dispatch (context=context@entry=0x225b8d0) at gmain.c:3828
 #12 0x00007f1e27e483a8 in g_main_context_iterate (context=0x225b8d0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3901
 #13 0x00007f1e27e4867a in g_main_loop_run (loop=0x24e29f0) at gmain.c:4097
 #14 0x00007f1e2636a3dc in meta_run () at core/main.c:666
 #15 0x000000000040219c in main (argc=1, argv=0x7ffd7fc63238) at ../src/main.c:534

and

 #0  0x00007f93943c1f25 in raise () at /usr/lib/libc.so.6
 #1  0x00007f93943ab897 in abort () at /usr/lib/libc.so.6
 #2  0x00007f9393e1e062 in g_assertion_message (domain=<optimized out>, file=<optimized out>, line=<optimized out>, func=0x7f93933e6860 <__func__.116322> "meta_x11_get_stage_window",
 #3  0x00007f9393e4ab1d in g_assertion_message_expr ()
 #4  0x00007f939338ecd7 in meta_x11_get_stage_window (stage=<optimized out>) at ../mutter/src/backends/x11/meta-stage-x11.c:923
 #5  0x00007f939339e599 in meta_backend_x11_cm_translate_device_event (x11=<optimized out>, device_event=0x55bc8bcfd6b0) at ../mutter/src/backends/x11/cm/meta-backend-x11-cm.c:381
 #6  0x00007f939339f2e2 in meta_backend_x11_translate_device_event (device_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:179
 #7  0x00007f939339f2e2 in translate_device_event (device_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:208
 #8  0x00007f939339f2e2 in maybe_spoof_event_as_stage_event (input_event=0x55bc8bcfd6b0, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:284
 #9  0x00007f939339f2e2 in handle_input_event (event=0x7fff62d60490, x11=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:309
 #10 0x00007f939339f2e2 in handle_host_xevent (event=0x7fff62d60490, backend=0x55bc89dd5220) at ../mutter/src/backends/x11/meta-backend-x11.c:413
 #11 0x00007f939339f2e2 in x_event_source_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at ../mutter/src/backends/x11/meta-backend-x11.c:467
 #12 0x00007f9393e6c39e in g_main_dispatch (context=0x55bc89dd03e0) at ../glib/glib/gmain.c:3179
 #13 0x00007f9393e6c39e in g_main_context_dispatch (context=context@entry=0x55bc89dd03e0) at ../glib/glib/gmain.c:3844
 #14 0x00007f9393e6e1b1 in g_main_context_iterate (context=0x55bc89dd03e0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/glib/gmain.c:3917
 #15 0x00007f9393e6f0c3 in g_main_loop_run (loop=0x55bc8a042640) at ../glib/glib/gmain.c:4111
 #16 0x00007f9393369a0c in meta_run () at ../mutter/src/core/main.c:676
 #17 0x000055bc880f2426 in main (argc=<optimized out>, argv=<optimized out>) at ../gnome-shell/src/main.c:552

Related: https://gitlab.gnome.org/GNOME/mutter/-/issues/338
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/951

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1317
(cherry picked from commit e5ea8f54836ed2d041f0caa420ee1bcee0ff146a)
---
 src/backends/x11/meta-stage-x11.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/backends/x11/meta-stage-x11.c b/src/backends/x11/meta-stage-x11.c
index 0f39bf990..d8c6860a0 100644
--- a/src/backends/x11/meta-stage-x11.c
+++ b/src/backends/x11/meta-stage-x11.c
@@ -896,12 +896,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
       g_debug ("Client message for stage, win:0x%x",
                (unsigned int) xevent->xany.window);
 
-      if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
+      if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
         {
-          event->any.type = CLUTTER_DELETE;
-          event->any.stage = stage;
-          res = TRUE;
+          if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
+            {
+              event->any.type = CLUTTER_DELETE;
+              event->any.stage = stage;
+              res = TRUE;
+            }
         }
+
       break;
 
     default:
-- 
2.32.0

