From 38c5bc5e4974157131cda7647dde7b0f6ca6843e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 5 Oct 2016 15:21:57 +0200 Subject: [PATCH xf86-input-libinput] Fix crash when using threaded input and the first device goes away When the xserver uses threaded input, it keeps a pointer to the InputInfo passed into xf86AddEnabledDevice and calls pointer->read_input on events. But when the first enabled device goes away the pInfo we've passed into xf86AddEnabledDevice gets freed and eventually pInfo->read_input gets overwritten (or pInfo points to unmapped memory) leading to a segfault. This commit fixes this by replacing the pInfo passed into xf86AddEnabledDevice with a pointer to a global InputInfo stored inside the driver_context struct. Signed-off-by: Hans de Goede --- src/xf86libinput.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/xf86libinput.c b/src/xf86libinput.c index 21f87f5..485e212 100644 --- a/src/xf86libinput.c +++ b/src/xf86libinput.c @@ -86,6 +86,7 @@ struct xf86libinput_driver { struct libinput *libinput; + struct _InputInfoRec InputInfo; int device_enabled_count; }; @@ -582,7 +583,17 @@ xf86libinput_on(DeviceIntPtr dev) if (driver_context.device_enabled_count == 0) { #if HAVE_THREADED_INPUT - xf86AddEnabledDevice(pInfo); + /* + * The xserver keeps a pointer to the InputInfo passed into + * xf86AddEnabledDevice and calls pointer->read_input on + * events. Thus we cannot simply pass in our current pInfo + * as that will be deleted when the current input device gets + * unplugged. Instead pass in a pointer to a global + * InputInfo inside the driver_context. + */ + driver_context.InputInfo.fd = pInfo->fd; + driver_context.InputInfo.read_input = pInfo->read_input; + xf86AddEnabledDevice(&driver_context.InputInfo); #else /* Can't use xf86AddEnabledDevice on an epollfd */ AddEnabledDevice(pInfo->fd); @@ -606,7 +617,7 @@ xf86libinput_off(DeviceIntPtr dev) if (--driver_context.device_enabled_count == 0) { #if HAVE_THREADED_INPUT - xf86RemoveEnabledDevice(pInfo); + xf86RemoveEnabledDevice(&driver_context.InputInfo); #else RemoveEnabledDevice(pInfo->fd); #endif @@ -1923,7 +1934,7 @@ out: } static void -xf86libinput_read_input(InputInfoPtr pInfo) +xf86libinput_read_input(InputInfoPtr do_not_use) { struct libinput *libinput = driver_context.libinput; int rc; @@ -1934,9 +1945,8 @@ xf86libinput_read_input(InputInfoPtr pInfo) return; if (rc < 0) { - xf86IDrvMsg(pInfo, X_ERROR, - "Error reading events: %s\n", - strerror(-rc)); + xf86Msg(X_ERROR, "Error reading libinput events: %s\n", + strerror(-rc)); return; } -- 2.9.3