From patchwork Fri Dec 10 12:43:32 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 398302 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 oBAChoYP024333 for ; Fri, 10 Dec 2010 12:44:11 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 14FB49E7CC for ; Fri, 10 Dec 2010 04:43:50 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga03.intel.com (mga03.intel.com [143.182.124.21]) by gabe.freedesktop.org (Postfix) with ESMTP id 52ABD9E752 for ; Fri, 10 Dec 2010 04:43:42 -0800 (PST) Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 10 Dec 2010 04:43:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.59,323,1288594800"; d="scan'208";a="359854924" Received: from unknown (HELO cantiga.alporthouse.com) ([10.255.16.52]) by azsmga001.ch.intel.com with ESMTP; 10 Dec 2010 04:43:34 -0800 From: Chris Wilson To: xorg-devel@lists.x.org Subject: [PATCH] glx: Refcnt the GLXDrawable to avoid use after free with multiple FreeResource Date: Fri, 10 Dec 2010 12:43:32 +0000 Message-Id: <1291985012-12090-1-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.7.2.3 MIME-Version: 1.0 Cc: =?UTF-8?q?Michel=20D=C3=A4nzer?= , dri-devel@lists.freedesktop.org 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 12:44:11 +0000 (UTC) X-MIME-Autoconverted: from base64 to 8bit by demeter1.kernel.org id oBAChoYP024333 diff --git a/glx/glxcmds.c b/glx/glxcmds.c index de9c3f0..fa153d5 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,6 +1133,7 @@ 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 @@ -1139,6 +1143,8 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, pGlxDraw->destroy (pGlxDraw); return BadAlloc; } + pGlxDraw->refcnt++; + pGlxDraw->otherId = pDraw->id; 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..c473aa9 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)) {