Xwayland crash using a free cursor in 1.19

Olivier Fourdan ofourdan at redhat.com
Mon Nov 14 17:08:33 UTC 2016


Hi

Just a quick heads up, I have been trying to investigate random crashes in Xwayland, something that occurs very randomly and really hard to reproduce.

It appears that, sometimes, Xwayland will try to use a pCursor that has just been freed, leading to a crash when trying to use that cursor in miPointerUpdateSprite().

Initially, I thought it might be related to the use of miPointerInvalidateSprite() in Xwayland that sets the pPointer->pSpriteCursor to an invalid value thus forcing the update of the cursor, because each time the crash would occur, pPointer->pSpriteCursor would be 0x1 (the invalid value set in miPointerInvalidateSprite()).

Every time, the pPointer->pCursor was freed, with both bits = 0x0 and refcnt = 0.

A typical backtrace would look like:

  miPointerUpdateSprite () at mipointer.c:465
  mieqProcessInputEvents () at mieq.c:559
  ProcessInputEvents () at xwayland-input.c:1229
  Dispatch () at dispatch.c:408
  dix_main () at main.c:287

As seen in:

https://bugzilla.redhat.com/show_bug.cgi?id=1388976
https://bugzilla.redhat.com/show_bug.cgi?id=1393158
https://bugzilla.redhat.com/show_bug.cgi?id=1385258

(Daniel's been posting in the last one)

But I also had another similar crash but with a different code path:

  miPointerUpdateSprite () at mipointer.c:476
  mieqProcessInputEvents () at mieq.c:563
  keyboard_handle_modifiers () at xwayland-input.c:677
  wl_closure_invoke () at src/connection.c:935
  dispatch_event () at src/wayland-client.c:1310
  dispatch_queue () at src/wayland-client.c:1456
  wl_display_dispatch_queue_pending () at src/wayland-client.c:1698
  wl_display_dispatch_pending () at src/wayland-client.c:1761
  xwl_read_events () at xwayland.c:565
  WaitForSomething () at WaitFor.c:224
  Dispatch () at dispatch.c:412
  dix_main () at main.c:287

Which makes me think that the use of miPointerInvalidateSprite() is not necessarily the problem. 

Instrumenting the code and checking if any device would still be using the cursor when freed from FreeCursor(), or checking if a master's cursor refcnt is 0 from mieqProcessInputEvents, I can see that the cursor is freed from CloseDownClient(), i.e. after an X client is gone.

So in some rare cases, CloseDownClient() will free the associated cursor(s) and immediately after, mieqProcessInputEvents() will invoke miPointerUpdateSprite() trying to use that (freed) cursor to update the pointer, and crash.

Pulling the strings from there, I see that the cursor should be updated in miPointerDisplayCursor() which is called from CheckMotion() (via PostNewCursor()) but only if the new sprite window is different from the old one, and the new one comes from XYToWindow().

Xwayland implements its own XYToWindow() that will return the root window when transitioning from an Xwayland window to a native Wayland surface (so that the X clients get a LeaveNotify event in this case, otherwise they might not be able to tell the cursor has left the X window, that was one of my patches).

So now I suspect the problem actually lies in xwl_xy_to_window() which somehow defeats the logic in CheckMotion(), but I don't know how to fix that issue yet...

Cheers,
Olivier



More information about the xorg-devel mailing list