untrusted comment: verify with openbsd-74-base.pub RWRoyQmAD08ajUp/O8ptcH5uSrSY7hCE5S4QJSn5VQXqhWf3EDnT0Xa+6TgR50DgHqEA0uPDStW5g7QGjdMwR/YuUJQ7WytmMQw= OpenBSD 7.4 errata 012, January 16, 2024: Fix multiple heap buffer overflows, out of bounds memory accesses and memory corruption in the GLX, SELinux and Xi extensions as well as in the main device and cursor handling code. CVE-2023-6816 CVE-2024-0229 CVE-2024-21885 CVE-2024-21886 CVE-2024-0408 CVE-2024-0409 Apply by doing: signify -Vep /etc/signify/openbsd-74-base.pub -x 012_xserver.patch.sig \ -m - | (cd /usr/xenocara && patch -p0) And then rebuild and install the X server: cd /usr/xenocara/xserver make -f Makefile.bsd-wrapper obj make -f Makefile.bsd-wrapper build Index: xserver/Xi/exevents.c =================================================================== RCS file: /cvs/xenocara/xserver/Xi/exevents.c,v diff -u -p -r1.27.6.1 exevents.c --- xserver/Xi/exevents.c 13 Dec 2023 07:04:00 -0000 1.27.6.1 +++ xserver/Xi/exevents.c 12 Jan 2024 08:59:10 -0000 @@ -605,6 +605,7 @@ DeepCopyPointerClasses(DeviceIntPtr from to->button = calloc(1, sizeof(ButtonClassRec)); if (!to->button) FatalError("[Xi] no memory for class shift.\n"); + to->button->numButtons = from->button->numButtons; } else classes->button = NULL; Index: xserver/Xi/xichangehierarchy.c =================================================================== RCS file: /cvs/xenocara/xserver/Xi/xichangehierarchy.c,v diff -u -p -r1.13 xichangehierarchy.c --- xserver/Xi/xichangehierarchy.c 25 Aug 2020 15:41:59 -0000 1.13 +++ xserver/Xi/xichangehierarchy.c 12 Jan 2024 08:59:10 -0000 @@ -270,7 +270,7 @@ remove_master(ClientPtr client, xXIRemov if (rc != Success) goto unwind; - if (!IsMaster(newptr)) { + if (!IsMaster(newptr) || !IsPointerDevice(newptr)) { client->errorValue = r->return_pointer; rc = BadDevice; goto unwind; @@ -281,7 +281,7 @@ remove_master(ClientPtr client, xXIRemov if (rc != Success) goto unwind; - if (!IsMaster(newkeybd)) { + if (!IsMaster(newkeybd) || !IsKeyboardDevice(newkeybd)) { client->errorValue = r->return_keyboard; rc = BadDevice; goto unwind; @@ -416,6 +416,11 @@ ProcXIChangeHierarchy(ClientPtr client) size_t len; /* length of data remaining in request */ int rc = Success; int flags[MAXDEVICES] = { 0 }; + enum { + NO_CHANGE, + FLUSH, + CHANGED, + } changes = NO_CHANGE; REQUEST(xXIChangeHierarchyReq); REQUEST_AT_LEAST_SIZE(xXIChangeHierarchyReq); @@ -465,8 +470,9 @@ ProcXIChangeHierarchy(ClientPtr client) rc = add_master(client, c, flags); if (rc != Success) goto unwind; - } + changes = FLUSH; break; + } case XIRemoveMaster: { xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; @@ -475,8 +481,9 @@ ProcXIChangeHierarchy(ClientPtr client) rc = remove_master(client, r, flags); if (rc != Success) goto unwind; - } + changes = FLUSH; break; + } case XIDetachSlave: { xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; @@ -485,8 +492,9 @@ ProcXIChangeHierarchy(ClientPtr client) rc = detach_slave(client, c, flags); if (rc != Success) goto unwind; - } + changes = CHANGED; break; + } case XIAttachSlave: { xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; @@ -495,16 +503,25 @@ ProcXIChangeHierarchy(ClientPtr client) rc = attach_slave(client, c, flags); if (rc != Success) goto unwind; + changes = CHANGED; + break; } + default: break; } + if (changes == FLUSH) { + XISendDeviceHierarchyEvent(flags); + memset(flags, 0, sizeof(flags)); + changes = NO_CHANGE; + } + len -= any->length * 4; any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); } unwind: - - XISendDeviceHierarchyEvent(flags); + if (changes != NO_CHANGE) + XISendDeviceHierarchyEvent(flags); return rc; } Index: xserver/Xi/xiquerypointer.c =================================================================== RCS file: /cvs/xenocara/xserver/Xi/xiquerypointer.c,v diff -u -p -r1.9 xiquerypointer.c --- xserver/Xi/xiquerypointer.c 27 Jul 2019 07:57:08 -0000 1.9 +++ xserver/Xi/xiquerypointer.c 12 Jan 2024 08:59:10 -0000 @@ -149,8 +149,7 @@ ProcXIQueryPointer(ClientPtr client) if (pDev->button) { int i; - rep.buttons_len = - bytes_to_int32(bits_to_bytes(pDev->button->numButtons)); + rep.buttons_len = bytes_to_int32(bits_to_bytes(256)); /* button map up to 255 */ rep.length += rep.buttons_len; buttons = calloc(rep.buttons_len, 4); if (!buttons) Index: xserver/dix/devices.c =================================================================== RCS file: /cvs/xenocara/xserver/dix/devices.c,v diff -u -p -r1.28.10.1 devices.c --- xserver/dix/devices.c 13 Dec 2023 07:04:00 -0000 1.28.10.1 +++ xserver/dix/devices.c 12 Jan 2024 08:59:10 -0000 @@ -447,14 +447,20 @@ DisableDevice(DeviceIntPtr dev, BOOL sen { DeviceIntPtr *prev, other; BOOL enabled; + BOOL dev_in_devices_list = FALSE; int flags[MAXDEVICES] = { 0 }; if (!dev->enabled) return TRUE; - for (prev = &inputInfo.devices; - *prev && (*prev != dev); prev = &(*prev)->next); - if (*prev != dev) + for (other = inputInfo.devices; other; other = other->next) { + if (other == dev) { + dev_in_devices_list = TRUE; + break; + } + } + + if (!dev_in_devices_list) return FALSE; TouchEndPhysicallyActiveTouches(dev); @@ -471,6 +477,13 @@ DisableDevice(DeviceIntPtr dev, BOOL sen 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 { for (other = inputInfo.devices; other; other = other->next) { @@ -505,6 +518,9 @@ DisableDevice(DeviceIntPtr dev, BOOL sen LeaveWindow(dev); SetFocusOut(dev); + for (prev = &inputInfo.devices; + *prev && (*prev != dev); prev = &(*prev)->next); + *prev = dev->next; dev->next = inputInfo.off_devices; inputInfo.off_devices = dev; @@ -1060,6 +1076,11 @@ CloseDownDevices(void) * to NULL and pretend nothing happened. */ for (dev = inputInfo.devices; dev; dev = dev->next) { + if (!IsMaster(dev) && !IsFloating(dev)) + dev->master = NULL; + } + + for (dev = inputInfo.off_devices; dev; dev = dev->next) { if (!IsMaster(dev) && !IsFloating(dev)) dev->master = NULL; } Index: xserver/dix/enterleave.c =================================================================== RCS file: /cvs/xenocara/xserver/dix/enterleave.c,v diff -u -p -r1.10 enterleave.c --- xserver/dix/enterleave.c 11 Nov 2021 09:03:03 -0000 1.10 +++ xserver/dix/enterleave.c 12 Jan 2024 08:59:11 -0000 @@ -615,9 +615,15 @@ FixDeviceValuator(DeviceIntPtr dev, devi ev->type = DeviceValuator; ev->deviceid = dev->id; - ev->num_valuators = nval < 3 ? nval : 3; + ev->num_valuators = nval < 6 ? nval : 6; ev->first_valuator = first; 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: ev->valuator2 = v->axisVal[first + 2]; case 2: @@ -626,7 +632,6 @@ FixDeviceValuator(DeviceIntPtr dev, devi ev->valuator0 = v->axisVal[first]; break; } - first += ev->num_valuators; } static void @@ -646,7 +651,7 @@ FixDeviceStateNotify(DeviceIntPtr dev, d ev->num_buttons = b->numButtons; memcpy((char *) ev->buttons, (char *) b->down, 4); } - else if (k) { + if (k) { ev->classes_reported |= (1 << KeyClass); ev->num_keys = k->xkbInfo->desc->max_key_code - k->xkbInfo->desc->min_key_code; @@ -670,14 +675,26 @@ FixDeviceStateNotify(DeviceIntPtr dev, d } } - +/** + * 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 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; - deviceStateNotify *ev, *sev; - deviceKeyStateNotify *kev; - deviceButtonStateNotify *bev; + deviceStateNotify *ev = sev; KeyClassPtr k; ButtonClassPtr b; @@ -690,87 +707,53 @@ DeliverStateNotifyEvent(DeviceIntPtr dev if ((b = dev->button) != NULL) { nbuttons = b->numButtons; - if (nbuttons > 32) + if (nbuttons > 32) /* first 32 are encoded in deviceStateNotify */ evcount++; } if ((k = dev->key) != NULL) { nkeys = k->xkbInfo->desc->max_key_code - k->xkbInfo->desc->min_key_code; - if (nkeys > 32) - evcount++; - if (nbuttons > 0) { + if (nkeys > 32) /* first 32 are encoded in deviceStateNotify */ evcount++; - } } if ((v = dev->valuator) != NULL) { nval = v->numAxes; - - if (nval > 3) - evcount++; - if (nval > 6) { - if (!(k && b)) - evcount++; - if (nval > 9) - evcount += ((nval - 7) / 3); - } + /* first three are encoded in deviceStateNotify, then + * it's 6 per deviceValuator event */ + evcount += ((nval - 3) + 6)/6; } - sev = ev = xallocarray(evcount, sizeof(xEvent)); - FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first); + BUG_RETURN(evcount <= ARRAY_SIZE(sev)); - if (b != NULL) { - FixDeviceStateNotify(dev, ev++, NULL, b, v, first); - first += 3; - nval -= 3; - if (nbuttons > 32) { - (ev - 1)->deviceid |= MORE_EVENTS; - bev = (deviceButtonStateNotify *) ev++; - bev->type = DeviceButtonStateNotify; - bev->deviceid = dev->id; - 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; - } + FixDeviceStateNotify(dev, ev, k, b, v, first); + + if (b != NULL && nbuttons > 32) { + deviceButtonStateNotify *bev = (deviceButtonStateNotify *) ++ev; + (ev - 1)->deviceid |= MORE_EVENTS; + bev->type = DeviceButtonStateNotify; + bev->deviceid = dev->id; + memcpy((char *) &bev->buttons[4], (char *) &b->down[4], + DOWN_LENGTH - 4); } - if (k != NULL) { - FixDeviceStateNotify(dev, ev++, k, NULL, v, first); - first += 3; - nval -= 3; - if (nkeys > 32) { - (ev - 1)->deviceid |= MORE_EVENTS; - 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; - } + if (k != NULL && nkeys > 32) { + deviceKeyStateNotify *kev = (deviceKeyStateNotify *) ++ev; + (ev - 1)->deviceid |= MORE_EVENTS; + kev->type = DeviceKeyStateNotify; + kev->deviceid = dev->id; + memmove((char *) &kev->keys[0], (char *) &k->down[4], 28); } + first = 3; + nval -= 3; while (nval > 0) { - FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first); - first += 3; - nval -= 3; - if (nval > 0) { - (ev - 1)->deviceid |= MORE_EVENTS; - FixDeviceValuator(dev, (deviceValuator *) ev++, v, first); - first += 3; - nval -= 3; - } + ev->deviceid |= MORE_EVENTS; + FixDeviceValuator(dev, (deviceValuator *) ++ev, v, first); + first += 6; + nval -= 6; } DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount, DeviceStateNotifyMask, NullGrab); - free(sev); } void @@ -784,8 +767,9 @@ DeviceFocusEvent(DeviceIntPtr dev, int t mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER); - /* XI 2 event */ - btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; + /* XI 2 event contains the logical button map - maps are CARD8 + * so we need 256 bits for the possibly maximum mapping */ + btlen = (mouse->button) ? bits_to_bytes(256) : 0; btlen = bytes_to_int32(btlen); len = sizeof(xXIFocusInEvent) + btlen * 4; Index: xserver/glx/glxcmds.c =================================================================== RCS file: /cvs/xenocara/xserver/glx/glxcmds.c,v diff -u -p -r1.20 glxcmds.c --- xserver/glx/glxcmds.c 11 Nov 2021 09:03:03 -0000 1.20 +++ xserver/glx/glxcmds.c 12 Jan 2024 08:59:11 -0000 @@ -48,6 +48,7 @@ #include "indirect_util.h" #include "protocol-versions.h" #include "glxvndabi.h" +#include "xace.h" static char GLXServerVendorName[] = "SGI"; @@ -1391,6 +1392,13 @@ DoCreatePbuffer(ClientPtr client, int sc config->rgbBits, 0); if (!pPixmap) 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 * resource so it and the DRI2 drawable will be reclaimed when the Index: xserver/hw/kdrive/ephyr/ephyrcursor.c =================================================================== RCS file: /cvs/xenocara/xserver/hw/kdrive/ephyr/ephyrcursor.c,v diff -u -p -r1.3 ephyrcursor.c --- xserver/hw/kdrive/ephyr/ephyrcursor.c 27 Jul 2019 07:57:12 -0000 1.3 +++ xserver/hw/kdrive/ephyr/ephyrcursor.c 12 Jan 2024 08:59:11 -0000 @@ -246,7 +246,7 @@ miPointerSpriteFuncRec EphyrPointerSprit Bool ephyrCursorInit(ScreenPtr screen) { - if (!dixRegisterPrivateKey(&ephyrCursorPrivateKey, PRIVATE_CURSOR_BITS, + if (!dixRegisterPrivateKey(&ephyrCursorPrivateKey, PRIVATE_CURSOR, sizeof(ephyrCursorRec))) return FALSE;