[PATCH] libX11: check size of GetReqExtra after XFlush

Kees Cook kees.cook at canonical.com
Mon Jul 18 08:57:44 PDT 2011


Hi, any comments on this? Seems like kind of a nasty surprise bug...

Thanks,

-Kees

On Sat, Jul 09, 2011 at 12:42:57PM -0700, Kees Cook wrote:
> Two users of GetReqExtra pass arbitrarily sized allocations from the
> caller (ModMap and Host). Adjust the GetReqExtra macro to double-check
> the requested length and invalidate "req" when this happens. Users of
> potentially >16K lengths in GetReqExtra now check "req" and fail if
> something has gone wrong.
> 
> https://bugs.launchpad.net/ubuntu/+source/x11-xserver-utils/+bug/792628
> 
> Signed-off-by: Kees Cook <kees.cook at canonical.com>
> ---
>  include/X11/Xlibint.h |   28 ++++++++++++++++++----------
>  src/Host.c            |    8 ++++++++
>  src/ModMap.c          |    4 ++++
>  3 files changed, 30 insertions(+), 10 deletions(-)
> 
> diff --git a/include/X11/Xlibint.h b/include/X11/Xlibint.h
> index 2ce356d..81f8cfd 100644
> --- a/include/X11/Xlibint.h
> +++ b/include/X11/Xlibint.h
> @@ -461,21 +461,29 @@ extern LockInfoPtr _Xglobal_lock;
>          WORD64ALIGN\
>  	if ((dpy->bufptr + SIZEOF(x##name##Req) + n) > dpy->bufmax)\
>  		_XFlush(dpy);\
> -	req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\
> -	req->reqType = X_##name;\
> -	req->length = (SIZEOF(x##name##Req) + n)>>2;\
> -	dpy->bufptr += SIZEOF(x##name##Req) + n;\
> -	dpy->request++
> +	if ((dpy->bufptr + SIZEOF(x##name##Req) + n) <= dpy->bufmax) {\
> +	    req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\
> +    	req->reqType = X_##name;\
> +    	req->length = (SIZEOF(x##name##Req) + n)>>2;\
> +    	dpy->bufptr += SIZEOF(x##name##Req) + n;\
> +    	dpy->request++;\
> +    } else {\
> +        req = NULL;\
> +    }
>  #else
>  #define GetReqExtra(name, n, req) \
>          WORD64ALIGN\
>  	if ((dpy->bufptr + SIZEOF(x/**/name/**/Req) + n) > dpy->bufmax)\
>  		_XFlush(dpy);\
> -	req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\
> -	req->reqType = X_/**/name;\
> -	req->length = (SIZEOF(x/**/name/**/Req) + n)>>2;\
> -	dpy->bufptr += SIZEOF(x/**/name/**/Req) + n;\
> -	dpy->request++
> +	if ((dpy->bufptr + SIZEOF(x/**/name/**/Req) + n) <= dpy->bufmax) {\
> +    	req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\
> +    	req->reqType = X_/**/name;\
> +    	req->length = (SIZEOF(x/**/name/**/Req) + n)>>2;\
> +    	dpy->bufptr += SIZEOF(x/**/name/**/Req) + n;\
> +    	dpy->request++;\
> +    } else {\
> +        req = NULL;\
> +    }
>  #endif
>  
>  
> diff --git a/src/Host.c b/src/Host.c
> index da9923a..3f87731 100644
> --- a/src/Host.c
> +++ b/src/Host.c
> @@ -83,6 +83,10 @@ XAddHost (
>  
>      LockDisplay(dpy);
>      GetReqExtra (ChangeHosts, length, req);
> +    if (!req) {
> +        UnlockDisplay(dpy);
> +        return 0;
> +    }
>      req->mode = HostInsert;
>      req->hostFamily = host->family;
>      req->hostLength = addrlen;
> @@ -118,6 +122,10 @@ XRemoveHost (
>  
>      LockDisplay(dpy);
>      GetReqExtra (ChangeHosts, length, req);
> +    if (!req) {
> +        UnlockDisplay(dpy);
> +        return 0;
> +    }
>      req->mode = HostDelete;
>      req->hostFamily = host->family;
>      req->hostLength = addrlen;
> diff --git a/src/ModMap.c b/src/ModMap.c
> index c99bfdd..5deb894 100644
> --- a/src/ModMap.c
> +++ b/src/ModMap.c
> @@ -75,6 +75,10 @@ XSetModifierMapping(
>  
>      LockDisplay(dpy);
>      GetReqExtra(SetModifierMapping, mapSize, req);
> +    if (!req) {
> +        UnlockDisplay(dpy);
> +        return 2;
> +    }
>  
>      req->numKeyPerModifier = modifier_map->max_keypermod;
>  
> -- 
> 1.7.4.1
> 
> 
> -- 
> Kees Cook
> Ubuntu Security Team
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
-- 
Kees Cook
Ubuntu Security Team


More information about the xorg-devel mailing list