From patchwork Fri Dec 10 13:38:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 398422 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oBADdKEr030888 for ; Fri, 10 Dec 2010 13:39:41 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1DFAF9E915 for ; Fri, 10 Dec 2010 05:39:20 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTP id B10F49E759 for ; Fri, 10 Dec 2010 05:38:45 -0800 (PST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 10 Dec 2010 05:38:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.59,323,1288594800"; d="scan'208";a="635058345" Received: from unknown (HELO cantiga.alporthouse.com) ([10.255.16.52]) by fmsmga002.fm.intel.com with ESMTP; 10 Dec 2010 05:38:43 -0800 From: Chris Wilson To: xorg-devel@lists.x.org, dri-devel@lists.freedesktop.org Subject: [PATCH] glx: Refcnt the GLXDrawable to avoid use after free with multiple FreeResource Date: Fri, 10 Dec 2010 13:38:41 +0000 Message-Id: <1291988321-12556-1-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1291986983.11622.125.camel@thor.local> References: <1291986983.11622.125.camel@thor.local> MIME-Version: 1.0 Cc: =?UTF-8?q?Michel=20D=C3=A4nzer?= X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 10 Dec 2010 13:39:41 +0000 (UTC) X-MIME-Autoconverted: from base64 to 8bit by demeter1.kernel.org id oBADdKEr030888 diff --git a/glx/glxcmds.c b/glx/glxcmds.c index de9c3f0..b3ea784 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -529,6 +529,7 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client, *error = BadAlloc; return NULL; } + pGlxDraw->refcnt++; return pGlxDraw; } @@ -1099,8 +1100,10 @@ __glXDrawableInit(__GLXdrawable *drawable, drawable->pDraw = pDraw; drawable->type = type; drawable->drawId = drawId; + drawable->otherId = 0; drawable->config = config; drawable->eventMask = 0; + drawable->refcnt = 0; return GL_TRUE; } @@ -1130,14 +1133,18 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, pGlxDraw->destroy (pGlxDraw); return BadAlloc; } + pGlxDraw->refcnt++; - /* Add the glx drawable under the XID of the underlying X drawable - * too. That way we'll get a callback in DrawableGone and can - * clean up properly when the drawable is destroyed. */ - if (drawableId != glxDrawableId && - !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) { - pGlxDraw->destroy (pGlxDraw); - return BadAlloc; + if (drawableId != glxDrawableId) { + /* Add the glx drawable under the XID of the underlying X drawable + * too. That way we'll get a callback in DrawableGone and can + * clean up properly when the drawable is destroyed. */ + if (!AddResource(drawableId, __glXDrawableRes, pGlxDraw)) { + pGlxDraw->destroy (pGlxDraw); + return BadAlloc; + } + pGlxDraw->refcnt++; + pGlxDraw->otherId = drawableId; } return Success; diff --git a/glx/glxdrawable.h b/glx/glxdrawable.h index 2a365c5..80c3234 100644 --- a/glx/glxdrawable.h +++ b/glx/glxdrawable.h @@ -51,8 +51,11 @@ struct __GLXdrawable { void (*waitX)(__GLXdrawable *); void (*waitGL)(__GLXdrawable *); + int refcnt; /* number of resources handles referencing this */ + DrawablePtr pDraw; XID drawId; + XID otherId; /* for glx1.3 we need to track the original Drawable as well */ /* ** Either GLX_DRAWABLE_PIXMAP, GLX_DRAWABLE_WINDOW or diff --git a/glx/glxext.c b/glx/glxext.c index 4bd5d6b..77db8b0 100644 --- a/glx/glxext.c +++ b/glx/glxext.c @@ -128,13 +128,18 @@ static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid) * constructors, we added it as a glx drawable resource under both * its glx drawable ID and it X drawable ID. Remove the other * resource now so we don't a callback for freed memory. */ - if (glxPriv->drawId != glxPriv->pDraw->id) { - if (xid == glxPriv->drawId) - FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE); - else - FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE); + if (glxPriv->otherId) { + XID other = glxPriv->otherId; + glxPriv->otherId = 0; + if (xid == other) + FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE); + else + FreeResourceByType(other, __glXDrawableRes, TRUE); } + if (--glxPriv->refcnt) + return True; + for (c = glxAllContexts; c; c = next) { next = c->next; if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) {