dix: Fix segfault if CreateGC() failed in XaceHook()

CreateGC() allocates a new GC and then checks the resource access rights
with XaceHook().

If the call to XaceHook() fails (i.e. GC creation is not granted to the
client), CreateGC() exits early and calls FreeGC() to avoid leaking the
newly allocated GC.

If that happens, the screen's own CreateGC() has not yet been invoked,
and as a result the GC functions (GCfuncs) have not been set yet.

FreeGC() will invoke the funcs->DestroyClip() and the funcs->DestroyGC()
functions, but since those haven't been set, the Xserver will segfault
trying to call a NULL function.

To prevent that issue, make sure the GC's functions are initialized
prior to call them in FreeGC().

Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1625
Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
This commit is contained in:
Wanli Niu 2024-02-01 09:48:53 +01:00 committed by Olivier Fourdan
parent 9c7c470b12
commit e62246641b

View File

@ -770,14 +770,16 @@ FreeGC(void *value, XID gid)
GCPtr pGC = (GCPtr) value; GCPtr pGC = (GCPtr) value;
CloseFont(pGC->font, (Font) 0); CloseFont(pGC->font, (Font) 0);
(*pGC->funcs->DestroyClip) (pGC); if (pGC->funcs)
(*pGC->funcs->DestroyClip) (pGC);
if (!pGC->tileIsPixel) if (!pGC->tileIsPixel)
(*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap); (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap);
if (pGC->stipple) if (pGC->stipple)
(*pGC->pScreen->DestroyPixmap) (pGC->stipple); (*pGC->pScreen->DestroyPixmap) (pGC->stipple);
(*pGC->funcs->DestroyGC) (pGC); if (pGC->funcs)
(*pGC->funcs->DestroyGC) (pGC);
if (pGC->dash != DefaultDash) if (pGC->dash != DefaultDash)
free(pGC->dash); free(pGC->dash);
dixFreeObjectWithPrivates(pGC, PRIVATE_GC); dixFreeObjectWithPrivates(pGC, PRIVATE_GC);