untrusted comment: verify with openbsd-76-base.pub RWTkuwn4mbq8opcnREeCIhncZ6s2VsSFIOG1s8piY+ct9RmiIvwteNgu+0NHIKllF5/zNSjN9x+eUueXqmU00mejSru2muvW4g4= OpenBSD 7.6 errata 009, February 25, 2025: Multiple X server issues. CVE-2025-26594 CVE-2025-26595 CVE-2025-26596 CVE-2025-26597 CVE-2025-26598 CVE-2025-26599 CVE-2025-26600 CVE-2025-26601 Apply by doing: signify -Vep /etc/signify/openbsd-76-base.pub -x 009_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/Xext/sync.c =================================================================== RCS file: /cvs/xenocara/xserver/Xext/sync.c,v diff -u -p -r1.21 sync.c --- xserver/Xext/sync.c 7 Apr 2024 11:42:56 -0000 1.21 +++ xserver/Xext/sync.c 19 Feb 2025 22:06:14 -0000 @@ -199,8 +199,8 @@ SyncAddTriggerToSyncObject(SyncTrigger * return Success; } - if (!(pCur = malloc(sizeof(SyncTriggerList)))) - return BadAlloc; + /* Failure is not an option, it's succeed or burst! */ + pCur = XNFalloc(sizeof(SyncTriggerList)); pCur->pTrigger = pTrigger; pCur->next = pTrigger->pSync->pTriglist; @@ -329,11 +329,6 @@ SyncInitTrigger(ClientPtr client, SyncTr client->errorValue = syncObject; return rc; } - if (pSync != pTrigger->pSync) { /* new counter for trigger */ - SyncDeleteTriggerFromSyncObject(pTrigger); - pTrigger->pSync = pSync; - newSyncObject = TRUE; - } } /* if system counter, ask it what the current value is */ @@ -355,6 +350,24 @@ SyncInitTrigger(ClientPtr client, SyncTr } } + if (changes & (XSyncCAValueType | XSyncCAValue)) { + if (pTrigger->value_type == XSyncAbsolute) + pTrigger->test_value = pTrigger->wait_value; + else { /* relative */ + Bool overflow; + + if (pCounter == NULL) + return BadMatch; + + overflow = checked_int64_add(&pTrigger->test_value, + pCounter->value, pTrigger->wait_value); + if (overflow) { + client->errorValue = pTrigger->wait_value >> 32; + return BadValue; + } + } + } + if (changes & XSyncCATestType) { if (pSync && SYNC_FENCE == pSync->type) { @@ -383,21 +396,11 @@ SyncInitTrigger(ClientPtr client, SyncTr } } - if (changes & (XSyncCAValueType | XSyncCAValue)) { - if (pTrigger->value_type == XSyncAbsolute) - pTrigger->test_value = pTrigger->wait_value; - else { /* relative */ - Bool overflow; - - if (pCounter == NULL) - return BadMatch; - - overflow = checked_int64_add(&pTrigger->test_value, - pCounter->value, pTrigger->wait_value); - if (overflow) { - client->errorValue = pTrigger->wait_value >> 32; - return BadValue; - } + if (changes & XSyncCACounter) { + if (pSync != pTrigger->pSync) { /* new counter for trigger */ + SyncDeleteTriggerFromSyncObject(pTrigger); + pTrigger->pSync = pSync; + newSyncObject = TRUE; } } @@ -405,8 +408,7 @@ SyncInitTrigger(ClientPtr client, SyncTr * a new counter on a trigger */ if (newSyncObject) { - if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success) - return rc; + SyncAddTriggerToSyncObject(pTrigger); } else if (pCounter && IsSystemCounter(pCounter)) { SyncComputeBracketValues(pCounter); @@ -797,8 +799,14 @@ SyncChangeAlarmAttributes(ClientPtr clie int status; XSyncCounter counter; Mask origmask = mask; - - counter = pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None; + SyncTrigger trigger; + Bool select_events_changed = FALSE; + Bool select_events_value; + int64_t delta; + + trigger = pAlarm->trigger; + delta = pAlarm->delta; + counter = trigger.pSync ? trigger.pSync->id : None; while (mask) { int index2 = lowbit(mask); @@ -814,24 +822,24 @@ SyncChangeAlarmAttributes(ClientPtr clie case XSyncCAValueType: mask &= ~XSyncCAValueType; /* sanity check in SyncInitTrigger */ - pAlarm->trigger.value_type = *values++; + trigger.value_type = *values++; break; case XSyncCAValue: mask &= ~XSyncCAValue; - pAlarm->trigger.wait_value = ((int64_t)values[0] << 32) | values[1]; + trigger.wait_value = ((int64_t)values[0] << 32) | values[1]; values += 2; break; case XSyncCATestType: mask &= ~XSyncCATestType; /* sanity check in SyncInitTrigger */ - pAlarm->trigger.test_type = *values++; + trigger.test_type = *values++; break; case XSyncCADelta: mask &= ~XSyncCADelta; - pAlarm->delta = ((int64_t)values[0] << 32) | values[1]; + delta = ((int64_t)values[0] << 32) | values[1]; values += 2; break; @@ -841,10 +849,8 @@ SyncChangeAlarmAttributes(ClientPtr clie client->errorValue = *values; return BadValue; } - status = SyncEventSelectForAlarm(pAlarm, client, - (Bool) (*values++)); - if (status != Success) - return status; + select_events_value = (Bool) (*values++); + select_events_changed = TRUE; break; default: @@ -853,25 +859,33 @@ SyncChangeAlarmAttributes(ClientPtr clie } } + if (select_events_changed) { + status = SyncEventSelectForAlarm(pAlarm, client, select_events_value); + if (status != Success) + return status; + } + /* "If the test-type is PositiveComparison or PositiveTransition * and delta is less than zero, or if the test-type is * NegativeComparison or NegativeTransition and delta is * greater than zero, a Match error is generated." */ if (origmask & (XSyncCADelta | XSyncCATestType)) { - if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || - (pAlarm->trigger.test_type == XSyncPositiveTransition)) - && pAlarm->delta < 0) + if ((((trigger.test_type == XSyncPositiveComparison) || + (trigger.test_type == XSyncPositiveTransition)) + && delta < 0) || - (((pAlarm->trigger.test_type == XSyncNegativeComparison) || - (pAlarm->trigger.test_type == XSyncNegativeTransition)) - && pAlarm->delta > 0) + (((trigger.test_type == XSyncNegativeComparison) || + (trigger.test_type == XSyncNegativeTransition)) + && delta > 0) ) { return BadMatch; } } /* postpone this until now, when we're sure nothing else can go wrong */ + pAlarm->delta = delta; + pAlarm->trigger = trigger; if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter, origmask & XSyncCAAllTrigger)) != Success) return status; Index: xserver/Xi/xibarriers.c =================================================================== RCS file: /cvs/xenocara/xserver/Xi/xibarriers.c,v diff -u -p -r1.6 xibarriers.c --- xserver/Xi/xibarriers.c 27 Jul 2019 07:57:08 -0000 1.6 +++ xserver/Xi/xibarriers.c 19 Feb 2025 22:06:14 -0000 @@ -129,14 +129,15 @@ static void FreePointerBarrierClient(str static struct PointerBarrierDevice *GetBarrierDevice(struct PointerBarrierClient *c, int deviceid) { - struct PointerBarrierDevice *pbd = NULL; + struct PointerBarrierDevice *p, *pbd = NULL; - xorg_list_for_each_entry(pbd, &c->per_device, entry) { - if (pbd->deviceid == deviceid) + xorg_list_for_each_entry(p, &c->per_device, entry) { + if (p->deviceid == deviceid) { + pbd = p; break; + } } - BUG_WARN(!pbd); return pbd; } @@ -337,6 +338,9 @@ barrier_find_nearest(BarrierScreenPtr cs double distance; pbd = GetBarrierDevice(c, dev->id); + if (!pbd) + continue; + if (pbd->seen) continue; @@ -445,6 +449,9 @@ input_constrain_cursor(DeviceIntPtr dev, nearest = &c->barrier; pbd = GetBarrierDevice(c, master->id); + if (!pbd) + continue; + new_sequence = !pbd->hit; pbd->seen = TRUE; @@ -485,6 +492,9 @@ input_constrain_cursor(DeviceIntPtr dev, int flags = 0; pbd = GetBarrierDevice(c, master->id); + if (!pbd) + continue; + pbd->seen = FALSE; if (!pbd->hit) continue; @@ -679,6 +689,9 @@ BarrierFreeBarrier(void *data, XID id) continue; pbd = GetBarrierDevice(c, dev->id); + if (!pbd) + continue; + if (!pbd->hit) continue; @@ -738,6 +751,8 @@ static void remove_master_func(void *res barrier = container_of(b, struct PointerBarrierClient, barrier); pbd = GetBarrierDevice(barrier, *deviceid); + if (!pbd) + return; if (pbd->hit) { BarrierEvent ev = { @@ -903,6 +918,10 @@ ProcXIBarrierReleasePointer(ClientPtr cl barrier = container_of(b, struct PointerBarrierClient, barrier); pbd = GetBarrierDevice(barrier, dev->id); + if (!pbd) { + client->errorValue = dev->id; + return BadDevice; + } if (pbd->barrier_event_id == event_id) pbd->release_event_id = event_id; Index: xserver/composite/compalloc.c =================================================================== RCS file: /cvs/xenocara/xserver/composite/compalloc.c,v diff -u -p -r1.16 compalloc.c --- xserver/composite/compalloc.c 11 Nov 2021 09:03:02 -0000 1.16 +++ xserver/composite/compalloc.c 19 Feb 2025 22:06:14 -0000 @@ -140,6 +140,7 @@ compRedirectWindow(ClientPtr pClient, Wi CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); WindowPtr pLayerWin; Bool anyMarked = FALSE; + int status = Success; if (pWin == cs->pOverlayWin) { return Success; @@ -218,13 +219,13 @@ compRedirectWindow(ClientPtr pClient, Wi if (!compCheckRedirect(pWin)) { FreeResource(ccw->id, RT_NONE); - return BadAlloc; + status = BadAlloc; } if (anyMarked) compHandleMarkedWindows(pWin, pLayerWin); - return Success; + return status; } void @@ -605,9 +606,12 @@ compAllocPixmap(WindowPtr pWin) int h = pWin->drawable.height + (bw << 1); PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h); CompWindowPtr cw = GetCompWindow(pWin); + Bool status; - if (!pPixmap) - return FALSE; + if (!pPixmap) { + status = FALSE; + goto out; + } if (cw->update == CompositeRedirectAutomatic) pWin->redirectDraw = RedirectDrawAutomatic; else @@ -621,14 +625,16 @@ compAllocPixmap(WindowPtr pWin) DamageRegister(&pWin->drawable, cw->damage); cw->damageRegistered = TRUE; } + status = TRUE; +out: /* Make sure our borderClip is up to date */ RegionUninit(&cw->borderClip); RegionCopy(&cw->borderClip, &pWin->borderClip); cw->borderClipX = pWin->drawable.x; cw->borderClipY = pWin->drawable.y; - return TRUE; + return status; } void Index: xserver/dix/devices.c =================================================================== RCS file: /cvs/xenocara/xserver/dix/devices.c,v diff -u -p -r1.32 devices.c --- xserver/dix/devices.c 4 Aug 2024 07:53:57 -0000 1.32 +++ xserver/dix/devices.c 19 Feb 2025 22:06:14 -0000 @@ -963,6 +963,23 @@ FreeAllDeviceClasses(ClassesPtr classes) } +static void +FreePendingFrozenDeviceEvents(DeviceIntPtr dev) +{ + QdEventPtr qe, tmp; + + if (!dev->deviceGrab.sync.frozen) + return; + + /* Dequeue any frozen pending events */ + xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) { + if (qe->device == dev) { + xorg_list_del(&qe->next); + free(qe); + } + } +} + /** * Close down a device and free all resources. * Once closed down, the driver will probably not expect you that you'll ever @@ -1027,6 +1044,7 @@ CloseDevice(DeviceIntPtr dev) free(dev->last.touches[j].valuators); free(dev->last.touches); dev->config_info = NULL; + FreePendingFrozenDeviceEvents(dev); dixFreePrivates(dev->devPrivates, PRIVATE_DEVICE); free(dev); } Index: xserver/dix/dispatch.c =================================================================== RCS file: /cvs/xenocara/xserver/dix/dispatch.c,v diff -u -p -r1.23 dispatch.c --- xserver/dix/dispatch.c 7 Apr 2024 11:42:56 -0000 1.23 +++ xserver/dix/dispatch.c 19 Feb 2025 22:06:14 -0000 @@ -3107,6 +3107,10 @@ ProcFreeCursor(ClientPtr client) rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR, client, DixDestroyAccess); if (rc == Success) { + if (pCursor == rootCursor) { + client->errorValue = stuff->id; + return BadCursor; + } FreeResource(stuff->id, RT_NONE); return Success; } Index: xserver/dix/main.c =================================================================== RCS file: /cvs/xenocara/xserver/dix/main.c,v diff -u -p -r1.18 main.c --- xserver/dix/main.c 11 Nov 2021 09:03:03 -0000 1.18 +++ xserver/dix/main.c 19 Feb 2025 22:06:14 -0000 @@ -231,6 +231,8 @@ dix_main(int argc, char *argv[], char *e FatalError("could not open default cursor font"); } + rootCursor = RefCursor(rootCursor); + #ifdef PANORAMIX /* * Consolidate window and colourmap information for each screen @@ -270,6 +272,8 @@ dix_main(int argc, char *argv[], char *e InputThreadInit(); Dispatch(); + + UnrefCursor(rootCursor); UndisplayDevices(); DisableAllDevices(); Index: xserver/xkb/XKBMisc.c =================================================================== RCS file: /cvs/xenocara/xserver/xkb/XKBMisc.c,v diff -u -p -r1.10 XKBMisc.c --- xserver/xkb/XKBMisc.c 11 Nov 2021 09:03:16 -0000 1.10 +++ xserver/xkb/XKBMisc.c 19 Feb 2025 22:06:15 -0000 @@ -553,6 +553,7 @@ XkbChangeTypesOfKey(XkbDescPtr xkb, i = XkbSetNumGroups(i, 0); xkb->map->key_sym_map[key].group_info = i; XkbResizeKeySyms(xkb, key, 0); + XkbResizeKeyActions(xkb, key, 0); return Success; } Index: xserver/xkb/xkb.c =================================================================== RCS file: /cvs/xenocara/xserver/xkb/xkb.c,v diff -u -p -r1.24.10.1 xkb.c --- xserver/xkb/xkb.c 29 Oct 2024 18:11:33 -0000 1.24.10.1 +++ xserver/xkb/xkb.c 19 Feb 2025 22:06:15 -0000 @@ -1093,10 +1093,10 @@ XkbSizeKeySyms(XkbDescPtr xkb, xkbGetMap len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc); symMap = &xkb->map->key_sym_map[rep->firstKeySym]; for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) { - if (symMap->offset != 0) { - nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width; - nSyms += nSymsThisKey; - } + nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width; + if (nSymsThisKey == 0) + continue; + nSyms += nSymsThisKey; } len += nSyms * 4; rep->totalSyms = nSyms; Index: xserver/xkb/xkbtext.c =================================================================== RCS file: /cvs/xenocara/xserver/xkb/xkbtext.c,v diff -u -p -r1.11 xkbtext.c --- xserver/xkb/xkbtext.c 11 Nov 2021 09:03:16 -0000 1.11 +++ xserver/xkb/xkbtext.c 19 Feb 2025 22:06:15 -0000 @@ -175,14 +175,14 @@ XkbVModMaskText(XkbDescPtr xkb, len = strlen(tmp) + 1 + (str == buf ? 0 : 1); if (format == XkbCFile) len += 4; - if ((str - (buf + len)) <= VMOD_BUFFER_SIZE) { - if (str != buf) { - if (format == XkbCFile) - *str++ = '|'; - else - *str++ = '+'; - len--; - } + if ((str - buf) + len > VMOD_BUFFER_SIZE) + continue; /* Skip */ + if (str != buf) { + if (format == XkbCFile) + *str++ = '|'; + else + *str++ = '+'; + len--; } if (format == XkbCFile) snprintf(str, VMOD_BUFFER_SIZE - len, "%sMask", tmp);