From 3aa31823dbc3dd026ce08958ca5324d7af94a86a Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Tue, 5 May 2020 15:40:43 +0200 Subject: [PATCH] xwayland: Clear private on device removal Xwayland uses the device private to point to the `xwl_seat`. Device may be removed at any time, including on suspend. On resume, if the DIX code ends up calling a function that requires the `xwl_seat` such as `xwl_set_cursor()` we may end up pointing at random data. Make sure the clear the device private data on removal so that we don't try to use it and crash later. Signed-off-by: Olivier Fourdan Reviewed-by: Peter Hutterer https://gitlab.freedesktop.org/xorg/xserver/issues/709 (cherry picked from commit 4195e8035645007be313ade79032b8d561ceec6c) --- hw/xwayland/xwayland-input.c | 55 +++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index ba2febc1d..d069f72f6 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -831,6 +831,9 @@ remove_sync_pending(DeviceIntPtr dev) struct xwl_seat *xwl_seat = dev->public.devicePrivate; struct sync_pending *p, *npd; + if (!xwl_seat) + return; + xorg_list_for_each_entry_safe(p, npd, &xwl_seat->sync_pending, l) { if (p->pending_dev == dev) { xorg_list_del(&xwl_seat->sync_pending); @@ -857,11 +860,15 @@ static Bool keyboard_check_repeat (DeviceIntPtr dev, XkbSrvInfoPtr xkbi, unsigned key) { struct xwl_seat *xwl_seat = dev->public.devicePrivate; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; + struct xwl_screen *xwl_screen; struct wl_callback *callback; struct sync_pending *p; + if (!xwl_seat) + return FALSE; + /* Make sure we didn't miss a possible reply from the compositor */ + xwl_screen = xwl_seat->xwl_screen; xwl_sync_events (xwl_screen); xorg_list_for_each_entry(p, &xwl_seat->sync_pending, l) { @@ -1149,6 +1156,21 @@ add_device(struct xwl_seat *xwl_seat, return dev; } +static void +disable_device(DeviceIntPtr dev) +{ + DisableDevice(dev, TRUE); + dev->public.devicePrivate = NULL; +} + +static void +enable_device(struct xwl_seat *xwl_seat, DeviceIntPtr dev) +{ + dev->public.devicePrivate = xwl_seat; + EnableDevice(dev, TRUE); +} + + static void init_pointer(struct xwl_seat *xwl_seat) { @@ -1162,7 +1184,7 @@ init_pointer(struct xwl_seat *xwl_seat) add_device(xwl_seat, "xwayland-pointer", xwl_pointer_proc); ActivateDevice(xwl_seat->pointer, TRUE); } - EnableDevice(xwl_seat->pointer, TRUE); + enable_device(xwl_seat, xwl_seat->pointer); } static void @@ -1172,7 +1194,7 @@ release_pointer(struct xwl_seat *xwl_seat) xwl_seat->wl_pointer = NULL; if (xwl_seat->pointer) - DisableDevice(xwl_seat->pointer, TRUE); + disable_device(xwl_seat->pointer); } static void @@ -1196,7 +1218,7 @@ init_relative_pointer(struct xwl_seat *xwl_seat) xwl_pointer_proc_relative); ActivateDevice(xwl_seat->relative_pointer, TRUE); } - EnableDevice(xwl_seat->relative_pointer, TRUE); + enable_device(xwl_seat, xwl_seat->relative_pointer); } static void @@ -1208,7 +1230,7 @@ release_relative_pointer(struct xwl_seat *xwl_seat) } if (xwl_seat->relative_pointer) - DisableDevice(xwl_seat->relative_pointer, TRUE); + disable_device(xwl_seat->relative_pointer); } static void @@ -1225,7 +1247,7 @@ init_keyboard(struct xwl_seat *xwl_seat) add_device(xwl_seat, "xwayland-keyboard", xwl_keyboard_proc); ActivateDevice(xwl_seat->keyboard, TRUE); } - EnableDevice(xwl_seat->keyboard, TRUE); + enable_device(xwl_seat, xwl_seat->keyboard); xwl_seat->keyboard->key->xkbInfo->checkRepeat = keyboard_check_repeat; if (xwl_seat->xwl_screen->wp_grab) { @@ -1245,7 +1267,7 @@ release_keyboard(struct xwl_seat *xwl_seat) if (xwl_seat->keyboard) { remove_sync_pending(xwl_seat->keyboard); - DisableDevice(xwl_seat->keyboard, TRUE); + disable_device(xwl_seat->keyboard); } } @@ -1261,8 +1283,7 @@ init_touch(struct xwl_seat *xwl_seat) add_device(xwl_seat, "xwayland-touch", xwl_touch_proc); ActivateDevice(xwl_seat->touch, TRUE); } - EnableDevice(xwl_seat->touch, TRUE); - + enable_device(xwl_seat, xwl_seat->touch); } static void @@ -1272,7 +1293,7 @@ release_touch(struct xwl_seat *xwl_seat) xwl_seat->wl_touch = NULL; if (xwl_seat->touch) - DisableDevice(xwl_seat->touch, TRUE); + disable_device(xwl_seat->touch); } static void @@ -1431,19 +1452,19 @@ tablet_handle_done(void *data, struct zwp_tablet_v2 *tablet) xwl_seat->stylus = add_device(xwl_seat, "xwayland-stylus", xwl_tablet_proc); ActivateDevice(xwl_seat->stylus, TRUE); } - EnableDevice(xwl_seat->stylus, TRUE); + enable_device(xwl_seat, xwl_seat->stylus); if (xwl_seat->eraser == NULL) { xwl_seat->eraser = add_device(xwl_seat, "xwayland-eraser", xwl_tablet_proc); ActivateDevice(xwl_seat->eraser, TRUE); } - EnableDevice(xwl_seat->eraser, TRUE); + enable_device(xwl_seat, xwl_seat->eraser); if (xwl_seat->puck == NULL) { xwl_seat->puck = add_device(xwl_seat, "xwayland-cursor", xwl_tablet_proc); ActivateDevice(xwl_seat->puck, TRUE); } - EnableDevice(xwl_seat->puck, TRUE); + enable_device(xwl_seat, xwl_seat->puck); } static void @@ -1458,11 +1479,11 @@ tablet_handle_removed(void *data, struct zwp_tablet_v2 *tablet) will re-use the same X devices */ if (xorg_list_is_empty(&xwl_seat->tablets)) { if (xwl_seat->stylus) - DisableDevice(xwl_seat->stylus, TRUE); + disable_device(xwl_seat->stylus); if (xwl_seat->eraser) - DisableDevice(xwl_seat->eraser, TRUE); + disable_device(xwl_seat->eraser); if (xwl_seat->puck) - DisableDevice(xwl_seat->puck, TRUE); + disable_device(xwl_seat->puck); /* pads are removed separately */ } @@ -2524,6 +2545,8 @@ sprite_check_lost_focus(SpritePtr sprite, WindowPtr window) return FALSE; xwl_seat = device->public.devicePrivate; + if (!xwl_seat) + return FALSE; master = GetMaster(device, POINTER_OR_FLOAT); if (!master || !master->lastSlave)