xwayland: Clear up x_cursor on UnrealizeCursor()

In Xwayland's xwl_unrealize_cursor(), the x_cursor is cleared up only
when a device value is provided to the UnrealizeCursor() routine, but
if the device is NULL as called from FreeCursor(), the corresponding
x_cursor for the xwl_seat is left untouched.

This might cause a segfault when trying to access the unrealized
cursor's devPrivates in xwl_seat_set_cursor().

A possible occurrence of this is the client changing the cursor, the
Xserver calling FreeCursor() which does UnrealizeCursor() and then
the Wayland server sending a pointer enter event, which invokes
xwl_seat_set_cursor() while the seat's x_cursor has just been
unrealized.

To avoid this, walk through all the xwl_seats and clear up all x_cursor
matching the cursor being unrealized.

Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Olivier Fourdan 2016-09-22 09:38:50 +02:00 committed by Adam Jackson
parent b79eaf1184
commit 862a3dab28

View File

@ -76,6 +76,7 @@ static Bool
xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
{
PixmapPtr pixmap;
struct xwl_screen *xwl_screen;
struct xwl_seat *xwl_seat;
pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
@ -85,9 +86,9 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, NULL);
/* When called from FreeCursor(), device is always NULL */
if (device) {
xwl_seat = device->public.devicePrivate;
if (xwl_seat && cursor == xwl_seat->x_cursor)
xwl_screen = xwl_screen_get(screen);
xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
if (cursor == xwl_seat->x_cursor)
xwl_seat->x_cursor = NULL;
}