Merge branch 'wip/zdi-fixes-xwayland-24.1-branch' into 'xwayland-24.1'

[xwayland 24.1] Backport the latest batch of security issues

See merge request xorg/xserver!2230
This commit is contained in:
Peter Hutterer 2026-06-02 10:01:49 +10:00
commit a5ff888d88
8 changed files with 90 additions and 37 deletions

View file

@ -348,6 +348,9 @@ ScreenSaverFreeAttr(void *value, XID id)
dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
}
CheckScreenPrivate(pScreen);
/* CheckScreenPrivate may have freed pPriv (same pattern as
* CreateSaverWindow fix for ZDI-CAN-30168). */
pPriv = NULL;
return TRUE;
}
@ -479,6 +482,8 @@ CreateSaverWindow(ScreenPtr pScreen)
UninstallSaverColormap(pScreen);
pPriv->hasWindow = FALSE;
CheckScreenPrivate(pScreen);
/* Re-fetch pPriv since CheckScreenPrivate may have freed it */
pPriv = GetScreenPrivate(pScreen);
}
}

View file

@ -721,8 +721,29 @@ SyncChangeCounter(SyncCounter * pCounter, int64_t newval)
/* run through triggers to see if any become true */
for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
pnext = ptl->next;
if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval))
if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval)) {
(*ptl->pTrigger->TriggerFired) (ptl->pTrigger);
/* TriggerFired may have called SyncDeleteTriggerFromSyncObject
* for sibling triggers in the same Await group, freeing their
* trigger list nodes - potentially including pnext. Verify
* pnext is still on the counter's trigger list; if not,
* restart from the list head.
*
* Unlike miSyncTriggerFence() we cannot use a do/while
* restart loop here: counter trigger lists may contain alarm
* triggers which are not removed after firing and would cause
* an infinite loop when delta is 0.
*/
if (pnext) {
SyncTriggerList *tmp;
for (tmp = pCounter->sync.pTriglist; tmp; tmp = tmp->next) {
if (tmp == pnext)
break;
}
if (!tmp)
pnext = pCounter->sync.pTriglist;
}
}
}
if (IsSystemCounter(pCounter)) {
@ -1163,9 +1184,12 @@ FreeCounter(void *env, XID id)
SyncTriggerList *ptl, *pnext;
/* tell all the counter's triggers that counter has been destroyed */
for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) {
(*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
pnext = ptl->next;
nt_list_for_each_entry_safe(ptl, pnext, pCounter->sync.pTriglist, next) {
/* Remove it from the list first so CounterDestroyed
* callbacks have a valid list to iterate */
pCounter->sync.pTriglist = pnext;
if (ptl->pTrigger)
(*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
free(ptl); /* destroy the trigger list as we go */
}
if (IsSystemCounter(pCounter)) {
@ -1197,13 +1221,28 @@ FreeAwait(void *addr, XID id)
for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
numwaits--, pAwait++) {
/* If the counter is being destroyed, FreeCounter will delete
* the trigger list itself, so don't do it here.
/* If the counter is being destroyed, FreeCounter/miSyncDestroyFence
* will delete the trigger list itself, so don't do it here.
* However, we must NULL out the pTrigger pointer in the trigger list
* node so the destroy loop knows not to dereference it - the backing
* SyncAwait memory is about to be freed below.
*/
SyncObject *pSync = pAwait->trigger.pSync;
if (pSync && !pSync->beingDestroyed)
SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
if (pSync) {
if (!pSync->beingDestroyed) {
SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
} else {
SyncTriggerList *ptl;
nt_list_for_each_entry(ptl, pSync->pTriglist, next) {
if (ptl->pTrigger == &pAwait->trigger) {
ptl->pTrigger = NULL;
break;
}
}
}
}
}
free(pAwaitUnion);
return Success;

View file

@ -670,6 +670,10 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
* is BadFontName, indicating the alias resolution
* is complete.
*/
if (resolvedlen > XLFDMAXFONTNAMELEN) {
err = BadFontName;
goto ContBadFontName;
}
memcpy(tmp_pattern, resolved, resolvedlen);
if (c->haveSaved) {
char *tmpname;
@ -932,6 +936,10 @@ doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
memcpy(c->savedName, name, namelen + 1);
aliascount = 20;
}
if (namelen > XLFDMAXFONTNAMELEN) {
err = BadFontName;
goto ContBadFontName;
}
memmove(c->current.pattern, name, namelen);
c->current.patlen = namelen;
c->current.max_names = 1;

View file

@ -1144,8 +1144,7 @@ __glXDisp_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc)
ClientPtr client = cl->client;
xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc;
/* work around mesa bug, don't use REQUEST_SIZE_MATCH */
REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
REQUEST_SIZE_MATCH(xGLXGetFBConfigsSGIXReq);
return DoGetFBConfigs(cl, req->screen);
}
@ -1366,9 +1365,7 @@ __glXDisp_DestroyPixmap(__GLXclientState * cl, GLbyte * pc)
ClientPtr client = cl->client;
xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc;
/* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set
* length to 3 instead of 2 */
REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq);
REQUEST_SIZE_MATCH(xGLXDestroyPixmapReq);
return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
}
@ -1524,14 +1521,8 @@ __glXDisp_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
client->errorValue = req->numAttribs;
return BadValue;
}
#if 0
/* mesa sends an additional 8 bytes */
REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
#else
if (((sizeof(xGLXChangeDrawableAttributesReq) +
(req->numAttribs << 3)) >> 2) < client->req_len)
return BadLength;
#endif
return DoChangeDrawableAttributes(cl->client, req->drawable,
req->numAttribs, (CARD32 *) (req + 1));
@ -1598,8 +1589,7 @@ __glXDisp_DestroyWindow(__GLXclientState * cl, GLbyte * pc)
ClientPtr client = cl->client;
xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc;
/* mesa's glXDestroyWindow used to set length to 3 instead of 2 */
REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
REQUEST_SIZE_MATCH(xGLXDestroyWindowReq);
return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW);
}
@ -1960,8 +1950,7 @@ __glXDisp_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
ClientPtr client = cl->client;
xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *) pc;
/* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */
REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesReq);
return DoGetDrawableAttributes(cl, req->drawable);
}

View file

@ -235,7 +235,7 @@ __glXDispSwap_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc)
__GLX_DECLARE_SWAP_VARIABLES;
REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
REQUEST_SIZE_MATCH(xGLXGetFBConfigsSGIXReq);
__GLX_SWAP_INT(&req->screen);
return __glXDisp_GetFBConfigsSGIX(cl, pc);
@ -327,7 +327,7 @@ __glXDispSwap_DestroyPixmap(__GLXclientState * cl, GLbyte * pc)
__GLX_DECLARE_SWAP_VARIABLES;
REQUEST_AT_LEAST_SIZE(xGLXDestroyGLXPixmapReq);
REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq);
__GLX_SWAP_SHORT(&req->length);
__GLX_SWAP_INT(&req->glxpixmap);
@ -440,9 +440,7 @@ __glXDispSwap_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
client->errorValue = req->numAttribs;
return BadValue;
}
if (((sizeof(xGLXChangeDrawableAttributesReq) +
(req->numAttribs << 3)) >> 2) < client->req_len)
return BadLength;
REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
attribs = (CARD32 *) (req + 1);
__GLX_SWAP_INT_ARRAY(attribs, req->numAttribs << 1);
@ -514,7 +512,7 @@ __glXDispSwap_DestroyWindow(__GLXclientState * cl, GLbyte * pc)
__GLX_DECLARE_SWAP_VARIABLES;
REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
REQUEST_SIZE_MATCH(xGLXDestroyWindowReq);
__GLX_SWAP_INT(&req->glxwindow);
@ -723,7 +721,7 @@ __glXDispSwap_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
__GLX_DECLARE_SWAP_VARIABLES;
REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesReq);
__GLX_SWAP_SHORT(&req->length);
__GLX_SWAP_INT(&req->drawable);

View file

@ -57,7 +57,12 @@ typedef struct _OFclosure {
/* ListFontsWithInfo */
#define XLFDMAXFONTNAMELEN 256
/* libXfont2 allows font names/aliases up to MAXFONTNAMELEN (1024) bytes in
* fonts.alias files. The server's pattern buffers must be large enough to
* hold resolved alias targets returned by the font library.
* ZDI-CAN-30136
*/
#define XLFDMAXFONTNAMELEN 1024
typedef struct _LFWIstate {
char pattern[XLFDMAXFONTNAMELEN];
int patlen;

View file

@ -115,10 +115,14 @@ miSyncDestroyFence(SyncFence * pFence)
SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
SyncTriggerList *ptl, *pNext;
/* tell all the fence's triggers that the counter has been destroyed */
for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext) {
(*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
pNext = ptl->next;
/* tell all the fence's triggers that the fence has been destroyed.
* Update pTriglist before each callback and free so that FreeAwait
* sees a valid list head when scanning for triggers to NULL out.
*/
nt_list_for_each_entry_safe(ptl, pNext, pFence->sync.pTriglist, next) {
pFence->sync.pTriglist = pNext;
if (ptl->pTrigger)
(*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger);
free(ptl); /* destroy the trigger list as we go */
}

View file

@ -1616,6 +1616,11 @@ CheckKeyTypes(ClientPtr client,
*nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4);
return 0;
}
if (nMaps > XkbMaxLegalKeyCode + 1) {
*nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes,
XkbMaxLegalKeyCode + 1);
return 0;
}
}
else if (req->present & XkbKeyTypesMask) {
nMaps = xkb->map->num_types;
@ -1647,7 +1652,7 @@ CheckKeyTypes(ClientPtr client,
}
n = i + req->firstType;
width = wire->numLevels;
if (width < 1) {
if (width < 1 || width > XkbMaxShiftLevel) {
*nMapsRtrn = _XkbErrCode3(0x04, n, width);
return 0;
}