Multiple issues have been found in the X server and Xwayland

This commit is contained in:
purplerain 2024-01-16 14:54:32 +00:00
parent b5bb0bd1e8
commit 79d7f8454a
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
7 changed files with 114 additions and 84 deletions

View file

@ -605,6 +605,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
to->button = calloc(1, sizeof(ButtonClassRec)); to->button = calloc(1, sizeof(ButtonClassRec));
if (!to->button) if (!to->button)
FatalError("[Xi] no memory for class shift.\n"); FatalError("[Xi] no memory for class shift.\n");
to->button->numButtons = from->button->numButtons;
} }
else else
classes->button = NULL; classes->button = NULL;

View file

@ -270,7 +270,7 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES])
if (rc != Success) if (rc != Success)
goto unwind; goto unwind;
if (!IsMaster(newptr)) { if (!IsMaster(newptr) || !IsPointerDevice(newptr)) {
client->errorValue = r->return_pointer; client->errorValue = r->return_pointer;
rc = BadDevice; rc = BadDevice;
goto unwind; goto unwind;
@ -281,7 +281,7 @@ remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES])
if (rc != Success) if (rc != Success)
goto unwind; goto unwind;
if (!IsMaster(newkeybd)) { if (!IsMaster(newkeybd) || !IsKeyboardDevice(newkeybd)) {
client->errorValue = r->return_keyboard; client->errorValue = r->return_keyboard;
rc = BadDevice; rc = BadDevice;
goto unwind; goto unwind;
@ -416,6 +416,11 @@ ProcXIChangeHierarchy(ClientPtr client)
size_t len; /* length of data remaining in request */ size_t len; /* length of data remaining in request */
int rc = Success; int rc = Success;
int flags[MAXDEVICES] = { 0 }; int flags[MAXDEVICES] = { 0 };
enum {
NO_CHANGE,
FLUSH,
CHANGED,
} changes = NO_CHANGE;
REQUEST(xXIChangeHierarchyReq); REQUEST(xXIChangeHierarchyReq);
REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq);
@ -465,8 +470,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = add_master(client, c, flags); rc = add_master(client, c, flags);
if (rc != Success) if (rc != Success)
goto unwind; goto unwind;
} changes = FLUSH;
break; break;
}
case XIRemoveMaster: case XIRemoveMaster:
{ {
xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any;
@ -475,8 +481,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = remove_master(client, r, flags); rc = remove_master(client, r, flags);
if (rc != Success) if (rc != Success)
goto unwind; goto unwind;
} changes = FLUSH;
break; break;
}
case XIDetachSlave: case XIDetachSlave:
{ {
xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any;
@ -485,8 +492,9 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = detach_slave(client, c, flags); rc = detach_slave(client, c, flags);
if (rc != Success) if (rc != Success)
goto unwind; goto unwind;
} changes = CHANGED;
break; break;
}
case XIAttachSlave: case XIAttachSlave:
{ {
xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any;
@ -495,16 +503,25 @@ ProcXIChangeHierarchy(ClientPtr client)
rc = attach_slave(client, c, flags); rc = attach_slave(client, c, flags);
if (rc != Success) if (rc != Success)
goto unwind; goto unwind;
} changes = CHANGED;
break; break;
} }
default:
break;
}
if (changes == FLUSH) {
XISendDeviceHierarchyEvent(flags);
memset(flags, 0, sizeof(flags));
changes = NO_CHANGE;
}
len -= any->length * 4; len -= any->length * 4;
any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4);
} }
unwind: unwind:
if (changes != NO_CHANGE)
XISendDeviceHierarchyEvent(flags); XISendDeviceHierarchyEvent(flags);
return rc; return rc;
} }

View file

@ -149,8 +149,7 @@ ProcXIQueryPointer(ClientPtr client)
if (pDev->button) { if (pDev->button) {
int i; int i;
rep.buttons_len = rep.buttons_len = bytes_to_int32(bits_to_bytes(256)); /* button map up to 255 */
bytes_to_int32(bits_to_bytes(pDev->button->numButtons));
rep.length += rep.buttons_len; rep.length += rep.buttons_len;
buttons = calloc(rep.buttons_len, 4); buttons = calloc(rep.buttons_len, 4);
if (!buttons) if (!buttons)

View file

@ -447,14 +447,20 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
{ {
DeviceIntPtr *prev, other; DeviceIntPtr *prev, other;
BOOL enabled; BOOL enabled;
BOOL dev_in_devices_list = FALSE;
int flags[MAXDEVICES] = { 0 }; int flags[MAXDEVICES] = { 0 };
if (!dev->enabled) if (!dev->enabled)
return TRUE; return TRUE;
for (prev = &inputInfo.devices; for (other = inputInfo.devices; other; other = other->next) {
*prev && (*prev != dev); prev = &(*prev)->next); if (other == dev) {
if (*prev != dev) dev_in_devices_list = TRUE;
break;
}
}
if (!dev_in_devices_list)
return FALSE; return FALSE;
TouchEndPhysicallyActiveTouches(dev); TouchEndPhysicallyActiveTouches(dev);
@ -471,6 +477,13 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
flags[other->id] |= XISlaveDetached; flags[other->id] |= XISlaveDetached;
} }
} }
for (other = inputInfo.off_devices; other; other = other->next) {
if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) {
AttachDevice(NULL, other, NULL);
flags[other->id] |= XISlaveDetached;
}
}
} }
else { else {
for (other = inputInfo.devices; other; other = other->next) { for (other = inputInfo.devices; other; other = other->next) {
@ -505,6 +518,9 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
LeaveWindow(dev); LeaveWindow(dev);
SetFocusOut(dev); SetFocusOut(dev);
for (prev = &inputInfo.devices;
*prev && (*prev != dev); prev = &(*prev)->next);
*prev = dev->next; *prev = dev->next;
dev->next = inputInfo.off_devices; dev->next = inputInfo.off_devices;
inputInfo.off_devices = dev; inputInfo.off_devices = dev;
@ -1064,6 +1080,11 @@ CloseDownDevices(void)
dev->master = NULL; dev->master = NULL;
} }
for (dev = inputInfo.off_devices; dev; dev = dev->next) {
if (!IsMaster(dev) && !IsFloating(dev))
dev->master = NULL;
}
CloseDeviceList(&inputInfo.devices); CloseDeviceList(&inputInfo.devices);
CloseDeviceList(&inputInfo.off_devices); CloseDeviceList(&inputInfo.off_devices);

View file

@ -615,9 +615,15 @@ FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
ev->type = DeviceValuator; ev->type = DeviceValuator;
ev->deviceid = dev->id; ev->deviceid = dev->id;
ev->num_valuators = nval < 3 ? nval : 3; ev->num_valuators = nval < 6 ? nval : 6;
ev->first_valuator = first; ev->first_valuator = first;
switch (ev->num_valuators) { switch (ev->num_valuators) {
case 6:
ev->valuator2 = v->axisVal[first + 5];
case 5:
ev->valuator2 = v->axisVal[first + 4];
case 4:
ev->valuator2 = v->axisVal[first + 3];
case 3: case 3:
ev->valuator2 = v->axisVal[first + 2]; ev->valuator2 = v->axisVal[first + 2];
case 2: case 2:
@ -626,7 +632,6 @@ FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
ev->valuator0 = v->axisVal[first]; ev->valuator0 = v->axisVal[first];
break; break;
} }
first += ev->num_valuators;
} }
static void static void
@ -646,7 +651,7 @@ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
ev->num_buttons = b->numButtons; ev->num_buttons = b->numButtons;
memcpy((char *) ev->buttons, (char *) b->down, 4); memcpy((char *) ev->buttons, (char *) b->down, 4);
} }
else if (k) { if (k) {
ev->classes_reported |= (1 << KeyClass); ev->classes_reported |= (1 << KeyClass);
ev->num_keys = k->xkbInfo->desc->max_key_code - ev->num_keys = k->xkbInfo->desc->max_key_code -
k->xkbInfo->desc->min_key_code; k->xkbInfo->desc->min_key_code;
@ -670,14 +675,26 @@ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
} }
} }
/**
* The device state notify event is split across multiple 32-byte events.
* The first one contains the first 32 button state bits, the first 32
* key state bits, and the first 3 valuator values.
*
* If a device has more than that, the server sends out:
* - one deviceButtonStateNotify for buttons 32 and above
* - one deviceKeyStateNotify for keys 32 and above
* - one deviceValuator event per 6 valuators above valuator 4
*
* All events but the last one have the deviceid binary ORed with MORE_EVENTS,
*/
static void static void
DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win) DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
{ {
/* deviceStateNotify, deviceKeyStateNotify, deviceButtonStateNotify
* and one deviceValuator for each 6 valuators */
deviceStateNotify sev[3 + (MAX_VALUATORS + 6)/6];
int evcount = 1; int evcount = 1;
deviceStateNotify *ev, *sev; deviceStateNotify *ev = sev;
deviceKeyStateNotify *kev;
deviceButtonStateNotify *bev;
KeyClassPtr k; KeyClassPtr k;
ButtonClassPtr b; ButtonClassPtr b;
@ -690,87 +707,53 @@ DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
if ((b = dev->button) != NULL) { if ((b = dev->button) != NULL) {
nbuttons = b->numButtons; nbuttons = b->numButtons;
if (nbuttons > 32) if (nbuttons > 32) /* first 32 are encoded in deviceStateNotify */
evcount++; evcount++;
} }
if ((k = dev->key) != NULL) { if ((k = dev->key) != NULL) {
nkeys = k->xkbInfo->desc->max_key_code - k->xkbInfo->desc->min_key_code; nkeys = k->xkbInfo->desc->max_key_code - k->xkbInfo->desc->min_key_code;
if (nkeys > 32) if (nkeys > 32) /* first 32 are encoded in deviceStateNotify */
evcount++; evcount++;
if (nbuttons > 0) {
evcount++;
}
} }
if ((v = dev->valuator) != NULL) { if ((v = dev->valuator) != NULL) {
nval = v->numAxes; nval = v->numAxes;
/* first three are encoded in deviceStateNotify, then
if (nval > 3) * it's 6 per deviceValuator event */
evcount++; evcount += ((nval - 3) + 6)/6;
if (nval > 6) {
if (!(k && b))
evcount++;
if (nval > 9)
evcount += ((nval - 7) / 3);
}
} }
sev = ev = xallocarray(evcount, sizeof(xEvent)); BUG_RETURN(evcount <= ARRAY_SIZE(sev));
FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
if (b != NULL) { FixDeviceStateNotify(dev, ev, k, b, v, first);
FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
first += 3; if (b != NULL && nbuttons > 32) {
nval -= 3; deviceButtonStateNotify *bev = (deviceButtonStateNotify *) ++ev;
if (nbuttons > 32) { (ev - 1)->deviceid |= MORE_EVENTS;
(ev - 1)->deviceid |= MORE_EVENTS; bev->type = DeviceButtonStateNotify;
bev = (deviceButtonStateNotify *) ev++; bev->deviceid = dev->id;
bev->type = DeviceButtonStateNotify; memcpy((char *) &bev->buttons[4], (char *) &b->down[4],
bev->deviceid = dev->id; DOWN_LENGTH - 4);
memcpy((char *) &bev->buttons[4], (char *) &b->down[4],
DOWN_LENGTH - 4);
}
if (nval > 0) {
(ev - 1)->deviceid |= MORE_EVENTS;
FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
first += 3;
nval -= 3;
}
} }
if (k != NULL) { if (k != NULL && nkeys > 32) {
FixDeviceStateNotify(dev, ev++, k, NULL, v, first); deviceKeyStateNotify *kev = (deviceKeyStateNotify *) ++ev;
first += 3; (ev - 1)->deviceid |= MORE_EVENTS;
nval -= 3; kev->type = DeviceKeyStateNotify;
if (nkeys > 32) { kev->deviceid = dev->id;
(ev - 1)->deviceid |= MORE_EVENTS; memmove((char *) &kev->keys[0], (char *) &k->down[4], 28);
kev = (deviceKeyStateNotify *) ev++;
kev->type = DeviceKeyStateNotify;
kev->deviceid = dev->id;
memmove((char *) &kev->keys[0], (char *) &k->down[4], 28);
}
if (nval > 0) {
(ev - 1)->deviceid |= MORE_EVENTS;
FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
first += 3;
nval -= 3;
}
} }
first = 3;
nval -= 3;
while (nval > 0) { while (nval > 0) {
FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first); ev->deviceid |= MORE_EVENTS;
first += 3; FixDeviceValuator(dev, (deviceValuator *) ++ev, v, first);
nval -= 3; first += 6;
if (nval > 0) { nval -= 6;
(ev - 1)->deviceid |= MORE_EVENTS;
FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
first += 3;
nval -= 3;
}
} }
DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount, DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount,
DeviceStateNotifyMask, NullGrab); DeviceStateNotifyMask, NullGrab);
free(sev);
} }
void void
@ -784,8 +767,9 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER); mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
/* XI 2 event */ /* XI 2 event contains the logical button map - maps are CARD8
btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; * so we need 256 bits for the possibly maximum mapping */
btlen = (mouse->button) ? bits_to_bytes(256) : 0;
btlen = bytes_to_int32(btlen); btlen = bytes_to_int32(btlen);
len = sizeof(xXIFocusInEvent) + btlen * 4; len = sizeof(xXIFocusInEvent) + btlen * 4;

View file

@ -48,6 +48,7 @@
#include "indirect_util.h" #include "indirect_util.h"
#include "protocol-versions.h" #include "protocol-versions.h"
#include "glxvndabi.h" #include "glxvndabi.h"
#include "xace.h"
static char GLXServerVendorName[] = "SGI"; static char GLXServerVendorName[] = "SGI";
@ -1392,6 +1393,13 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
if (!pPixmap) if (!pPixmap)
return BadAlloc; return BadAlloc;
err = XaceHook(XACE_RESOURCE_ACCESS, client, glxDrawableId, RT_PIXMAP,
pPixmap, RT_NONE, NULL, DixCreateAccess);
if (err != Success) {
(*pGlxScreen->pScreen->DestroyPixmap) (pPixmap);
return err;
}
/* Assign the pixmap the same id as the pbuffer and add it as a /* Assign the pixmap the same id as the pbuffer and add it as a
* resource so it and the DRI2 drawable will be reclaimed when the * resource so it and the DRI2 drawable will be reclaimed when the
* pbuffer is destroyed. */ * pbuffer is destroyed. */

View file

@ -246,7 +246,7 @@ miPointerSpriteFuncRec EphyrPointerSpriteFuncs = {
Bool Bool
ephyrCursorInit(ScreenPtr screen) ephyrCursorInit(ScreenPtr screen)
{ {
if (!dixRegisterPrivateKey(&ephyrCursorPrivateKey, PRIVATE_CURSOR_BITS, if (!dixRegisterPrivateKey(&ephyrCursorPrivateKey, PRIVATE_CURSOR,
sizeof(ephyrCursorRec))) sizeof(ephyrCursorRec)))
return FALSE; return FALSE;