From a604a0a26791e9f352aad27232127d729bca4334 Mon Sep 17 00:00:00 2001 From: Erik Kurzinger Date: Thu, 10 Dec 2020 14:24:32 -0800 Subject: [PATCH xserver 26/27] glx: don't create implicit GLXWindow if one already exists If a GLXMakeCurrent request specifies an X window as its drawable, __glXGetDrawable will implicitly create a GLXWindow for it. However, the client may have already explicitly created a GLXWindow for that X window. If that happens, two __glXDrawableRes resources will be added to the window. If the explicitly-created GLXWindow is later destroyed by the client, DrawableGone will call FreeResourceByType on the X window, but this will actually free the resource for the implicitly-created GLXWindow, since that one would be at the head of the list. Then if the X window is destroyed after that, the resource for the explicitly-created GLXWindow will be freed. But that GLXWindow was already destroyed above. This crashes the server when it tries to call the destroyed GLXWindow's destructor. It also means the implicitly-created GLXWindow would have been leaked since the FreeResourceByType call mentioned above skips calling the destructor. To fix this, if __glXGetDrawable is given an X window, it should check if there is already a GLXWindow associated with it, and only create an implicit one if there is not. Signed-off-by: Erik Kurzinger Reviewed-by: Adam Jackson (cherry picked from commit b7a85e44da91d1663d5b4eabac06327c92a80f91) --- glx/glxcmds.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 37576b6ef..1b9ad6d14 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -487,8 +487,15 @@ __glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client, __GLXscreen *pGlxScreen; int rc; - if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, - DixWriteAccess, &pGlxDraw, &rc)) { + rc = dixLookupResourceByType((void **)&pGlxDraw, drawId, + __glXDrawableRes, client, DixWriteAccess); + if (rc == Success && + /* If pGlxDraw->drawId == drawId, drawId is a valid GLX drawable. + * Otherwise, if pGlxDraw->type == GLX_DRAWABLE_WINDOW, drawId is + * an X window, but the client has already created a GLXWindow + * associated with it, so we don't want to create another one. */ + (pGlxDraw->drawId == drawId || + pGlxDraw->type == GLX_DRAWABLE_WINDOW)) { if (glxc != NULL && glxc->config != NULL && glxc->config != pGlxDraw->config) { -- 2.31.1