summaryrefslogtreecommitdiff
path: root/Xi
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2024-01-30 11:11:54 +1000
committerMarge Bot <emma+marge@anholt.net>2024-09-01 23:12:28 +0000
commite7c876ab0b0daa546a23d4ef82537fdf8fd88e04 (patch)
tree3ddf8559dad353ba00ec776a5781282621d33585 /Xi
parent9b983fecf999b9f50946973f2379a5ce00491cad (diff)
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>
Diffstat (limited to 'Xi')
-rw-r--r--Xi/xichangehierarchy.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
index 99cc25045..8e7a0dcae 100644
--- a/Xi/xichangehierarchy.c
+++ b/Xi/xichangehierarchy.c
@@ -50,6 +50,7 @@
#include "extnsionst.h"
#include "exglobals.h"
#include "geext.h"
+#include "misc.h"
#include "xace.h"
#include "xiquerydevice.h" /* for GetDeviceUse */
#include "xkbsrv.h"
@@ -217,36 +218,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;