[PATCH] glx: Refcnt the GLXDrawable to avoid use after free with multiple FreeResource

Michel Dänzer michel at daenzer.net
Fri Dec 10 05:16:23 PST 2010


On Fre, 2010-12-10 at 12:43 +0000, Chris Wilson wrote: 
> Although there may be more than one resource handles pointing to the
> Drawable, we only want to destroy it once and only reference the
> resource which may have just been deleted on the first instance.
> 
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Kristian Høgsberg <krh at bitplanet.net>
> Cc: Michel Dänzer <daenzer at vmware.com>
> ---
>  glx/glxcmds.c     |    6 ++++++
>  glx/glxdrawable.h |    3 +++
>  glx/glxext.c      |   15 ++++++++++-----
>  3 files changed, 19 insertions(+), 5 deletions(-)
> 
> diff --git a/glx/glxcmds.c b/glx/glxcmds.c
> index de9c3f0..fa153d5 100644
> --- a/glx/glxcmds.c
> +++ b/glx/glxcmds.c
> @@ -1139,6 +1143,8 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
>  	pGlxDraw->destroy (pGlxDraw);
>  	return BadAlloc;
>      }
> +    pGlxDraw->refcnt++;
> +    pGlxDraw->otherId = pDraw->id;

I think this should use drawableId instead of pDraw->id, and refcnt
should only be incremented if it's different from glxDrawableId.
Combined with the patch I attached to
https://bugs.freedesktop.org/show_bug.cgi?id=28181 this block could look
something like

    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 = pDraw->id;
    }

Then this patch will hopefully address that bug and maybe others with
references to DrawableGone. Fingers crossed. :)


> 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;

The return at the end of the function uses True instead of TRUE.


-- 
Earthling Michel Dänzer           |                http://www.vmware.com
Libre software enthusiast         |          Debian, X and DRI developer


More information about the xorg-devel mailing list