From: Julien Cristau Date: Sat Jul 3 19:47:55 2010 +0100 Subject: [PATCH] glx: validate request lengths Patch-Mainline: Upstream Git-commit: ec9c97c6bf70b523bc500bd3adf62176f1bb33a4 References: bnc #648278, CVE-2010-4818 Signed-off-by: Egbert Eich Reviewed-by: Adam Jackson Reviewed-by: Kristian Høgsberg Reviewed-by: Daniel Stone Signed-off-by: Julien Cristau --- xorg-server-1.6.5.orig/glx/xfont.c +++ xorg-server-1.6.5/glx/xfont.c @@ -161,6 +161,8 @@ int __glXDisp_UseXFont(__GLXclientState __GLXcontext *cx; int error; + REQUEST_SIZE_MATCH(xGLXUseXFontReq); + req = (xGLXUseXFontReq *) pc; cx = __glXForceCurrent(cl, req->contextTag, &error); if (!cx) { --- xorg-server-1.9.3/glx/glxcmds.c.orig 2012-02-06 14:45:15.000000000 +0100 +++ xorg-server-1.9.3/glx/glxcmds.c 2012-02-06 15:09:00.000000000 +0100 @@ -315,11 +315,14 @@ DoCreateContext(__GLXclientState *cl, GL int __glXDisp_CreateContext(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; __GLXconfig *config; __GLXscreen *pGlxScreen; int err; + REQUEST_SIZE_MATCH(xGLXCreateContextReq); + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) return err; if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) @@ -331,11 +334,14 @@ int __glXDisp_CreateContext(__GLXclientS int __glXDisp_CreateNewContext(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; __GLXconfig *config; __GLXscreen *pGlxScreen; int err; + REQUEST_SIZE_MATCH(xGLXCreateNewContextReq); + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) return err; if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) @@ -347,12 +353,15 @@ int __glXDisp_CreateNewContext(__GLXclie int __glXDisp_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreateContextWithConfigSGIXReq *req = (xGLXCreateContextWithConfigSGIXReq *) pc; __GLXconfig *config; __GLXscreen *pGlxScreen; int err; + REQUEST_SIZE_MATCH(xGLXCreateContextWithConfigSGIXReq); + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) return err; if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) @@ -372,6 +372,7 @@ int __glXDisp_CreateContextWithConfigSGI } int __glXDisp_DestroyContext(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc; __GLXcontext *glxc; int err; @@ -367,6 +376,8 @@ int __glXDisp_DestroyContext(__GLXclient __GLXcontext *glxc; int err; + REQUEST_SIZE_MATCH(xGLXDestroyContextReq); + if (!validGlxContext(cl->client, req->context, DixDestroyAccess, &glxc, &err)) return err; @@ -686,24 +697,33 @@ DoMakeCurrent(__GLXclientState *cl, int __glXDisp_MakeCurrent(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc; + REQUEST_SIZE_MATCH(xGLXMakeCurrentReq); + return DoMakeCurrent( cl, req->drawable, req->drawable, req->context, req->oldContextTag ); } int __glXDisp_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc; + REQUEST_SIZE_MATCH(xGLXMakeContextCurrentReq); + return DoMakeCurrent( cl, req->drawable, req->readdrawable, req->context, req->oldContextTag ); } int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc; + REQUEST_SIZE_MATCH(xGLXMakeCurrentReadSGIReq); + return DoMakeCurrent( cl, req->drawable, req->readable, req->context, req->oldContextTag ); } @@ -716,6 +736,8 @@ int __glXDisp_IsDirect(__GLXclientState __GLXcontext *glxc; int err; + REQUEST_SIZE_MATCH(xGLXIsDirectReq); + if (!validGlxContext(cl->client, req->context, DixReadAccess, &glxc, &err)) return err; @@ -740,6 +762,8 @@ int __glXDisp_QueryVersion(__GLXclientSt xGLXQueryVersionReply reply; GLuint major, minor; + REQUEST_SIZE_MATCH(xGLXQueryVersionReq); + major = req->majorVersion; minor = req->minorVersion; (void)major; @@ -766,11 +790,15 @@ int __glXDisp_QueryVersion(__GLXclientSt int __glXDisp_WaitGL(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc; - GLXContextTag tag = req->contextTag; + GLXContextTag tag; __GLXcontext *glxc = NULL; int error; + REQUEST_SIZE_MATCH(xGLXWaitGLReq); + + tag = req->contextTag; if (tag) { glxc = __glXLookupContextByTag(cl, tag); if (!glxc) @@ -790,11 +818,15 @@ int __glXDisp_WaitGL(__GLXclientState *c int __glXDisp_WaitX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXWaitXReq *req = (xGLXWaitXReq *)pc; - GLXContextTag tag = req->contextTag; + GLXContextTag tag; __GLXcontext *glxc = NULL; int error; + REQUEST_SIZE_MATCH(xGLXWaitXReq); + + tag = req->contextTag; if (tag) { glxc = __glXLookupContextByTag(cl, tag); if (!glxc) @@ -814,13 +846,21 @@ int __glXDisp_CopyContext(__GLXclientSta { ClientPtr client = cl->client; xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc; - GLXContextID source = req->source; - GLXContextID dest = req->dest; - GLXContextTag tag = req->contextTag; - unsigned long mask = req->mask; + GLXContextID source; + GLXContextID dest; + GLXContextTag tag; + unsigned long mask; + __GLXcontext *src, *dst; int error; + REQUEST_SIZE_MATCH(xGLXCopyContextReq); + + source = req->source; + dest = req->dest; + tag = req->contextTag; + mask = req->mask; + if (!validGlxContext(cl->client, source, DixReadAccess, &src, &error)) return error; if (!validGlxContext(cl->client, dest, DixWriteAccess, &dst, &error)) @@ -903,6 +943,8 @@ int __glXDisp_GetVisualConfigs(__GLXclie __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + REQUEST_SIZE_MATCH(xGLXGetVisualConfigsReq); + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) return err; @@ -1082,13 +1124,17 @@ DoGetFBConfigs(__GLXclientState *cl, uns int __glXDisp_GetFBConfigs(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc; + REQUEST_SIZE_MATCH(xGLXGetFBConfigsReq); return DoGetFBConfigs(cl, req->screen); } int __glXDisp_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc; + REQUEST_SIZE_MATCH(xGLXGetFBConfigsSGIXReq); return DoGetFBConfigs(cl, req->screen); } @@ -1214,11 +1260,14 @@ determineTextureTarget(ClientPtr client, int __glXDisp_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; __GLXconfig *config; __GLXscreen *pGlxScreen; int err; + REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq); + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) return err; if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) @@ -1230,11 +1279,14 @@ int __glXDisp_CreateGLXPixmap(__GLXclien int __glXDisp_CreatePixmap(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; __GLXconfig *config; __GLXscreen *pGlxScreen; int err; + REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3); + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) return err; if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) @@ -1253,12 +1305,15 @@ int __glXDisp_CreatePixmap(__GLXclientSt int __glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreateGLXPixmapWithConfigSGIXReq *req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc; __GLXconfig *config; __GLXscreen *pGlxScreen; int err; + REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq); + if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) return err; if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) @@ -1285,15 +1340,21 @@ static int DoDestroyDrawable(__GLXclient int __glXDisp_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; + REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq); + return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); } int __glXDisp_DestroyPixmap(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc; + REQUEST_SIZE_MATCH(xGLXDestroyPixmapReq); + return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); } @@ -1332,10 +1393,13 @@ DoCreatePbuffer(ClientPtr client, int sc int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc; CARD32 *attrs; int width, height, i; + REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3); + attrs = (CARD32 *) (req + 1); width = 0; height = 0; @@ -1361,23 +1425,32 @@ int __glXDisp_CreatePbuffer(__GLXclientS int __glXDisp_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc; + REQUEST_SIZE_MATCH(xGLXCreateGLXPbufferSGIXReq); + return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, req->width, req->height, req->pbuffer); } int __glXDisp_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc; + REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq); + return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); } int __glXDisp_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc; + REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq); + return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); } @@ -1408,18 +1481,24 @@ DoChangeDrawableAttributes(ClientPtr cli int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXChangeDrawableAttributesReq *req = (xGLXChangeDrawableAttributesReq *) pc; + REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3); + return DoChangeDrawableAttributes(cl->client, req->drawable, req->numAttribs, (CARD32 *) (req + 1)); } int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXChangeDrawableAttributesSGIXReq *req = (xGLXChangeDrawableAttributesSGIXReq *)pc; + REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, req->numAttribs << 3); + return DoChangeDrawableAttributes(cl->client, req->drawable, req->numAttribs, (CARD32 *) (req + 1)); } @@ -1433,6 +1512,8 @@ int __glXDisp_CreateWindow(__GLXclientSt DrawablePtr pDraw; int err; + REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3); + LEGAL_NEW_RESOURCE(req->glxwindow, client); if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) @@ -1456,8 +1537,11 @@ int __glXDisp_CreateWindow(__GLXclientSt int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; + REQUEST_SIZE_MATCH(xGLXDestroyWindowReq); + return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW); } @@ -1473,12 +1557,16 @@ int __glXDisp_SwapBuffers(__GLXclientSta { ClientPtr client = cl->client; xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc; - GLXContextTag tag = req->contextTag; - XID drawId = req->drawable; + GLXContextTag tag; + XID drawId; __GLXcontext *glxc = NULL; __GLXdrawable *pGlxDraw; int error; + REQUEST_SIZE_MATCH(xGLXSwapBuffersReq); + + tag = req->contextTag; + drawId = req->drawable; if (tag) { glxc = __glXLookupContextByTag(cl, tag); if (!glxc) { @@ -1559,15 +1647,21 @@ DoQueryContext(__GLXclientState *cl, GLX int __glXDisp_QueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc; + REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq); + return DoQueryContext(cl, req->context); } int __glXDisp_QueryContext(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc; + REQUEST_SIZE_MATCH(xGLXQueryContextReq); + return DoQueryContext(cl, req->context); } @@ -1581,6 +1675,8 @@ int __glXDisp_BindTexImageEXT(__GLXclien int buffer; int error; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8); + pc += __GLX_VENDPRIV_HDR_SIZE; drawId = *((CARD32 *) (pc)); @@ -1615,6 +1711,8 @@ int __glXDisp_ReleaseTexImageEXT(__GLXcl int buffer; int error; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8); + pc += __GLX_VENDPRIV_HDR_SIZE; drawId = *((CARD32 *) (pc)); @@ -1650,6 +1748,8 @@ int __glXDisp_CopySubBufferMESA(__GLXcli (void) client; (void) req; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20); + pc += __GLX_VENDPRIV_HDR_SIZE; drawId = *((CARD32 *) (pc)); @@ -1738,16 +1838,22 @@ DoGetDrawableAttributes(__GLXclientState int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc; + REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesReq); + return DoGetDrawableAttributes(cl, req->drawable); } int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXGetDrawableAttributesSGIXReq *req = (xGLXGetDrawableAttributesSGIXReq *)pc; + REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq); + return DoGetDrawableAttributes(cl, req->drawable); } @@ -1772,6 +1878,8 @@ int __glXDisp_Render(__GLXclientState *c __GLXcontext *glxc; __GLX_DECLARE_SWAP_VARIABLES; + REQUEST_AT_LEAST_SIZE(xGLXRenderReq); + req = (xGLXRenderReq *) pc; if (client->swapped) { __GLX_SWAP_SHORT(&req->length); @@ -1792,6 +1900,9 @@ int __glXDisp_Render(__GLXclientState *c __GLXdispatchRenderProcPtr proc; int err; + if (left < sizeof(__GLXrenderHeader)) + return BadLength; + /* ** Verify that the header length and the overall length agree. ** Also, each command must be word aligned. @@ -2302,10 +2413,12 @@ int __glXDisp_HyperpipeConfigSGIX(__GLXc int __glXDisp_VendorPrivate(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; GLint vendorcode = req->vendorCode; __GLXdispatchVendorPrivProcPtr proc; + REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); proc = (__GLXdispatchVendorPrivProcPtr) __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info, @@ -2321,10 +2434,12 @@ int __glXDisp_VendorPrivate(__GLXclientS int __glXDisp_VendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; GLint vendorcode = req->vendorCode; __GLXdispatchVendorPrivProcPtr proc; + REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); proc = (__GLXdispatchVendorPrivProcPtr) __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info, @@ -2347,6 +2462,8 @@ int __glXDisp_QueryExtensionsString(__GL char *buf; int err; + REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq); + if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) return err; @@ -2386,6 +2503,8 @@ int __glXDisp_QueryServerString(__GLXcli int err; char ver_str[16]; + REQUEST_SIZE_MATCH(xGLXQueryServerStringReq); + if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) return err; @@ -2433,13 +2552,19 @@ int __glXDisp_QueryServerString(__GLXcli int __glXDisp_ClientInfo(__GLXclientState *cl, GLbyte *pc) { + ClientPtr client = cl->client; xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc; const char *buf; + + REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq); + + buf = (const char *)(req+1); + if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq))) + return BadLength; cl->GLClientmajorVersion = req->major; cl->GLClientminorVersion = req->minor; free(cl->GLClientextensions); - buf = (const char *)(req+1); cl->GLClientextensions = strdup(buf); return Success;