Xi: when removing a master search for a disabled paired device
If either the master pointer or keyboard was disabled, the respective GetMaster() call returns NULL, causing a segfault later accessing the deviceid. Fix this by looking in the off_devices list for any master device of the type we're looking for. Master devices lose the pairing when disabled (on enabling a keyboard we simply pair with the first available unpaired pointer). And for readability, split the device we get from the protocol request into a new "dev" variable instead of re-using ptr. Fixes #1611 Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1256>
This commit is contained in:
parent
f38faab295
commit
fd7da4bddd
|
@ -48,6 +48,7 @@
|
|||
#include "extnsionst.h"
|
||||
#include "exglobals.h"
|
||||
#include "geext.h"
|
||||
#include "misc.h"
|
||||
#include "xace.h"
|
||||
#include "xiquerydevice.h" /* for GetDeviceUse */
|
||||
#include "xkbsrv.h"
|
||||
|
@ -207,36 +208,56 @@ disable_clientpointer(DeviceIntPtr dev)
|
|||
}
|
||||
}
|
||||
|
||||
static DeviceIntPtr
|
||||
find_disabled_master(int type)
|
||||
{
|
||||
DeviceIntPtr dev;
|
||||
|
||||
/* Once a master device is disabled it loses the pairing, so returning the first
|
||||
* match is good enough */
|
||||
for (dev = inputInfo.off_devices; dev; dev = dev->next) {
|
||||
if (dev->type == type)
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES])
|
||||
{
|
||||
DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
|
||||
DeviceIntPtr dev, ptr, keybd, XTestptr, XTestkeybd;
|
||||
int rc = Success;
|
||||
|
||||
if (r->return_mode != XIAttachToMaster && r->return_mode != XIFloating)
|
||||
return BadValue;
|
||||
|
||||
rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess);
|
||||
rc = dixLookupDevice(&dev, r->deviceid, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
if (!IsMaster(ptr)) {
|
||||
if (!IsMaster(dev)) {
|
||||
client->errorValue = r->deviceid;
|
||||
rc = BadDevice;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* XXX: For now, don't allow removal of VCP, VCK */
|
||||
if (ptr == inputInfo.pointer ||ptr == inputInfo.keyboard) {
|
||||
if (dev == inputInfo.pointer || dev == inputInfo.keyboard) {
|
||||
rc = BadDevice;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
ptr = GetMaster(ptr, MASTER_POINTER);
|
||||
if ((ptr = GetMaster(dev, MASTER_POINTER)) == NULL)
|
||||
ptr = find_disabled_master(MASTER_POINTER);
|
||||
BUG_RETURN_VAL(ptr == NULL, BadDevice);
|
||||
rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
keybd = GetMaster(ptr, MASTER_KEYBOARD);
|
||||
|
||||
if ((keybd = GetMaster(dev, MASTER_KEYBOARD)) == NULL)
|
||||
keybd = find_disabled_master(MASTER_KEYBOARD);
|
||||
BUG_RETURN_VAL(keybd == NULL, BadDevice);
|
||||
rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
|
Loading…
Reference in New Issue