From 90cc925c5991fcb203f72d00b04419cd754a9b2c Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Fri, 17 Jan 2014 18:54:03 -0800 Subject: [PATCH 01/37] unchecked malloc may allow unauthed client to crash Xserver [CVE-2014-8091] authdes_ezdecode() calls malloc() using a length provided by the connection handshake sent by a newly connected client in order to authenticate to the server, so should be treated as untrusted. It didn't check if malloc() failed before writing to the newly allocated buffer, so could lead to a server crash if the server fails to allocate memory (up to UINT16_MAX bytes, since the len field is a CARD16 in the X protocol). Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- os/rpcauth.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/os/rpcauth.c b/os/rpcauth.c index d60ea3518..413cc6118 100644 --- a/os/rpcauth.c +++ b/os/rpcauth.c @@ -66,6 +66,10 @@ authdes_ezdecode(const char *inmsg, int len) SVCXPRT xprt; temp_inmsg = malloc(len); + if (temp_inmsg == NULL) { + why = AUTH_FAILED; /* generic error, since there is no AUTH_BADALLOC */ + return NULL; + } memmove(temp_inmsg, inmsg, len); memset((char *) &msg, 0, sizeof(msg)); From eeae42d60bf3d5663ea088581f6c28a82cd17829 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 22 Jan 2014 21:11:16 -0800 Subject: [PATCH 02/37] dix: integer overflow in ProcPutImage() [CVE-2014-8092 1/4] ProcPutImage() calculates a length field from a width, left pad and depth specified by the client (if the specified format is XYPixmap). The calculations for the total amount of memory the server needs for the pixmap can overflow a 32-bit number, causing out-of-bounds memory writes on 32-bit systems (since the length is stored in a long int variable). Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- dix/dispatch.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dix/dispatch.c b/dix/dispatch.c index d844a0942..55b978dea 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -2000,6 +2000,9 @@ ProcPutImage(ClientPtr client) tmpImage = (char *) &stuff[1]; lengthProto = length; + if (lengthProto >= (INT32_MAX / stuff->height)) + return BadLength; + if ((bytes_to_int32(lengthProto * stuff->height) + bytes_to_int32(sizeof(xPutImageReq))) != client->req_len) return BadLength; From bc8e20430b6f6378daf6ce4329029248a88af08b Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Mon, 6 Jan 2014 23:30:14 -0800 Subject: [PATCH 03/37] dix: integer overflow in GetHosts() [CVE-2014-8092 2/4] GetHosts() iterates over all the hosts it has in memory, and copies them to a buffer. The buffer length is calculated by iterating over all the hosts and adding up all of their combined length. There is a potential integer overflow, if there are lots and lots of hosts (with a combined length of > ~4 gig). This should be possible by repeatedly calling ProcChangeHosts() on 64bit machines with enough memory. This patch caps the list at 1mb, because multi-megabyte hostname lists for X access control are insane. Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- os/access.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/os/access.c b/os/access.c index 5c510ded2..f393c8d54 100644 --- a/os/access.c +++ b/os/access.c @@ -1296,6 +1296,10 @@ GetHosts(void **data, int *pnHosts, int *pLen, BOOL * pEnabled) for (host = validhosts; host; host = host->next) { nHosts++; n += pad_to_int32(host->len) + sizeof(xHostEntry); + /* Could check for INT_MAX, but in reality having more than 1mb of + hostnames in the access list is ridiculous */ + if (n >= 1048576) + break; } if (n) { *data = ptr = malloc(n); @@ -1304,6 +1308,8 @@ GetHosts(void **data, int *pnHosts, int *pLen, BOOL * pEnabled) } for (host = validhosts; host; host = host->next) { len = host->len; + if ((ptr + sizeof(xHostEntry) + len) > (data + n)) + break; ((xHostEntry *) ptr)->family = host->family; ((xHostEntry *) ptr)->length = len; ptr += sizeof(xHostEntry); From 97015a07b9e15d8ec5608b95d95ec0eb51202acb Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 22 Jan 2014 22:37:15 -0800 Subject: [PATCH 04/37] dix: integer overflow in RegionSizeof() [CVE-2014-8092 3/4] RegionSizeof contains several integer overflows if a large length value is passed in. Once we fix it to return 0 on overflow, we also have to fix the callers to handle this error condition v2: Fixed limit calculation in RegionSizeof as pointed out by jcristau. Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer Reviewed-by: Julien Cristau --- dix/region.c | 20 +++++++++++++------- include/regionstr.h | 10 +++++++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/dix/region.c b/dix/region.c index ce1014ef8..04e590170 100644 --- a/dix/region.c +++ b/dix/region.c @@ -169,7 +169,6 @@ Equipment Corporation. ((r1)->y1 <= (r2)->y1) && \ ((r1)->y2 >= (r2)->y2) ) -#define xallocData(n) malloc(RegionSizeof(n)) #define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data) #define RECTALLOC_BAIL(pReg,n,bail) \ @@ -205,8 +204,9 @@ if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ #define DOWNSIZE(reg,numRects) \ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ { \ - RegDataPtr NewData; \ - NewData = (RegDataPtr)realloc((reg)->data, RegionSizeof(numRects)); \ + size_t NewSize = RegionSizeof(numRects); \ + RegDataPtr NewData = \ + (NewSize > 0) ? realloc((reg)->data, NewSize) : NULL ; \ if (NewData) \ { \ NewData->size = (numRects); \ @@ -345,17 +345,20 @@ Bool RegionRectAlloc(RegionPtr pRgn, int n) { RegDataPtr data; + size_t rgnSize; if (!pRgn->data) { n++; - pRgn->data = xallocData(n); + rgnSize = RegionSizeof(n); + pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL; if (!pRgn->data) return RegionBreak(pRgn); pRgn->data->numRects = 1; *RegionBoxptr(pRgn) = pRgn->extents; } else if (!pRgn->data->size) { - pRgn->data = xallocData(n); + rgnSize = RegionSizeof(n); + pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL; if (!pRgn->data) return RegionBreak(pRgn); pRgn->data->numRects = 0; @@ -367,7 +370,8 @@ RegionRectAlloc(RegionPtr pRgn, int n) n = 250; } n += pRgn->data->numRects; - data = (RegDataPtr) realloc(pRgn->data, RegionSizeof(n)); + rgnSize = RegionSizeof(n); + data = (rgnSize > 0) ? realloc(pRgn->data, rgnSize) : NULL; if (!data) return RegionBreak(pRgn); pRgn->data = data; @@ -1312,6 +1316,7 @@ RegionFromRects(int nrects, xRectangle *prect, int ctype) { RegionPtr pRgn; + size_t rgnSize; RegDataPtr pData; BoxPtr pBox; int i; @@ -1338,7 +1343,8 @@ RegionFromRects(int nrects, xRectangle *prect, int ctype) } return pRgn; } - pData = xallocData(nrects); + rgnSize = RegionSizeof(nrects); + pData = (rgnSize > 0) ? malloc(rgnSize) : NULL; if (!pData) { RegionBreak(pRgn); return pRgn; diff --git a/include/regionstr.h b/include/regionstr.h index 515e93ffa..079375d33 100644 --- a/include/regionstr.h +++ b/include/regionstr.h @@ -127,7 +127,10 @@ RegionEnd(RegionPtr reg) static inline size_t RegionSizeof(size_t n) { - return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec))); + if (n < ((INT_MAX - sizeof(RegDataRec)) / sizeof(BoxRec))) + return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec))); + else + return 0; } static inline void @@ -138,9 +141,10 @@ RegionInit(RegionPtr _pReg, BoxPtr _rect, int _size) (_pReg)->data = (RegDataPtr) NULL; } else { + size_t rgnSize; (_pReg)->extents = RegionEmptyBox; - if (((_size) > 1) && ((_pReg)->data = - (RegDataPtr) malloc(RegionSizeof(_size)))) { + if (((_size) > 1) && ((rgnSize = RegionSizeof(_size)) > 0) && + (((_pReg)->data = malloc(rgnSize)) != NULL)) { (_pReg)->data->size = (_size); (_pReg)->data->numRects = 0; } From e0e11644622a589129a01e11e5d105dc74a098de Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 22 Jan 2014 23:44:46 -0800 Subject: [PATCH 05/37] dix: integer overflow in REQUEST_FIXED_SIZE() [CVE-2014-8092 4/4] Force use of 64-bit integers when evaluating data provided by clients in 32-bit fields which can overflow when added or multiplied during checks. Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- include/dix.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/dix.h b/include/dix.h index 991a3ce88..e0c6ed84f 100644 --- a/include/dix.h +++ b/include/dix.h @@ -76,7 +76,8 @@ SOFTWARE. #define REQUEST_FIXED_SIZE(req, n)\ if (((sizeof(req) >> 2) > client->req_len) || \ - (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \ + ((n >> 2) >= client->req_len) || \ + ((((uint64_t) sizeof(req) + (n) + 3) >> 2) != (uint64_t) client->req_len)) \ return(BadLength) #define LEGAL_NEW_RESOURCE(id,client)\ From 6692670fde081bbfe9313f17d84037ae9116702a Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 22 Jan 2014 23:40:18 -0800 Subject: [PATCH 06/37] dri2: integer overflow in ProcDRI2GetBuffers() [CVE-2014-8094] ProcDRI2GetBuffers() tries to validate a length field (count). There is an integer overflow in the validation. This can cause out of bound reads and memory corruption later on. Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer Reviewed-by: Julien Cristau --- hw/xfree86/dri2/dri2ext.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c index ffd66fad6..221ec530b 100644 --- a/hw/xfree86/dri2/dri2ext.c +++ b/hw/xfree86/dri2/dri2ext.c @@ -270,6 +270,9 @@ ProcDRI2GetBuffers(ClientPtr client) unsigned int *attachments; REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4); + if (stuff->count > (INT_MAX / 4)) + return BadLength; + if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, &pDrawable, &status)) return status; From 2ef42519c41e793579c9cea699c866fee3d9321f Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 22 Jan 2014 23:12:04 -0800 Subject: [PATCH 07/37] dbe: unvalidated lengths in DbeSwapBuffers calls [CVE-2014-8097] ProcDbeSwapBuffers() has a 32bit (n) length value that it uses to read from a buffer. The length is never validated, which can lead to out of bound reads, and possibly returning the data read from out of bounds to the misbehaving client via an X Error packet. SProcDbeSwapBuffers() swaps data (for correct endianness) before handing it off to the real proc. While doing the swapping, the length field is not validated, which can cause memory corruption. v2: reorder checks to avoid compilers optimizing out checks for overflow that happen after we'd already have done the overflowing multiplications. Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- dbe/dbe.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dbe/dbe.c b/dbe/dbe.c index 527588c3c..df2ad5c51 100644 --- a/dbe/dbe.c +++ b/dbe/dbe.c @@ -450,18 +450,20 @@ ProcDbeSwapBuffers(ClientPtr client) DbeSwapInfoPtr swapInfo; xDbeSwapInfo *dbeSwapInfo; int error; - register int i, j; - int nStuff; + unsigned int i, j; + unsigned int nStuff; REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); nStuff = stuff->n; /* use local variable for performance. */ if (nStuff == 0) { + REQUEST_SIZE_MATCH(xDbeSwapBuffersReq); return Success; } if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) return BadAlloc; + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo)); /* Get to the swap info appended to the end of the request. */ dbeSwapInfo = (xDbeSwapInfo *) &stuff[1]; @@ -914,13 +916,16 @@ static int SProcDbeSwapBuffers(ClientPtr client) { REQUEST(xDbeSwapBuffersReq); - register int i; + unsigned int i; xDbeSwapInfo *pSwapInfo; swaps(&stuff->length); REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); swapl(&stuff->n); + if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec)) + return BadAlloc; + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo)); if (stuff->n != 0) { pSwapInfo = (xDbeSwapInfo *) stuff + 1; From 73c63afb93c0af1bfd1969bf6e71c9edca586c77 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 10:54:41 -0800 Subject: [PATCH 08/37] Xi: unvalidated lengths in Xinput extension [CVE-2014-8095] Multiple functions in the Xinput extension handling of requests from clients failed to check that the length of the request sent by the client was large enough to perform all the required operations and thus could read or write to memory outside the bounds of the request buffer. This commit includes the creation of a new REQUEST_AT_LEAST_EXTRA_SIZE macro in include/dix.h for the common case of needing to ensure a request is large enough to include both the request itself and a minimum amount of extra data following the request header. Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- Xi/chgdctl.c | 8 ++++++-- Xi/chgfctl.c | 2 ++ Xi/sendexev.c | 3 +++ Xi/xiallowev.c | 2 ++ Xi/xichangecursor.c | 2 +- Xi/xichangehierarchy.c | 35 ++++++++++++++++++++++++++++++++--- Xi/xigetclientpointer.c | 1 + Xi/xigrabdev.c | 9 ++++++++- Xi/xipassivegrab.c | 12 ++++++++++-- Xi/xiproperty.c | 14 ++++++-------- Xi/xiquerydevice.c | 1 + Xi/xiquerypointer.c | 2 ++ Xi/xiselectev.c | 8 ++++++++ Xi/xisetclientpointer.c | 3 ++- Xi/xisetdevfocus.c | 4 ++++ Xi/xiwarppointer.c | 2 ++ include/dix.h | 4 ++++ 17 files changed, 94 insertions(+), 18 deletions(-) diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c index d078aa248..b3ee867f0 100644 --- a/Xi/chgdctl.c +++ b/Xi/chgdctl.c @@ -78,7 +78,7 @@ SProcXChangeDeviceControl(ClientPtr client) REQUEST(xChangeDeviceControlReq); swaps(&stuff->length); - REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq); + REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl)); swaps(&stuff->control); ctl = (xDeviceCtl *) &stuff[1]; swaps(&ctl->control); @@ -115,7 +115,7 @@ ProcXChangeDeviceControl(ClientPtr client) xDeviceEnableCtl *e; REQUEST(xChangeDeviceControlReq); - REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq); + REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl)); len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq)); ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); @@ -192,6 +192,10 @@ ProcXChangeDeviceControl(ClientPtr client) break; case DEVICE_ENABLE: e = (xDeviceEnableCtl *) &stuff[1]; + if ((len != bytes_to_int32(sizeof(xDeviceEnableCtl)))) { + ret = BadLength; + goto out; + } if (IsXTestDevice(dev, NULL)) status = !Success; diff --git a/Xi/chgfctl.c b/Xi/chgfctl.c index 6dcf60c66..224c2ba0a 100644 --- a/Xi/chgfctl.c +++ b/Xi/chgfctl.c @@ -467,6 +467,8 @@ ProcXChangeFeedbackControl(ClientPtr client) xStringFeedbackCtl *f = ((xStringFeedbackCtl *) &stuff[1]); if (client->swapped) { + if (len < bytes_to_int32(sizeof(xStringFeedbackCtl))) + return BadLength; swaps(&f->num_keysyms); } if (len != diff --git a/Xi/sendexev.c b/Xi/sendexev.c index 3c213864b..183f88dae 100644 --- a/Xi/sendexev.c +++ b/Xi/sendexev.c @@ -135,6 +135,9 @@ ProcXSendExtensionEvent(ClientPtr client) if (ret != Success) return ret; + if (stuff->num_events == 0) + return ret; + /* The client's event type must be one defined by an extension. */ first = ((xEvent *) &stuff[1]); diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c index ebef23344..ca263ef1f 100644 --- a/Xi/xiallowev.c +++ b/Xi/xiallowev.c @@ -48,6 +48,7 @@ int SProcXIAllowEvents(ClientPtr client) { REQUEST(xXIAllowEventsReq); + REQUEST_AT_LEAST_SIZE(xXIAllowEventsReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -55,6 +56,7 @@ SProcXIAllowEvents(ClientPtr client) if (stuff->length > 3) { xXI2_2AllowEventsReq *req_xi22 = (xXI2_2AllowEventsReq *) stuff; + REQUEST_AT_LEAST_SIZE(xXI2_2AllowEventsReq); swapl(&req_xi22->touchid); swapl(&req_xi22->grab_window); } diff --git a/Xi/xichangecursor.c b/Xi/xichangecursor.c index 7a1bb7a0d..8e6255b6e 100644 --- a/Xi/xichangecursor.c +++ b/Xi/xichangecursor.c @@ -57,11 +57,11 @@ int SProcXIChangeCursor(ClientPtr client) { REQUEST(xXIChangeCursorReq); + REQUEST_SIZE_MATCH(xXIChangeCursorReq); swaps(&stuff->length); swapl(&stuff->win); swapl(&stuff->cursor); swaps(&stuff->deviceid); - REQUEST_SIZE_MATCH(xXIChangeCursorReq); return (ProcXIChangeCursor(client)); } diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c index 9e36354d1..27324452d 100644 --- a/Xi/xichangehierarchy.c +++ b/Xi/xichangehierarchy.c @@ -411,7 +411,7 @@ int ProcXIChangeHierarchy(ClientPtr client) { xXIAnyHierarchyChangeInfo *any; - int required_len = sizeof(xXIChangeHierarchyReq); + size_t len; /* length of data remaining in request */ int rc = Success; int flags[MAXDEVICES] = { 0 }; @@ -421,21 +421,46 @@ ProcXIChangeHierarchy(ClientPtr client) if (!stuff->num_changes) return rc; + if (stuff->length > (INT_MAX >> 2)) + return BadAlloc; + len = (stuff->length << 2) - sizeof(xXIAnyHierarchyChangeInfo); + any = (xXIAnyHierarchyChangeInfo *) &stuff[1]; while (stuff->num_changes--) { + if (len < sizeof(xXIAnyHierarchyChangeInfo)) { + rc = BadLength; + goto unwind; + } + SWAPIF(swaps(&any->type)); SWAPIF(swaps(&any->length)); - required_len += any->length; - if ((stuff->length * 4) < required_len) + if ((any->length > (INT_MAX >> 2)) || (len < (any->length << 2))) return BadLength; +#define CHANGE_SIZE_MATCH(type) \ + do { \ + if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \ + rc = BadLength; \ + goto unwind; \ + } \ + } while(0) + switch (any->type) { case XIAddMaster: { xXIAddMasterInfo *c = (xXIAddMasterInfo *) any; + /* Variable length, due to appended name string */ + if (len < sizeof(xXIAddMasterInfo)) { + rc = BadLength; + goto unwind; + } SWAPIF(swaps(&c->name_len)); + if (c->name_len > (len - sizeof(xXIAddMasterInfo))) { + rc = BadLength; + goto unwind; + } rc = add_master(client, c, flags); if (rc != Success) @@ -446,6 +471,7 @@ ProcXIChangeHierarchy(ClientPtr client) { xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; + CHANGE_SIZE_MATCH(xXIRemoveMasterInfo); rc = remove_master(client, r, flags); if (rc != Success) goto unwind; @@ -455,6 +481,7 @@ ProcXIChangeHierarchy(ClientPtr client) { xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; + CHANGE_SIZE_MATCH(xXIDetachSlaveInfo); rc = detach_slave(client, c, flags); if (rc != Success) goto unwind; @@ -464,6 +491,7 @@ ProcXIChangeHierarchy(ClientPtr client) { xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; + CHANGE_SIZE_MATCH(xXIAttachSlaveInfo); rc = attach_slave(client, c, flags); if (rc != Success) goto unwind; @@ -471,6 +499,7 @@ ProcXIChangeHierarchy(ClientPtr client) break; } + len -= any->length * 4; any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); } diff --git a/Xi/xigetclientpointer.c b/Xi/xigetclientpointer.c index 3c90d588d..306dd396b 100644 --- a/Xi/xigetclientpointer.c +++ b/Xi/xigetclientpointer.c @@ -50,6 +50,7 @@ int SProcXIGetClientPointer(ClientPtr client) { REQUEST(xXIGetClientPointerReq); + REQUEST_SIZE_MATCH(xXIGetClientPointerReq); swaps(&stuff->length); swapl(&stuff->win); diff --git a/Xi/xigrabdev.c b/Xi/xigrabdev.c index 63d95bc1c..e2a2ae333 100644 --- a/Xi/xigrabdev.c +++ b/Xi/xigrabdev.c @@ -47,6 +47,11 @@ int SProcXIGrabDevice(ClientPtr client) { REQUEST(xXIGrabDeviceReq); + /* + * Check here for at least the length of the struct we swap, then + * let ProcXIGrabDevice check the full size after we swap mask_len. + */ + REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -71,7 +76,7 @@ ProcXIGrabDevice(ClientPtr client) unsigned int pointer_mode; REQUEST(xXIGrabDeviceReq); - REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq); + REQUEST_FIXED_SIZE(xXIGrabDeviceReq, ((size_t) stuff->mask_len) * 4); ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); if (ret != Success) @@ -131,6 +136,7 @@ int SProcXIUngrabDevice(ClientPtr client) { REQUEST(xXIUngrabDeviceReq); + REQUEST_SIZE_MATCH(xXIUngrabDeviceReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -148,6 +154,7 @@ ProcXIUngrabDevice(ClientPtr client) TimeStamp time; REQUEST(xXIUngrabDeviceReq); + REQUEST_SIZE_MATCH(xXIUngrabDeviceReq); ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); if (ret != Success) diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c index 700622d38..9241ffdea 100644 --- a/Xi/xipassivegrab.c +++ b/Xi/xipassivegrab.c @@ -53,6 +53,7 @@ SProcXIPassiveGrabDevice(ClientPtr client) uint32_t *mods; REQUEST(xXIPassiveGrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -63,6 +64,8 @@ SProcXIPassiveGrabDevice(ClientPtr client) swaps(&stuff->mask_len); swaps(&stuff->num_modifiers); + REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, + ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4); mods = (uint32_t *) &stuff[1] + stuff->mask_len; for (i = 0; i < stuff->num_modifiers; i++, mods++) { @@ -92,7 +95,8 @@ ProcXIPassiveGrabDevice(ClientPtr client) int mask_len; REQUEST(xXIPassiveGrabDeviceReq); - REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); + REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, + ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); if (stuff->deviceid == XIAllDevices) dev = inputInfo.all_devices; @@ -252,6 +256,7 @@ SProcXIPassiveUngrabDevice(ClientPtr client) uint32_t *modifiers; REQUEST(xXIPassiveUngrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); swaps(&stuff->length); swapl(&stuff->grab_window); @@ -259,6 +264,8 @@ SProcXIPassiveUngrabDevice(ClientPtr client) swapl(&stuff->detail); swaps(&stuff->num_modifiers); + REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, + ((uint32_t) stuff->num_modifiers) << 2); modifiers = (uint32_t *) &stuff[1]; for (i = 0; i < stuff->num_modifiers; i++, modifiers++) @@ -277,7 +284,8 @@ ProcXIPassiveUngrabDevice(ClientPtr client) int i, rc; REQUEST(xXIPassiveUngrabDeviceReq); - REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); + REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, + ((uint32_t) stuff->num_modifiers) << 2); if (stuff->deviceid == XIAllDevices) dev = inputInfo.all_devices; diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index 463607d33..8e8e4b061 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -1013,10 +1013,9 @@ int SProcXListDeviceProperties(ClientPtr client) { REQUEST(xListDevicePropertiesReq); + REQUEST_SIZE_MATCH(xListDevicePropertiesReq); swaps(&stuff->length); - - REQUEST_SIZE_MATCH(xListDevicePropertiesReq); return (ProcXListDeviceProperties(client)); } @@ -1037,10 +1036,10 @@ int SProcXDeleteDeviceProperty(ClientPtr client) { REQUEST(xDeleteDevicePropertyReq); + REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); swaps(&stuff->length); swapl(&stuff->property); - REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); return (ProcXDeleteDeviceProperty(client)); } @@ -1048,13 +1047,13 @@ int SProcXGetDeviceProperty(ClientPtr client) { REQUEST(xGetDevicePropertyReq); + REQUEST_SIZE_MATCH(xGetDevicePropertyReq); swaps(&stuff->length); swapl(&stuff->property); swapl(&stuff->type); swapl(&stuff->longOffset); swapl(&stuff->longLength); - REQUEST_SIZE_MATCH(xGetDevicePropertyReq); return (ProcXGetDeviceProperty(client)); } @@ -1253,11 +1252,10 @@ int SProcXIListProperties(ClientPtr client) { REQUEST(xXIListPropertiesReq); + REQUEST_SIZE_MATCH(xXIListPropertiesReq); swaps(&stuff->length); swaps(&stuff->deviceid); - - REQUEST_SIZE_MATCH(xXIListPropertiesReq); return (ProcXIListProperties(client)); } @@ -1279,11 +1277,11 @@ int SProcXIDeleteProperty(ClientPtr client) { REQUEST(xXIDeletePropertyReq); + REQUEST_SIZE_MATCH(xXIDeletePropertyReq); swaps(&stuff->length); swaps(&stuff->deviceid); swapl(&stuff->property); - REQUEST_SIZE_MATCH(xXIDeletePropertyReq); return (ProcXIDeleteProperty(client)); } @@ -1291,6 +1289,7 @@ int SProcXIGetProperty(ClientPtr client) { REQUEST(xXIGetPropertyReq); + REQUEST_SIZE_MATCH(xXIGetPropertyReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -1298,7 +1297,6 @@ SProcXIGetProperty(ClientPtr client) swapl(&stuff->type); swapl(&stuff->offset); swapl(&stuff->len); - REQUEST_SIZE_MATCH(xXIGetPropertyReq); return (ProcXIGetProperty(client)); } diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c index 4e544f0f5..67a9a4f3f 100644 --- a/Xi/xiquerydevice.c +++ b/Xi/xiquerydevice.c @@ -54,6 +54,7 @@ int SProcXIQueryDevice(ClientPtr client) { REQUEST(xXIQueryDeviceReq); + REQUEST_SIZE_MATCH(xXIQueryDeviceReq); swaps(&stuff->length); swaps(&stuff->deviceid); diff --git a/Xi/xiquerypointer.c b/Xi/xiquerypointer.c index e9bdd428d..7ec0c851d 100644 --- a/Xi/xiquerypointer.c +++ b/Xi/xiquerypointer.c @@ -63,6 +63,8 @@ int SProcXIQueryPointer(ClientPtr client) { REQUEST(xXIQueryPointerReq); + REQUEST_SIZE_MATCH(xXIQueryPointerReq); + swaps(&stuff->length); swaps(&stuff->deviceid); swapl(&stuff->win); diff --git a/Xi/xiselectev.c b/Xi/xiselectev.c index 45a996e4c..168579f5b 100644 --- a/Xi/xiselectev.c +++ b/Xi/xiselectev.c @@ -114,6 +114,7 @@ int SProcXISelectEvents(ClientPtr client) { int i; + int len; xXIEventMask *evmask; REQUEST(xXISelectEventsReq); @@ -122,10 +123,17 @@ SProcXISelectEvents(ClientPtr client) swapl(&stuff->win); swaps(&stuff->num_masks); + len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq)); evmask = (xXIEventMask *) &stuff[1]; for (i = 0; i < stuff->num_masks; i++) { + if (len < bytes_to_int32(sizeof(xXIEventMask))) + return BadLength; + len -= bytes_to_int32(sizeof(xXIEventMask)); swaps(&evmask->deviceid); swaps(&evmask->mask_len); + if (len < evmask->mask_len) + return BadLength; + len -= evmask->mask_len; evmask = (xXIEventMask *) (((char *) &evmask[1]) + evmask->mask_len * 4); } diff --git a/Xi/xisetclientpointer.c b/Xi/xisetclientpointer.c index 38ff51e86..24d4a5379 100644 --- a/Xi/xisetclientpointer.c +++ b/Xi/xisetclientpointer.c @@ -51,10 +51,11 @@ int SProcXISetClientPointer(ClientPtr client) { REQUEST(xXISetClientPointerReq); + REQUEST_SIZE_MATCH(xXISetClientPointerReq); + swaps(&stuff->length); swapl(&stuff->win); swaps(&stuff->deviceid); - REQUEST_SIZE_MATCH(xXISetClientPointerReq); return (ProcXISetClientPointer(client)); } diff --git a/Xi/xisetdevfocus.c b/Xi/xisetdevfocus.c index 372ec248a..96a9a16e4 100644 --- a/Xi/xisetdevfocus.c +++ b/Xi/xisetdevfocus.c @@ -44,6 +44,8 @@ int SProcXISetFocus(ClientPtr client) { REQUEST(xXISetFocusReq); + REQUEST_AT_LEAST_SIZE(xXISetFocusReq); + swaps(&stuff->length); swaps(&stuff->deviceid); swapl(&stuff->focus); @@ -56,6 +58,8 @@ int SProcXIGetFocus(ClientPtr client) { REQUEST(xXIGetFocusReq); + REQUEST_AT_LEAST_SIZE(xXIGetFocusReq); + swaps(&stuff->length); swaps(&stuff->deviceid); diff --git a/Xi/xiwarppointer.c b/Xi/xiwarppointer.c index 3f051f759..780758a9e 100644 --- a/Xi/xiwarppointer.c +++ b/Xi/xiwarppointer.c @@ -56,6 +56,8 @@ int SProcXIWarpPointer(ClientPtr client) { REQUEST(xXIWarpPointerReq); + REQUEST_SIZE_MATCH(xXIWarpPointerReq); + swaps(&stuff->length); swapl(&stuff->src_win); swapl(&stuff->dst_win); diff --git a/include/dix.h b/include/dix.h index e0c6ed84f..21176a8c3 100644 --- a/include/dix.h +++ b/include/dix.h @@ -74,6 +74,10 @@ SOFTWARE. if ((sizeof(req) >> 2) > client->req_len )\ return(BadLength) +#define REQUEST_AT_LEAST_EXTRA_SIZE(req, extra) \ + if (((sizeof(req) + ((uint64_t) extra)) >> 2) > client->req_len ) \ + return(BadLength) + #define REQUEST_FIXED_SIZE(req, n)\ if (((sizeof(req) >> 2) > client->req_len) || \ ((n >> 2) >= client->req_len) || \ From 7553082b9b883b5f130044f3d53bce2f0b660e52 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 17:18:54 -0800 Subject: [PATCH 09/37] xcmisc: unvalidated length in SProcXCMiscGetXIDList() [CVE-2014-8096] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- Xext/xcmisc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Xext/xcmisc.c b/Xext/xcmisc.c index 034bfb63b..1e9101059 100644 --- a/Xext/xcmisc.c +++ b/Xext/xcmisc.c @@ -167,6 +167,7 @@ static int SProcXCMiscGetXIDList(ClientPtr client) { REQUEST(xXCMiscGetXIDListReq); + REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq); swaps(&stuff->length); swapl(&stuff->count); From 32a95fb7c7dbe22c9441c62762dfa4a8ec54d6c3 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 19:23:17 -0800 Subject: [PATCH 10/37] Xv: unvalidated lengths in XVideo extension swapped procs [CVE-2014-8099] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- Xext/xvdisp.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c index 86f982ae2..c2d0fc9c1 100644 --- a/Xext/xvdisp.c +++ b/Xext/xvdisp.c @@ -1121,6 +1121,7 @@ static int SProcXvQueryExtension(ClientPtr client) { REQUEST(xvQueryExtensionReq); + REQUEST_SIZE_MATCH(xvQueryExtensionReq); swaps(&stuff->length); return XvProcVector[xv_QueryExtension] (client); } @@ -1129,6 +1130,7 @@ static int SProcXvQueryAdaptors(ClientPtr client) { REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); swaps(&stuff->length); swapl(&stuff->window); return XvProcVector[xv_QueryAdaptors] (client); @@ -1138,6 +1140,7 @@ static int SProcXvQueryEncodings(ClientPtr client) { REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); swaps(&stuff->length); swapl(&stuff->port); return XvProcVector[xv_QueryEncodings] (client); @@ -1147,6 +1150,7 @@ static int SProcXvGrabPort(ClientPtr client) { REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->time); @@ -1157,6 +1161,7 @@ static int SProcXvUngrabPort(ClientPtr client) { REQUEST(xvUngrabPortReq); + REQUEST_SIZE_MATCH(xvUngrabPortReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->time); @@ -1167,6 +1172,7 @@ static int SProcXvPutVideo(ClientPtr client) { REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->drawable); @@ -1186,6 +1192,7 @@ static int SProcXvPutStill(ClientPtr client) { REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->drawable); @@ -1205,6 +1212,7 @@ static int SProcXvGetVideo(ClientPtr client) { REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->drawable); @@ -1224,6 +1232,7 @@ static int SProcXvGetStill(ClientPtr client) { REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->drawable); @@ -1243,6 +1252,7 @@ static int SProcXvPutImage(ClientPtr client) { REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->drawable); @@ -1266,6 +1276,7 @@ static int SProcXvShmPutImage(ClientPtr client) { REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->drawable); @@ -1293,6 +1304,7 @@ static int SProcXvSelectVideoNotify(ClientPtr client) { REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); swaps(&stuff->length); swapl(&stuff->drawable); return XvProcVector[xv_SelectVideoNotify] (client); @@ -1302,6 +1314,7 @@ static int SProcXvSelectPortNotify(ClientPtr client) { REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); swaps(&stuff->length); swapl(&stuff->port); return XvProcVector[xv_SelectPortNotify] (client); @@ -1311,6 +1324,7 @@ static int SProcXvStopVideo(ClientPtr client) { REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->drawable); @@ -1321,6 +1335,7 @@ static int SProcXvSetPortAttribute(ClientPtr client) { REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->attribute); @@ -1332,6 +1347,7 @@ static int SProcXvGetPortAttribute(ClientPtr client) { REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->attribute); @@ -1342,6 +1358,7 @@ static int SProcXvQueryBestSize(ClientPtr client) { REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); swaps(&stuff->length); swapl(&stuff->port); swaps(&stuff->vid_w); @@ -1355,6 +1372,7 @@ static int SProcXvQueryPortAttributes(ClientPtr client) { REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); swaps(&stuff->length); swapl(&stuff->port); return XvProcVector[xv_QueryPortAttributes] (client); @@ -1364,6 +1382,7 @@ static int SProcXvQueryImageAttributes(ClientPtr client) { REQUEST(xvQueryImageAttributesReq); + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); swaps(&stuff->length); swapl(&stuff->port); swapl(&stuff->id); @@ -1376,6 +1395,7 @@ static int SProcXvListImageFormats(ClientPtr client) { REQUEST(xvListImageFormatsReq); + REQUEST_SIZE_MATCH(xvListImageFormatsReq); swaps(&stuff->length); swapl(&stuff->port); return XvProcVector[xv_ListImageFormats] (client); From 0a6085aaf3581cca558d960ea176ddf3a41a2213 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 19:28:05 -0800 Subject: [PATCH 11/37] dri3: unvalidated lengths in DRI3 extension swapped procs [CVE-2014-8103 1/2] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- dri3/dri3_request.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c index fe45620c9..2d7558863 100644 --- a/dri3/dri3_request.c +++ b/dri3/dri3_request.c @@ -321,6 +321,7 @@ static int sproc_dri3_query_version(ClientPtr client) { REQUEST(xDRI3QueryVersionReq); + REQUEST_SIZE_MATCH(xDRI3QueryVersionReq); swaps(&stuff->length); swapl(&stuff->majorVersion); @@ -332,6 +333,7 @@ static int sproc_dri3_open(ClientPtr client) { REQUEST(xDRI3OpenReq); + REQUEST_SIZE_MATCH(xDRI3OpenReq); swaps(&stuff->length); swapl(&stuff->drawable); @@ -343,6 +345,7 @@ static int sproc_dri3_pixmap_from_buffer(ClientPtr client) { REQUEST(xDRI3PixmapFromBufferReq); + REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); swaps(&stuff->length); swapl(&stuff->pixmap); @@ -358,6 +361,7 @@ static int sproc_dri3_buffer_from_pixmap(ClientPtr client) { REQUEST(xDRI3BufferFromPixmapReq); + REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); swaps(&stuff->length); swapl(&stuff->pixmap); @@ -368,6 +372,7 @@ static int sproc_dri3_fence_from_fd(ClientPtr client) { REQUEST(xDRI3FenceFromFDReq); + REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); swaps(&stuff->length); swapl(&stuff->drawable); @@ -379,6 +384,7 @@ static int sproc_dri3_fd_from_fence(ClientPtr client) { REQUEST(xDRI3FDFromFenceReq); + REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq); swaps(&stuff->length); swapl(&stuff->drawable); From d155b7a8e38e74aee96bf52c20c8b6a330d7d462 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 19:33:34 -0800 Subject: [PATCH 12/37] present: unvalidated lengths in Present extension procs [CVE-2014-8103 2/2] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer Reviewed-by: Julien Cristau --- present/present_request.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/present/present_request.c b/present/present_request.c index 835890d28..7c53e7262 100644 --- a/present/present_request.c +++ b/present/present_request.c @@ -210,6 +210,7 @@ proc_present_query_capabilities (ClientPtr client) RRCrtcPtr crtc = NULL; int r; + REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq); r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess); switch (r) { case Success: @@ -254,6 +255,7 @@ static int sproc_present_query_version(ClientPtr client) { REQUEST(xPresentQueryVersionReq); + REQUEST_SIZE_MATCH(xPresentQueryVersionReq); swaps(&stuff->length); swapl(&stuff->majorVersion); @@ -265,6 +267,7 @@ static int sproc_present_pixmap(ClientPtr client) { REQUEST(xPresentPixmapReq); + REQUEST_AT_LEAST_SIZE(xPresentPixmapReq); swaps(&stuff->length); swapl(&stuff->window); @@ -284,6 +287,7 @@ static int sproc_present_notify_msc(ClientPtr client) { REQUEST(xPresentNotifyMSCReq); + REQUEST_SIZE_MATCH(xPresentNotifyMSCReq); swaps(&stuff->length); swapl(&stuff->window); @@ -297,6 +301,7 @@ static int sproc_present_select_input (ClientPtr client) { REQUEST(xPresentSelectInputReq); + REQUEST_SIZE_MATCH(xPresentSelectInputReq); swaps(&stuff->length); swapl(&stuff->window); @@ -308,6 +313,7 @@ static int sproc_present_query_capabilities (ClientPtr client) { REQUEST(xPresentQueryCapabilitiesReq); + REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq); swaps(&stuff->length); swapl(&stuff->target); return (*proc_present_vector[stuff->presentReqType]) (client); From 3df2fcf12499ebdb26b9b67419ea485a42041f33 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 19:38:09 -0800 Subject: [PATCH 13/37] randr: unvalidated lengths in RandR extension swapped procs [CVE-2014-8101] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- randr/rrsdispatch.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c index 08c3b6abe..47558cf75 100644 --- a/randr/rrsdispatch.c +++ b/randr/rrsdispatch.c @@ -27,6 +27,7 @@ SProcRRQueryVersion(ClientPtr client) { REQUEST(xRRQueryVersionReq); + REQUEST_SIZE_MATCH(xRRQueryVersionReq); swaps(&stuff->length); swapl(&stuff->majorVersion); swapl(&stuff->minorVersion); @@ -38,6 +39,7 @@ SProcRRGetScreenInfo(ClientPtr client) { REQUEST(xRRGetScreenInfoReq); + REQUEST_SIZE_MATCH(xRRGetScreenInfoReq); swaps(&stuff->length); swapl(&stuff->window); return (*ProcRandrVector[stuff->randrReqType]) (client); @@ -69,6 +71,7 @@ SProcRRSelectInput(ClientPtr client) { REQUEST(xRRSelectInputReq); + REQUEST_SIZE_MATCH(xRRSelectInputReq); swaps(&stuff->length); swapl(&stuff->window); swaps(&stuff->enable); @@ -152,6 +155,7 @@ SProcRRConfigureOutputProperty(ClientPtr client) { REQUEST(xRRConfigureOutputPropertyReq); + REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq); swaps(&stuff->length); swapl(&stuff->output); swapl(&stuff->property); From b5f9ef03df6a650571b29d3d1c1d2b67c6e84336 Mon Sep 17 00:00:00 2001 From: Julien Cristau Date: Tue, 28 Oct 2014 10:30:04 +0100 Subject: [PATCH 14/37] render: check request size before reading it [CVE-2014-8100 1/2] Otherwise we may be reading outside of the client request. Signed-off-by: Julien Cristau Reviewed-by: Alan Coopersmith Signed-off-by: Alan Coopersmith --- render/render.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render/render.c b/render/render.c index e3031da25..200e0c826 100644 --- a/render/render.c +++ b/render/render.c @@ -276,11 +276,11 @@ ProcRenderQueryVersion(ClientPtr client) REQUEST(xRenderQueryVersionReq); + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); + pRenderClient->major_version = stuff->majorVersion; pRenderClient->minor_version = stuff->minorVersion; - REQUEST_SIZE_MATCH(xRenderQueryVersionReq); - if ((stuff->majorVersion * 1000 + stuff->minorVersion) < (SERVER_RENDER_MAJOR_VERSION * 1000 + SERVER_RENDER_MINOR_VERSION)) { rep.majorVersion = stuff->majorVersion; From 5d3a788aeb2fbd3ca2812747dc18c94a8b981c63 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 19:51:29 -0800 Subject: [PATCH 15/37] render: unvalidated lengths in Render extn. swapped procs [CVE-2014-8100 2/2] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- render/render.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/render/render.c b/render/render.c index 200e0c826..723f380c2 100644 --- a/render/render.c +++ b/render/render.c @@ -1995,7 +1995,7 @@ static int SProcRenderQueryVersion(ClientPtr client) { REQUEST(xRenderQueryVersionReq); - + REQUEST_SIZE_MATCH(xRenderQueryVersionReq); swaps(&stuff->length); swapl(&stuff->majorVersion); swapl(&stuff->minorVersion); @@ -2006,6 +2006,7 @@ static int SProcRenderQueryPictFormats(ClientPtr client) { REQUEST(xRenderQueryPictFormatsReq); + REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); swaps(&stuff->length); return (*ProcRenderVector[stuff->renderReqType]) (client); } @@ -2014,6 +2015,7 @@ static int SProcRenderQueryPictIndexValues(ClientPtr client) { REQUEST(xRenderQueryPictIndexValuesReq); + REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); swaps(&stuff->length); swapl(&stuff->format); return (*ProcRenderVector[stuff->renderReqType]) (client); @@ -2029,6 +2031,7 @@ static int SProcRenderCreatePicture(ClientPtr client) { REQUEST(xRenderCreatePictureReq); + REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); swaps(&stuff->length); swapl(&stuff->pid); swapl(&stuff->drawable); @@ -2042,6 +2045,7 @@ static int SProcRenderChangePicture(ClientPtr client) { REQUEST(xRenderChangePictureReq); + REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); swaps(&stuff->length); swapl(&stuff->picture); swapl(&stuff->mask); @@ -2053,6 +2057,7 @@ static int SProcRenderSetPictureClipRectangles(ClientPtr client) { REQUEST(xRenderSetPictureClipRectanglesReq); + REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); swaps(&stuff->length); swapl(&stuff->picture); swaps(&stuff->xOrigin); @@ -2065,6 +2070,7 @@ static int SProcRenderFreePicture(ClientPtr client) { REQUEST(xRenderFreePictureReq); + REQUEST_SIZE_MATCH(xRenderFreePictureReq); swaps(&stuff->length); swapl(&stuff->picture); return (*ProcRenderVector[stuff->renderReqType]) (client); @@ -2074,6 +2080,7 @@ static int SProcRenderComposite(ClientPtr client) { REQUEST(xRenderCompositeReq); + REQUEST_SIZE_MATCH(xRenderCompositeReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->mask); @@ -2093,6 +2100,7 @@ static int SProcRenderScale(ClientPtr client) { REQUEST(xRenderScaleReq); + REQUEST_SIZE_MATCH(xRenderScaleReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->dst); @@ -2193,6 +2201,7 @@ static int SProcRenderCreateGlyphSet(ClientPtr client) { REQUEST(xRenderCreateGlyphSetReq); + REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); swaps(&stuff->length); swapl(&stuff->gsid); swapl(&stuff->format); @@ -2203,6 +2212,7 @@ static int SProcRenderReferenceGlyphSet(ClientPtr client) { REQUEST(xRenderReferenceGlyphSetReq); + REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); swaps(&stuff->length); swapl(&stuff->gsid); swapl(&stuff->existing); @@ -2213,6 +2223,7 @@ static int SProcRenderFreeGlyphSet(ClientPtr client) { REQUEST(xRenderFreeGlyphSetReq); + REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); swaps(&stuff->length); swapl(&stuff->glyphset); return (*ProcRenderVector[stuff->renderReqType]) (client); @@ -2227,6 +2238,7 @@ SProcRenderAddGlyphs(ClientPtr client) xGlyphInfo *gi; REQUEST(xRenderAddGlyphsReq); + REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); swaps(&stuff->length); swapl(&stuff->glyphset); swapl(&stuff->nglyphs); @@ -2261,6 +2273,7 @@ static int SProcRenderFreeGlyphs(ClientPtr client) { REQUEST(xRenderFreeGlyphsReq); + REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); swaps(&stuff->length); swapl(&stuff->glyphset); SwapRestL(stuff); @@ -2278,6 +2291,7 @@ SProcRenderCompositeGlyphs(ClientPtr client) int size; REQUEST(xRenderCompositeGlyphsReq); + REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); switch (stuff->renderReqType) { default: From a0ece23a8bd300c8be10812d368dc8058c97c63e Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 26 Jan 2014 20:02:20 -0800 Subject: [PATCH 16/37] xfixes: unvalidated length in SProcXFixesSelectSelectionInput [CVE-2014-8102] Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- xfixes/select.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xfixes/select.c b/xfixes/select.c index c088ed3de..e964d588c 100644 --- a/xfixes/select.c +++ b/xfixes/select.c @@ -201,6 +201,7 @@ SProcXFixesSelectSelectionInput(ClientPtr client) { REQUEST(xXFixesSelectSelectionInputReq); + REQUEST_SIZE_MATCH(xXFixesSelectSelectionInputReq); swaps(&stuff->length); swapl(&stuff->window); swapl(&stuff->selection); From d153a85f7478a7a67ccb02fbca6390b0ab1732ee Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 9 Feb 2014 21:27:27 -0800 Subject: [PATCH 17/37] Add request length checking test cases for some Xinput 1.x requests Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- configure.ac | 1 + test/Makefile.am | 2 +- test/xi1/Makefile.am | 34 +++++++ test/xi1/protocol-xchangedevicecontrol.c | 122 +++++++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 test/xi1/Makefile.am create mode 100644 test/xi1/protocol-xchangedevicecontrol.c diff --git a/configure.ac b/configure.ac index 140e33e45..96524c58b 100644 --- a/configure.ac +++ b/configure.ac @@ -2621,6 +2621,7 @@ hw/kdrive/linux/Makefile hw/kdrive/src/Makefile hw/xwayland/Makefile test/Makefile +test/xi1/Makefile test/xi2/Makefile xserver.ent xorg-server.pc diff --git a/test/Makefile.am b/test/Makefile.am index 83442767a..82578d977 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -4,7 +4,7 @@ noinst_PROGRAMS = list string if XORG # Tests that require at least some DDX functions in order to fully link # For now, requires xf86 ddx, could be adjusted to use another -SUBDIRS += xi2 +SUBDIRS += xi1 xi2 noinst_PROGRAMS += xkb input xtest misc fixes xfree86 os signal-logging touch if RES noinst_PROGRAMS += hashtabletest diff --git a/test/xi1/Makefile.am b/test/xi1/Makefile.am new file mode 100644 index 000000000..907fa7aea --- /dev/null +++ b/test/xi1/Makefile.am @@ -0,0 +1,34 @@ +if ENABLE_UNIT_TESTS +if HAVE_LD_WRAP +noinst_PROGRAMS = \ + protocol-xchangedevicecontrol + +TESTS=$(noinst_PROGRAMS) +TESTS_ENVIRONMENT = $(XORG_MALLOC_DEBUG_ENV) + +AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ +AM_CPPFLAGS = @XORG_INCS@ -I$(srcdir)/../xi2 +TEST_LDADD=../libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLX_SYS_LIBS) +COMMON_SOURCES=$(srcdir)/../xi2/protocol-common.c + +if SPECIAL_DTRACE_OBJECTS +TEST_LDADD += $(OS_LIB) $(DIX_LIB) +endif + +protocol_xchangedevicecontrol_LDADD=$(TEST_LDADD) + +protocol_xchangedevicecontrol_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient + +protocol_xchangedevicecontrol_SOURCES=$(COMMON_SOURCES) protocol-xchangedevicecontrol.c + +else +# Print that xi1-tests were skipped (exit code 77 for automake test harness) +TESTS = xi1-tests +CLEANFILES = $(TESTS) + +xi1-tests: + @echo 'echo "ld -wrap support required for xi1 unit tests, skipping"' > $@ + @echo 'exit 77' >> $@ + $(AM_V_GEN)chmod +x $@ +endif +endif diff --git a/test/xi1/protocol-xchangedevicecontrol.c b/test/xi1/protocol-xchangedevicecontrol.c new file mode 100644 index 000000000..8e638b218 --- /dev/null +++ b/test/xi1/protocol-xchangedevicecontrol.c @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +/* + * Protocol testing for ChangeDeviceControl request. + */ +#include +#include +#include +#include +#include "inputstr.h" +#include "chgdctl.h" + +#include "protocol-common.h" + +static ClientRec client_request; + +static void +reply_ChangeDeviceControl(ClientPtr client, int len, char *data, void *userdata) +{ + xChangeDeviceControlReply *rep = (xChangeDeviceControlReply *) data; + + if (client->swapped) { + swapl(&rep->length); + swaps(&rep->sequenceNumber); + } + + reply_check_defaults(rep, len, ChangeDeviceControl); + + /* XXX: check status code in reply */ +} + +static void +request_ChangeDeviceControl(ClientPtr client, xChangeDeviceControlReq * req, + xDeviceCtl *ctl, int error) +{ + int rc; + + client_request.req_len = req->length; + rc = ProcXChangeDeviceControl(&client_request); + assert(rc == error); + + /* XXX: ChangeDeviceControl doesn't seem to fill in errorValue to check */ + + client_request.swapped = TRUE; + swaps(&req->length); + swaps(&req->control); + swaps(&ctl->length); + swaps(&ctl->control); + /* XXX: swap other contents of ctl, depending on type */ + rc = SProcXChangeDeviceControl(&client_request); + assert(rc == error); +} + +static unsigned char *data[4096]; /* the request buffer */ + +static void +test_ChangeDeviceControl(void) +{ + xChangeDeviceControlReq *request = (xChangeDeviceControlReq *) data; + xDeviceCtl *control = (xDeviceCtl *) (&request[1]); + + request_init(request, ChangeDeviceControl); + + reply_handler = reply_ChangeDeviceControl; + + client_request = init_client(request->length, request); + + printf("Testing invalid lengths:\n"); + printf(" -- no control struct\n"); + request_ChangeDeviceControl(&client_request, request, control, BadLength); + + printf(" -- xDeviceResolutionCtl\n"); + request_init(request, ChangeDeviceControl); + request->control = DEVICE_RESOLUTION; + control->length = (sizeof(xDeviceResolutionCtl) >> 2); + request->length += control->length - 2; + request_ChangeDeviceControl(&client_request, request, control, BadLength); + + printf(" -- xDeviceEnableCtl\n"); + request_init(request, ChangeDeviceControl); + request->control = DEVICE_ENABLE; + control->length = (sizeof(xDeviceEnableCtl) >> 2); + request->length += control->length - 2; + request_ChangeDeviceControl(&client_request, request, control, BadLength); + + /* XXX: Test functionality! */ +} + +int +main(int argc, char **argv) +{ + init_simple(); + + test_ChangeDeviceControl(); + + return 0; +} From 2df83bb122debc3c20cfc3d3b0edc85cd0270f79 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 9 Feb 2014 21:28:05 -0800 Subject: [PATCH 18/37] Add request length checking test cases for some Xinput 2.x requests Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- test/xi2/protocol-xigetclientpointer.c | 5 +++++ test/xi2/protocol-xipassivegrabdevice.c | 8 ++++++++ test/xi2/protocol-xiquerypointer.c | 4 ++++ test/xi2/protocol-xiwarppointer.c | 3 +++ 4 files changed, 20 insertions(+) diff --git a/test/xi2/protocol-xigetclientpointer.c b/test/xi2/protocol-xigetclientpointer.c index 28eb8d32a..570c53e06 100644 --- a/test/xi2/protocol-xigetclientpointer.c +++ b/test/xi2/protocol-xigetclientpointer.c @@ -124,6 +124,11 @@ test_XIGetClientPointer(void) request.win = INVALID_WINDOW_ID; request_XIGetClientPointer(&client_request, &request, BadWindow); + printf("Testing invalid length\n"); + client_request.req_len -= 4; + request_XIGetClientPointer(&client_request, &request, BadLength); + client_request.req_len += 4; + test_data.cp_is_set = FALSE; printf("Testing window None, unset ClientPointer.\n"); diff --git a/test/xi2/protocol-xipassivegrabdevice.c b/test/xi2/protocol-xipassivegrabdevice.c index c747ddf03..95d8ebf2b 100644 --- a/test/xi2/protocol-xipassivegrabdevice.c +++ b/test/xi2/protocol-xipassivegrabdevice.c @@ -139,6 +139,7 @@ request_XIPassiveGrabDevice(ClientPtr client, xXIPassiveGrabDeviceReq * req, int local_modifiers; int mask_len; + client_request.req_len = req->length; rc = ProcXIPassiveGrabDevice(&client_request); assert(rc == error); @@ -190,6 +191,13 @@ test_XIPassiveGrabDevice(void) request_XIPassiveGrabDevice(&client_request, request, BadDevice, request->deviceid); + printf("Testing invalid length\n"); + request->length -= 2; + request_XIPassiveGrabDevice(&client_request, request, BadLength, + client_request.errorValue); + /* re-init request since swapped length test leaves some values swapped */ + request_init(request, XIPassiveGrabDevice); + request->grab_window = CLIENT_WINDOW_ID; request->deviceid = XIAllMasterDevices; printf("Testing invalid grab types\n"); diff --git a/test/xi2/protocol-xiquerypointer.c b/test/xi2/protocol-xiquerypointer.c index fc66b6429..c0421f6dd 100644 --- a/test/xi2/protocol-xiquerypointer.c +++ b/test/xi2/protocol-xiquerypointer.c @@ -201,6 +201,10 @@ test_XIQueryPointer(void) test_data.dev = devices.mouse; request.deviceid = devices.mouse->id; request_XIQueryPointer(&client_request, &request, Success); + + /* test REQUEST_SIZE_MATCH */ + client_request.req_len -= 4; + request_XIQueryPointer(&client_request, &request, BadLength); } int diff --git a/test/xi2/protocol-xiwarppointer.c b/test/xi2/protocol-xiwarppointer.c index f7986c1eb..3aaaae6f9 100644 --- a/test/xi2/protocol-xiwarppointer.c +++ b/test/xi2/protocol-xiwarppointer.c @@ -198,6 +198,9 @@ test_XIWarpPointer(void) request_XIWarpPointer(&client_request, &request, Success); /* FIXME: src_x/y checks */ + + client_request.req_len -= 2; /* invalid length */ + request_XIWarpPointer(&client_request, &request, BadLength); } int From f4afd53f2aeaddf509bf9f71d1716dd273fd6e14 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 9 Feb 2014 22:42:47 -0800 Subject: [PATCH 19/37] Add REQUEST_FIXED_SIZE testcases to test/misc.c Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- test/misc.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/misc.c b/test/misc.c index dd792e692..66330a140 100644 --- a/test/misc.c +++ b/test/misc.c @@ -28,6 +28,8 @@ #include #include "misc.h" #include "scrnintstr.h" +#include "dix.h" +#include "dixstruct.h" ScreenInfo screenInfo; @@ -155,11 +157,46 @@ dix_update_desktop_dimensions(void) assert_dimensions(-w2, -h2, w2, h2); } +static int +dix_request_fixed_size_overflow(ClientRec *client) +{ + xReq req = { 0 }; + + client->req_len = req.length = 1; + REQUEST_FIXED_SIZE(req, SIZE_MAX); + return Success; +} + +static int +dix_request_fixed_size_match(ClientRec *client) +{ + xReq req = { 0 }; + + client->req_len = req.length = 9; + REQUEST_FIXED_SIZE(req, 30); + return Success; +} + +static void +dix_request_size_checks(void) +{ + ClientRec client = { 0 }; + int rc; + + rc = dix_request_fixed_size_overflow(&client); + assert(rc == BadLength); + + rc = dix_request_fixed_size_match(&client); + assert(rc == Success); +} + + int main(int argc, char **argv) { dix_version_compare(); dix_update_desktop_dimensions(); + dix_request_size_checks(); return 0; } From 23fe7718bb171e71db2d1a30505c2ca2988799d9 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:36 -0500 Subject: [PATCH 20/37] glx: Be more paranoid about variable-length requests [CVE-2014-8093 1/6] If the size computation routine returns -1 we should just reject the request outright. Clamping it to zero could give an attacker the opportunity to also mangle cmdlen in such a way that the subsequent length check passes, and the request would get executed, thus passing data we wanted to reject to the renderer. Reviewed-by: Keith Packard Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/glxcmds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 009fd9be0..ea42e2a01 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -2062,7 +2062,7 @@ __glXDisp_Render(__GLXclientState * cl, GLbyte * pc) extra = (*entry.varsize) (pc + __GLX_RENDER_HDR_SIZE, client->swapped); if (extra < 0) { - extra = 0; + return BadLength; } if (cmdlen != __GLX_PAD(entry.bytes + extra)) { return BadLength; @@ -2179,7 +2179,7 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) extra = (*entry.varsize) (pc + __GLX_RENDER_LARGE_HDR_SIZE, client->swapped); if (extra < 0) { - extra = 0; + return BadLength; } /* large command's header is 4 bytes longer, so add 4 */ if (cmdlen != __GLX_PAD(entry.bytes + 4 + extra)) { From ab2ba9338aa5e85b4487bc7fbe69985c76483e01 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:37 -0500 Subject: [PATCH 21/37] glx: Be more strict about rejecting invalid image sizes [CVE-2014-8093 2/6] Before this we'd just clamp the image size to 0, which was just hideously stupid; if the parameters were such that they'd overflow an integer, you'd allocate a small buffer, then pass huge values into (say) ReadPixels, and now you're scribbling over arbitrary server memory. Reviewed-by: Keith Packard Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/singlepix.c | 16 ++++++++-------- glx/singlepixswap.c | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/glx/singlepix.c b/glx/singlepix.c index 506fdaad5..8b6c26187 100644 --- a/glx/singlepix.c +++ b/glx/singlepix.c @@ -65,7 +65,7 @@ __glXDisp_ReadPixels(__GLXclientState * cl, GLbyte * pc) lsbFirst = *(GLboolean *) (pc + 25); compsize = __glReadPixels_size(format, type, width, height); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes); glPixelStorei(GL_PACK_LSB_FIRST, lsbFirst); @@ -124,7 +124,7 @@ __glXDisp_GetTexImage(__GLXclientState * cl, GLbyte * pc) compsize = __glGetTexImage_size(target, level, format, type, width, height, depth); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -218,9 +218,9 @@ GetSeparableFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) compsize2 = __glGetTexImage_size(target, 1, format, type, height, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; if (compsize2 < 0) - compsize2 = 0; + return BadLength; compsize = __GLX_PAD(compsize); compsize2 = __GLX_PAD(compsize2); @@ -296,7 +296,7 @@ GetConvolutionFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) */ compsize = __glGetTexImage_size(target, 1, format, type, width, height, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -365,7 +365,7 @@ GetHistogram(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) */ compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -426,7 +426,7 @@ GetMinmax(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) compsize = __glGetTexImage_size(target, 1, format, type, 2, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -491,7 +491,7 @@ GetColorTable(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) */ compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); diff --git a/glx/singlepixswap.c b/glx/singlepixswap.c index 846910153..8dc304fa7 100644 --- a/glx/singlepixswap.c +++ b/glx/singlepixswap.c @@ -75,7 +75,7 @@ __glXDispSwap_ReadPixels(__GLXclientState * cl, GLbyte * pc) lsbFirst = *(GLboolean *) (pc + 25); compsize = __glReadPixels_size(format, type, width, height); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); glPixelStorei(GL_PACK_LSB_FIRST, lsbFirst); @@ -144,7 +144,7 @@ __glXDispSwap_GetTexImage(__GLXclientState * cl, GLbyte * pc) compsize = __glGetTexImage_size(target, level, format, type, width, height, depth); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -252,9 +252,9 @@ GetSeparableFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) compsize2 = __glGetTexImage_size(target, 1, format, type, height, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; if (compsize2 < 0) - compsize2 = 0; + return BadLength; compsize = __GLX_PAD(compsize); compsize2 = __GLX_PAD(compsize2); @@ -338,7 +338,7 @@ GetConvolutionFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) */ compsize = __glGetTexImage_size(target, 1, format, type, width, height, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -415,7 +415,7 @@ GetHistogram(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) */ compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -483,7 +483,7 @@ GetMinmax(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) compsize = __glGetTexImage_size(target, 1, format, type, 2, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); @@ -554,7 +554,7 @@ GetColorTable(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) */ compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1); if (compsize < 0) - compsize = 0; + return BadLength; glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); __GLX_GET_ANSWER_BUFFER(answer, cl, compsize, 1); From 717a1b37767b41e14859e5022ae9e679152821a9 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:38 -0500 Subject: [PATCH 22/37] glx: Additional paranoia in __glXGetAnswerBuffer / __GLX_GET_ANSWER_BUFFER (v2) [CVE-2014-8093 3/6] If the computed reply size is negative, something went wrong, treat it as an error. v2: Be more careful about size_t being unsigned (Matthieu Herrb) v3: SIZE_MAX not SIZE_T_MAX (Alan Coopersmith) Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/indirect_util.c | 7 ++++++- glx/unpack.h | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/glx/indirect_util.c b/glx/indirect_util.c index 926e57c78..de8149127 100644 --- a/glx/indirect_util.c +++ b/glx/indirect_util.c @@ -76,9 +76,14 @@ __glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size, const unsigned mask = alignment - 1; if (local_size < required_size) { - const size_t worst_case_size = required_size + alignment; + size_t worst_case_size; intptr_t temp_buf; + if (required_size < SIZE_MAX - alignment) + worst_case_size = required_size + alignment; + else + return NULL; + if (cl->returnBufSize < worst_case_size) { void *temp = realloc(cl->returnBuf, worst_case_size); diff --git a/glx/unpack.h b/glx/unpack.h index 52fba74e1..2b1ebcf02 100644 --- a/glx/unpack.h +++ b/glx/unpack.h @@ -83,7 +83,8 @@ extern xGLXSingleReply __glXReply; ** pointer. */ #define __GLX_GET_ANSWER_BUFFER(res,cl,size,align) \ - if ((size) > sizeof(answerBuffer)) { \ + if (size < 0) return BadLength; \ + else if ((size) > sizeof(answerBuffer)) { \ int bump; \ if ((cl)->returnBufSize < (size)+(align)) { \ (cl)->returnBuf = (GLbyte*)realloc((cl)->returnBuf, \ From 13d36923e0ddb077f4854e354c3d5c80590b5d9d Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:39 -0500 Subject: [PATCH 23/37] glx: Fix image size computation for EXT_texture_integer [CVE-2014-8098 1/8] Without this we'd reject the request with BadLength. Note that some old versions of Mesa had a bug in the same place, and would _send_ zero bytes of image data; these will now be rejected, correctly. Reviewed-by: Keith Packard Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/rensize.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/glx/rensize.c b/glx/rensize.c index ba22d1067..9ff73c764 100644 --- a/glx/rensize.c +++ b/glx/rensize.c @@ -224,6 +224,11 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, case GL_ALPHA: case GL_LUMINANCE: case GL_INTENSITY: + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + case GL_LUMINANCE_INTEGER_EXT: elementsPerGroup = 1; break; case GL_422_EXT: @@ -234,14 +239,19 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, case GL_DEPTH_STENCIL_MESA: case GL_YCBCR_MESA: case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: elementsPerGroup = 2; break; case GL_RGB: case GL_BGR: + case GL_RGB_INTEGER_EXT: + case GL_BGR_INTEGER_EXT: elementsPerGroup = 3; break; case GL_RGBA: case GL_BGRA: + case GL_RGBA_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: case GL_ABGR_EXT: elementsPerGroup = 4; break; From 2a5cbc17fc72185bf0fa06fef26d1f782de72595 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:40 -0500 Subject: [PATCH 24/37] glx: Add safe_{add,mul,pad} (v3) [CVE-2014-8093 4/6] These are paranoid about integer overflow, and will return -1 if their operation would overflow a (signed) integer or if either argument is negative. Note that RenderLarge requests are sized with a uint32_t so in principle this could be sketchy there, but dix limits bigreqs to 128M so you shouldn't ever notice, and honestly if you're sending more than 2G of rendering commands you're already doing something very wrong. v2: Use INT_MAX for consistency with the rest of the server (jcristau) v3: Reject negative arguments (anholt) Reviewed-by: Keith Packard Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/glxserver.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/glx/glxserver.h b/glx/glxserver.h index a324b290f..948260149 100644 --- a/glx/glxserver.h +++ b/glx/glxserver.h @@ -228,6 +228,47 @@ extern void glxSwapQueryServerStringReply(ClientPtr client, * Routines for computing the size of variably-sized rendering commands. */ +static _X_INLINE int +safe_add(int a, int b) +{ + if (a < 0 || b < 0) + return -1; + + if (INT_MAX - a < b) + return -1; + + return a + b; +} + +static _X_INLINE int +safe_mul(int a, int b) +{ + if (a < 0 || b < 0) + return -1; + + if (a == 0 || b == 0) + return 0; + + if (a > INT_MAX / b) + return -1; + + return a * b; +} + +static _X_INLINE int +safe_pad(int a) +{ + int ret; + + if (a < 0) + return -1; + + if ((ret = safe_add(a, 3)) < 0) + return -1; + + return ret & (GLuint)~3; +} + extern int __glXTypeSize(GLenum enm); extern int __glXImageSize(GLenum format, GLenum type, GLenum target, GLsizei w, GLsizei h, GLsizei d, From be09e0c988ffdb0371293af49fb4ea8f49ed324a Mon Sep 17 00:00:00 2001 From: Julien Cristau Date: Mon, 10 Nov 2014 12:13:41 -0500 Subject: [PATCH 25/37] glx: Length checking for GLXRender requests (v2) [CVE-2014-8098 2/8] v2: Remove can't-happen comparison for cmdlen < 0 (Michal Srb) Reviewed-by: Adam Jackson Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Julien Cristau Signed-off-by: Alan Coopersmith --- glx/glxcmds.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/glx/glxcmds.c b/glx/glxcmds.c index ea42e2a01..ddd911933 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -2025,7 +2025,7 @@ __glXDisp_Render(__GLXclientState * cl, GLbyte * pc) left = (req->length << 2) - sz_xGLXRenderReq; while (left > 0) { __GLXrenderSizeData entry; - int extra; + int extra = 0; __GLXdispatchRenderProcPtr proc; int err; @@ -2044,6 +2044,9 @@ __glXDisp_Render(__GLXclientState * cl, GLbyte * pc) cmdlen = hdr->length; opcode = hdr->opcode; + if (left < cmdlen) + return BadLength; + /* ** Check for core opcodes and grab entry data. */ @@ -2057,6 +2060,10 @@ __glXDisp_Render(__GLXclientState * cl, GLbyte * pc) return __glXError(GLXBadRenderRequest); } + if (cmdlen < entry.bytes) { + return BadLength; + } + if (entry.varsize) { /* variable size command */ extra = (*entry.varsize) (pc + __GLX_RENDER_HDR_SIZE, @@ -2064,17 +2071,9 @@ __glXDisp_Render(__GLXclientState * cl, GLbyte * pc) if (extra < 0) { return BadLength; } - if (cmdlen != __GLX_PAD(entry.bytes + extra)) { - return BadLength; - } } - else { - /* constant size command */ - if (cmdlen != __GLX_PAD(entry.bytes)) { - return BadLength; - } - } - if (left < cmdlen) { + + if (cmdlen != safe_pad(safe_add(entry.bytes, extra))) { return BadLength; } From 698888e6671d54c7ae41e9d456f7f5483a3459d2 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:42 -0500 Subject: [PATCH 26/37] glx: Integer overflow protection for non-generated render requests (v3) [CVE-2014-8093 5/6] v2: Fix constants in __glXMap2fReqSize (Michal Srb) Validate w/h/d for proxy targets too (Keith Packard) v3: Fix Map[12]Size to correctly reject order == 0 (Julien Cristau) Reviewed-by: Keith Packard Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/rensize.c | 77 +++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/glx/rensize.c b/glx/rensize.c index 9ff73c764..d46334a71 100644 --- a/glx/rensize.c +++ b/glx/rensize.c @@ -43,19 +43,11 @@ (((a & 0xff000000U)>>24) | ((a & 0xff0000U)>>8) | \ ((a & 0xff00U)<<8) | ((a & 0xffU)<<24)) -static int -Map1Size(GLint k, GLint order) -{ - if (order <= 0 || k < 0) - return -1; - return k * order; -} - int __glXMap1dReqSize(const GLbyte * pc, Bool swap) { GLenum target; - GLint order, k; + GLint order; target = *(GLenum *) (pc + 16); order = *(GLint *) (pc + 20); @@ -63,15 +55,16 @@ __glXMap1dReqSize(const GLbyte * pc, Bool swap) target = SWAPL(target); order = SWAPL(order); } - k = __glMap1d_size(target); - return 8 * Map1Size(k, order); + if (order < 1) + return -1; + return safe_mul(8, safe_mul(__glMap1d_size(target), order)); } int __glXMap1fReqSize(const GLbyte * pc, Bool swap) { GLenum target; - GLint order, k; + GLint order; target = *(GLenum *) (pc + 0); order = *(GLint *) (pc + 12); @@ -79,23 +72,24 @@ __glXMap1fReqSize(const GLbyte * pc, Bool swap) target = SWAPL(target); order = SWAPL(order); } - k = __glMap1f_size(target); - return 4 * Map1Size(k, order); + if (order < 1) + return -1; + return safe_mul(4, safe_mul(__glMap1f_size(target), order)); } static int Map2Size(int k, int majorOrder, int minorOrder) { - if (majorOrder <= 0 || minorOrder <= 0 || k < 0) + if (majorOrder < 1 || minorOrder < 1) return -1; - return k * majorOrder * minorOrder; + return safe_mul(k, safe_mul(majorOrder, minorOrder)); } int __glXMap2dReqSize(const GLbyte * pc, Bool swap) { GLenum target; - GLint uorder, vorder, k; + GLint uorder, vorder; target = *(GLenum *) (pc + 32); uorder = *(GLint *) (pc + 36); @@ -105,15 +99,14 @@ __glXMap2dReqSize(const GLbyte * pc, Bool swap) uorder = SWAPL(uorder); vorder = SWAPL(vorder); } - k = __glMap2d_size(target); - return 8 * Map2Size(k, uorder, vorder); + return safe_mul(8, Map2Size(__glMap2d_size(target), uorder, vorder)); } int __glXMap2fReqSize(const GLbyte * pc, Bool swap) { GLenum target; - GLint uorder, vorder, k; + GLint uorder, vorder; target = *(GLenum *) (pc + 0); uorder = *(GLint *) (pc + 12); @@ -123,8 +116,7 @@ __glXMap2fReqSize(const GLbyte * pc, Bool swap) uorder = SWAPL(uorder); vorder = SWAPL(vorder); } - k = __glMap2f_size(target); - return 4 * Map2Size(k, uorder, vorder); + return safe_mul(4, Map2Size(__glMap2f_size(target), uorder, vorder)); } /** @@ -175,14 +167,16 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, GLint bytesPerElement, elementsPerGroup, groupsPerRow; GLint groupSize, rowSize, padding, imageSize; + if (w == 0 || h == 0 || d == 0) + return 0; + if (w < 0 || h < 0 || d < 0 || (type == GL_BITMAP && (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX))) { return -1; } - if (w == 0 || h == 0 || d == 0) - return 0; + /* proxy targets have no data */ switch (target) { case GL_PROXY_TEXTURE_1D: case GL_PROXY_TEXTURE_2D: @@ -199,6 +193,12 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, return 0; } + /* real data has to have real sizes */ + if (imageHeight < 0 || rowLength < 0 || skipImages < 0 || skipRows < 0) + return -1; + if (alignment != 1 && alignment != 2 && alignment != 4 && alignment != 8) + return -1; + if (type == GL_BITMAP) { if (rowLength > 0) { groupsPerRow = rowLength; @@ -207,11 +207,14 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, groupsPerRow = w; } rowSize = bits_to_bytes(groupsPerRow); + if (rowSize < 0) + return -1; padding = (rowSize % alignment); if (padding) { rowSize += alignment - padding; } - return ((h + skipRows) * rowSize); + + return safe_mul(safe_add(h, skipRows), rowSize); } else { switch (format) { @@ -303,6 +306,7 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, default: return -1; } + /* known safe by the switches above, not checked */ groupSize = bytesPerElement * elementsPerGroup; if (rowLength > 0) { groupsPerRow = rowLength; @@ -310,18 +314,21 @@ __glXImageSize(GLenum format, GLenum type, GLenum target, else { groupsPerRow = w; } - rowSize = groupsPerRow * groupSize; + + if ((rowSize = safe_mul(groupsPerRow, groupSize)) < 0) + return -1; padding = (rowSize % alignment); if (padding) { rowSize += alignment - padding; } - if (imageHeight > 0) { - imageSize = (imageHeight + skipRows) * rowSize; - } - else { - imageSize = (h + skipRows) * rowSize; - } - return ((d + skipImages) * imageSize); + + if (imageHeight > 0) + h = imageHeight; + h = safe_add(h, skipRows); + + imageSize = safe_mul(h, rowSize); + + return safe_mul(safe_add(d, skipImages), imageSize); } } @@ -445,9 +452,7 @@ __glXSeparableFilter2DReqSize(const GLbyte * pc, Bool swap) /* XXX Should rowLength be used for either or both image? */ image1size = __glXImageSize(format, type, 0, w, 1, 1, 0, rowLength, 0, 0, alignment); - image1size = __GLX_PAD(image1size); image2size = __glXImageSize(format, type, 0, h, 1, 1, 0, rowLength, 0, 0, alignment); - return image1size + image2size; - + return safe_add(safe_pad(image1size), image2size); } From a33a939e6abb255b14d8dbc85fcbd2c55b958bae Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:43 -0500 Subject: [PATCH 27/37] glx: Length checking for RenderLarge requests (v2) [CVE-2014-8098 3/8] This is a half-measure until we start passing request length into the varsize function, but it's better than the nothing we had before. v2: Verify that there's at least a large render header's worth of dataBytes (Julien Cristau) Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/glxcmds.c | 57 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/glx/glxcmds.c b/glx/glxcmds.c index ddd911933..a7a517293 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -2109,6 +2109,8 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) __GLX_DECLARE_SWAP_VARIABLES; + REQUEST_AT_LEAST_SIZE(xGLXRenderLargeReq); + req = (xGLXRenderLargeReq *) pc; if (client->swapped) { __GLX_SWAP_SHORT(&req->length); @@ -2124,12 +2126,14 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) __glXResetLargeCommandStatus(cl); return error; } + if (safe_pad(req->dataBytes) < 0) + return BadLength; dataBytes = req->dataBytes; /* ** Check the request length. */ - if ((req->length << 2) != __GLX_PAD(dataBytes) + sz_xGLXRenderLargeReq) { + if ((req->length << 2) != safe_pad(dataBytes) + sz_xGLXRenderLargeReq) { client->errorValue = req->length; /* Reset in case this isn't 1st request. */ __glXResetLargeCommandStatus(cl); @@ -2139,7 +2143,7 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) if (cl->largeCmdRequestsSoFar == 0) { __GLXrenderSizeData entry; - int extra; + int extra = 0; size_t cmdlen; int err; @@ -2152,13 +2156,17 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) return __glXError(GLXBadLargeRequest); } + if (dataBytes < __GLX_RENDER_LARGE_HDR_SIZE) + return BadLength; + hdr = (__GLXrenderLargeHeader *) pc; if (client->swapped) { __GLX_SWAP_INT(&hdr->length); __GLX_SWAP_INT(&hdr->opcode); } - cmdlen = hdr->length; opcode = hdr->opcode; + if ((cmdlen = safe_pad(hdr->length)) < 0) + return BadLength; /* ** Check for core opcodes and grab entry data. @@ -2180,17 +2188,13 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) if (extra < 0) { return BadLength; } - /* large command's header is 4 bytes longer, so add 4 */ - if (cmdlen != __GLX_PAD(entry.bytes + 4 + extra)) { - return BadLength; - } } - else { - /* constant size command */ - if (cmdlen != __GLX_PAD(entry.bytes + 4)) { - return BadLength; - } + + /* the +4 is safe because we know entry.bytes is small */ + if (cmdlen != safe_pad(safe_add(entry.bytes + 4, extra))) { + return BadLength; } + /* ** Make enough space in the buffer, then copy the entire request. */ @@ -2217,6 +2221,7 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) ** We are receiving subsequent (i.e. not the first) requests of a ** multi request command. */ + int bytesSoFar; /* including this packet */ /* ** Check the request number and the total request count. @@ -2235,11 +2240,18 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) /* ** Check that we didn't get too much data. */ - if ((cl->largeCmdBytesSoFar + dataBytes) > cl->largeCmdBytesTotal) { + if ((bytesSoFar = safe_add(cl->largeCmdBytesSoFar, dataBytes)) < 0) { client->errorValue = dataBytes; __glXResetLargeCommandStatus(cl); return __glXError(GLXBadLargeRequest); } + + if (bytesSoFar > cl->largeCmdBytesTotal) { + client->errorValue = dataBytes; + __glXResetLargeCommandStatus(cl); + return __glXError(GLXBadLargeRequest); + } + memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes); cl->largeCmdBytesSoFar += dataBytes; cl->largeCmdRequestsSoFar++; @@ -2251,17 +2263,16 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) ** This is the last request; it must have enough bytes to complete ** the command. */ - /* NOTE: the two pad macros have been added below; they are needed - ** because the client library pads the total byte count, but not - ** the per-request byte counts. The Protocol Encoding says the - ** total byte count should not be padded, so a proposal will be - ** made to the ARB to relax the padding constraint on the total - ** byte count, thus preserving backward compatibility. Meanwhile, - ** the padding done below fixes a bug that did not allow - ** large commands of odd sizes to be accepted by the server. + /* NOTE: the pad macro below is needed because the client library + ** pads the total byte count, but not the per-request byte counts. + ** The Protocol Encoding says the total byte count should not be + ** padded, so a proposal will be made to the ARB to relax the + ** padding constraint on the total byte count, thus preserving + ** backward compatibility. Meanwhile, the padding done below + ** fixes a bug that did not allow large commands of odd sizes to + ** be accepted by the server. */ - if (__GLX_PAD(cl->largeCmdBytesSoFar) != - __GLX_PAD(cl->largeCmdBytesTotal)) { + if (safe_pad(cl->largeCmdBytesSoFar) != cl->largeCmdBytesTotal) { client->errorValue = dataBytes; __glXResetLargeCommandStatus(cl); return __glXError(GLXBadLargeRequest); From c91e4abc3b892f42802efa20fef7ada442c2d3f5 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:44 -0500 Subject: [PATCH 28/37] glx: Top-level length checking for swapped VendorPrivate requests [CVE-2014-8098 4/8] Reviewed-by: Keith Packard Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/glxcmdsswap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/glx/glxcmdsswap.c b/glx/glxcmdsswap.c index 5d179f317..9ec1222f8 100644 --- a/glx/glxcmdsswap.c +++ b/glx/glxcmdsswap.c @@ -958,11 +958,13 @@ __glXDispSwap_RenderLarge(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_VendorPrivate(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; xGLXVendorPrivateReq *req; GLint vendorcode; __GLXdispatchVendorPrivProcPtr proc; __GLX_DECLARE_SWAP_VARIABLES; + REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); req = (xGLXVendorPrivateReq *) pc; __GLX_SWAP_SHORT(&req->length); @@ -985,11 +987,13 @@ __glXDispSwap_VendorPrivate(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_VendorPrivateWithReply(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; xGLXVendorPrivateWithReplyReq *req; GLint vendorcode; __GLXdispatchVendorPrivProcPtr proc; __GLX_DECLARE_SWAP_VARIABLES; + REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateWithReplyReq); req = (xGLXVendorPrivateWithReplyReq *) pc; __GLX_SWAP_SHORT(&req->length); From afe177020d1fb776c6163f21eddc82cb185b95ca Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:45 -0500 Subject: [PATCH 29/37] glx: Request length checks for SetClientInfoARB [CVE-2014-8098 5/8] Reviewed-by: Keith Packard Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/clientinfo.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/glx/clientinfo.c b/glx/clientinfo.c index 4aaa4c967..c5fef3074 100644 --- a/glx/clientinfo.c +++ b/glx/clientinfo.c @@ -33,18 +33,21 @@ static int set_client_info(__GLXclientState * cl, xGLXSetClientInfoARBReq * req, unsigned bytes_per_version) { + ClientPtr client = cl->client; char *gl_extensions; char *glx_extensions; + REQUEST_AT_LEAST_SIZE(xGLXSetClientInfoARBReq); + /* Verify that the size of the packet matches the size inferred from the * sizes specified for the various fields. */ - const unsigned expected_size = sz_xGLXSetClientInfoARBReq - + (req->numVersions * bytes_per_version) - + __GLX_PAD(req->numGLExtensionBytes) - + __GLX_PAD(req->numGLXExtensionBytes); + int size = sz_xGLXSetClientInfoARBReq; + size = safe_add(size, safe_mul(req->numVersions, bytes_per_version)); + size = safe_add(size, safe_pad(req->numGLExtensionBytes)); + size = safe_add(size, safe_pad(req->numGLXExtensionBytes)); - if (req->length != (expected_size / 4)) + if (size < 0 || req->length != (size / 4)) return BadLength; /* Verify that the actual length of the GL extension string matches what's @@ -80,8 +83,11 @@ __glXDisp_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_SetClientInfoARB(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc; + REQUEST_AT_LEAST_SIZE(xGLXSetClientInfoARBReq); + req->length = bswap_16(req->length); req->numVersions = bswap_32(req->numVersions); req->numGLExtensionBytes = bswap_32(req->numGLExtensionBytes); @@ -99,8 +105,11 @@ __glXDisp_SetClientInfo2ARB(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_SetClientInfo2ARB(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; xGLXSetClientInfoARBReq *req = (xGLXSetClientInfoARBReq *) pc; + REQUEST_AT_LEAST_SIZE(xGLXSetClientInfoARBReq); + req->length = bswap_16(req->length); req->numVersions = bswap_32(req->numVersions); req->numGLExtensionBytes = bswap_32(req->numGLExtensionBytes); From 44ba149f28ece93c2fbfc9cc980588de5322dd4b Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:46 -0500 Subject: [PATCH 30/37] glx: Length-checking for non-generated vendor private requests [CVE-2014-8098 6/8] Reviewed-by: Keith Packard Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/indirect_program.c | 2 ++ glx/swap_interval.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/glx/indirect_program.c b/glx/indirect_program.c index cda139ee6..5caee7b2a 100644 --- a/glx/indirect_program.c +++ b/glx/indirect_program.c @@ -56,6 +56,8 @@ DoGetProgramString(struct __GLXclientStateRec *cl, GLbyte * pc, __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error); ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateWithReplyReq, 8); + pc += __GLX_VENDPRIV_HDR_SIZE; if (cx != NULL) { GLenum target; diff --git a/glx/swap_interval.c b/glx/swap_interval.c index 17bc99207..232055080 100644 --- a/glx/swap_interval.c +++ b/glx/swap_interval.c @@ -46,6 +46,8 @@ DoSwapInterval(__GLXclientState * cl, GLbyte * pc, int do_swap) __GLXcontext *cx; GLint interval; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 4); + cx = __glXLookupContextByTag(cl, tag); if ((cx == NULL) || (cx->pGlxScreen == NULL)) { From 984583a497c813df5827ae22483133e704fee79c Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:47 -0500 Subject: [PATCH 31/37] glx: Length checking for non-generated single requests (v2) [CVE-2014-8098 7/8] v2: Fix single versus vendor-private length checking for ARB_imaging subset extensions. (Julien Cristau) v3: Fix single versus vendor-private length checking for ARB_imaging subset extensions. (Julien Cristau) Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Julien Cristau Signed-off-by: Alan Coopersmith --- glx/indirect_texture_compression.c | 4 +++ glx/single2.c | 23 ++++++++++++---- glx/single2swap.c | 19 ++++++++++--- glx/singlepix.c | 44 ++++++++++++++++++++---------- glx/singlepixswap.c | 34 +++++++++++++++++++---- 5 files changed, 95 insertions(+), 29 deletions(-) diff --git a/glx/indirect_texture_compression.c b/glx/indirect_texture_compression.c index cda765698..1ebf7f3a2 100644 --- a/glx/indirect_texture_compression.c +++ b/glx/indirect_texture_compression.c @@ -43,6 +43,8 @@ __glXDisp_GetCompressedTexImage(struct __GLXclientStateRec *cl, GLbyte * pc) __GLXcontext *const cx = __glXForceCurrent(cl, req->contextTag, &error); ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 8); + pc += __GLX_SINGLE_HDR_SIZE; if (cx != NULL) { const GLenum target = *(GLenum *) (pc + 0); @@ -87,6 +89,8 @@ __glXDispSwap_GetCompressedTexImage(struct __GLXclientStateRec *cl, GLbyte * pc) __glXForceCurrent(cl, bswap_32(req->contextTag), &error); ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 8); + pc += __GLX_SINGLE_HDR_SIZE; if (cx != NULL) { const GLenum target = (GLenum) bswap_32(*(int *) (pc + 0)); diff --git a/glx/single2.c b/glx/single2.c index 53b661d20..a6ea614fd 100644 --- a/glx/single2.c +++ b/glx/single2.c @@ -45,11 +45,14 @@ int __glXDisp_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; GLsizei size; GLenum type; __GLXcontext *cx; int error; + REQUEST_FIXED_SIZE(xGLXSingleReq, 8); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -76,10 +79,13 @@ __glXDisp_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc) int __glXDisp_SelectBuffer(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; __GLXcontext *cx; GLsizei size; int error; + REQUEST_FIXED_SIZE(xGLXSingleReq, 4); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -104,7 +110,7 @@ __glXDisp_SelectBuffer(__GLXclientState * cl, GLbyte * pc) int __glXDisp_RenderMode(__GLXclientState * cl, GLbyte * pc) { - ClientPtr client; + ClientPtr client = cl->client; xGLXRenderModeReply reply; __GLXcontext *cx; GLint nitems = 0, retBytes = 0, retval, newModeCheck; @@ -112,6 +118,8 @@ __glXDisp_RenderMode(__GLXclientState * cl, GLbyte * pc) GLenum newMode; int error; + REQUEST_FIXED_SIZE(xGLXSingleReq, 4); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -188,7 +196,6 @@ __glXDisp_RenderMode(__GLXclientState * cl, GLbyte * pc) ** selection array, as per the API for glRenderMode itself. */ noChangeAllowed:; - client = cl->client; reply = (xGLXRenderModeReply) { .type = X_Reply, .sequenceNumber = client->sequence, @@ -207,9 +214,12 @@ __glXDisp_RenderMode(__GLXclientState * cl, GLbyte * pc) int __glXDisp_Flush(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; __GLXcontext *cx; int error; + REQUEST_SIZE_MATCH(xGLXSingleReq); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -223,10 +233,12 @@ __glXDisp_Flush(__GLXclientState * cl, GLbyte * pc) int __glXDisp_Finish(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; __GLXcontext *cx; - ClientPtr client; int error; + REQUEST_SIZE_MATCH(xGLXSingleReq); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -317,7 +329,7 @@ __glXcombine_strings(const char *cext_string, const char *sext_string) int DoGetString(__GLXclientState * cl, GLbyte * pc, GLboolean need_swap) { - ClientPtr client; + ClientPtr client = cl->client; __GLXcontext *cx; GLenum name; const char *string; @@ -327,6 +339,8 @@ DoGetString(__GLXclientState * cl, GLbyte * pc, GLboolean need_swap) char *buf = NULL, *buf1 = NULL; GLint length = 0; + REQUEST_FIXED_SIZE(xGLXSingleReq, 4); + /* If the client has the opposite byte order, swap the contextTag and * the name. */ @@ -343,7 +357,6 @@ DoGetString(__GLXclientState * cl, GLbyte * pc, GLboolean need_swap) pc += __GLX_SINGLE_HDR_SIZE; name = *(GLenum *) (pc + 0); string = (const char *) glGetString(name); - client = cl->client; if (string == NULL) string = ""; diff --git a/glx/single2swap.c b/glx/single2swap.c index 764501f59..53490694b 100644 --- a/glx/single2swap.c +++ b/glx/single2swap.c @@ -41,6 +41,7 @@ int __glXDispSwap_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; GLsizei size; GLenum type; @@ -48,6 +49,8 @@ __glXDispSwap_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc) __GLXcontext *cx; int error; + REQUEST_FIXED_SIZE(xGLXSingleReq, 8); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -77,12 +80,15 @@ __glXDispSwap_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_SelectBuffer(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; __GLXcontext *cx; GLsizei size; __GLX_DECLARE_SWAP_VARIABLES; int error; + REQUEST_FIXED_SIZE(xGLXSingleReq, 4); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -109,7 +115,7 @@ __glXDispSwap_SelectBuffer(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_RenderMode(__GLXclientState * cl, GLbyte * pc) { - ClientPtr client; + ClientPtr client = cl->client; __GLXcontext *cx; xGLXRenderModeReply reply; GLint nitems = 0, retBytes = 0, retval, newModeCheck; @@ -120,6 +126,8 @@ __glXDispSwap_RenderMode(__GLXclientState * cl, GLbyte * pc) __GLX_DECLARE_SWAP_ARRAY_VARIABLES; int error; + REQUEST_FIXED_SIZE(xGLXSingleReq, 4); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -200,7 +208,6 @@ __glXDispSwap_RenderMode(__GLXclientState * cl, GLbyte * pc) ** selection array, as per the API for glRenderMode itself. */ noChangeAllowed:; - client = cl->client; reply = (xGLXRenderModeReply) { .type = X_Reply, .sequenceNumber = client->sequence, @@ -224,11 +231,14 @@ __glXDispSwap_RenderMode(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_Flush(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; __GLXcontext *cx; int error; __GLX_DECLARE_SWAP_VARIABLES; + REQUEST_SIZE_MATCH(xGLXSingleReq); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -243,12 +253,14 @@ __glXDispSwap_Flush(__GLXclientState * cl, GLbyte * pc) int __glXDispSwap_Finish(__GLXclientState * cl, GLbyte * pc) { + ClientPtr client = cl->client; __GLXcontext *cx; - ClientPtr client; int error; __GLX_DECLARE_SWAP_VARIABLES; + REQUEST_SIZE_MATCH(xGLXSingleReq); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -260,7 +272,6 @@ __glXDispSwap_Finish(__GLXclientState * cl, GLbyte * pc) cx->hasUnflushedCommands = GL_FALSE; /* Send empty reply packet to indicate finish is finished */ - client = cl->client; __GLX_BEGIN_REPLY(0); __GLX_PUT_RETVAL(0); __GLX_SWAP_REPLY_HEADER(); diff --git a/glx/singlepix.c b/glx/singlepix.c index 8b6c26187..54ed7fd21 100644 --- a/glx/singlepix.c +++ b/glx/singlepix.c @@ -51,6 +51,8 @@ __glXDisp_ReadPixels(__GLXclientState * cl, GLbyte * pc) int error; char *answer, answerBuffer[200]; + REQUEST_FIXED_SIZE(xGLXSingleReq, 28); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -100,6 +102,8 @@ __glXDisp_GetTexImage(__GLXclientState * cl, GLbyte * pc) char *answer, answerBuffer[200]; GLint width = 0, height = 0, depth = 1; + REQUEST_FIXED_SIZE(xGLXSingleReq, 20); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -157,6 +161,8 @@ __glXDisp_GetPolygonStipple(__GLXclientState * cl, GLbyte * pc) GLubyte answerBuffer[200]; char *answer; + REQUEST_FIXED_SIZE(xGLXSingleReq, 4); + cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { return error; @@ -217,15 +223,13 @@ GetSeparableFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1); compsize2 = __glGetTexImage_size(target, 1, format, type, height, 1, 1); - if (compsize < 0) + if ((compsize = safe_pad(compsize)) < 0) return BadLength; - if (compsize2 < 0) + if ((compsize2 = safe_pad(compsize2)) < 0) return BadLength; - compsize = __GLX_PAD(compsize); - compsize2 = __GLX_PAD(compsize2); glPixelStorei(GL_PACK_SWAP_BYTES, swapBytes); - __GLX_GET_ANSWER_BUFFER(answer, cl, compsize + compsize2, 1); + __GLX_GET_ANSWER_BUFFER(answer, cl, safe_add(compsize, compsize2), 1); __glXClearErrorOccured(); glGetSeparableFilter(*(GLenum *) (pc + 0), *(GLenum *) (pc + 4), *(GLenum *) (pc + 8), answer, answer + compsize, NULL); @@ -249,7 +253,8 @@ int __glXDisp_GetSeparableFilter(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetSeparableFilter(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -257,7 +262,8 @@ int __glXDisp_GetSeparableFilterEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetSeparableFilter(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -323,7 +329,8 @@ int __glXDisp_GetConvolutionFilter(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetConvolutionFilter(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -331,7 +338,8 @@ int __glXDisp_GetConvolutionFilterEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetConvolutionFilter(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -390,7 +398,8 @@ int __glXDisp_GetHistogram(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetHistogram(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -398,7 +407,8 @@ int __glXDisp_GetHistogramEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetHistogram(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -450,7 +460,8 @@ int __glXDisp_GetMinmax(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetMinmax(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -458,7 +469,8 @@ int __glXDisp_GetMinmaxEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetMinmax(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -517,7 +529,8 @@ int __glXDisp_GetColorTable(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetColorTable(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -525,6 +538,7 @@ int __glXDisp_GetColorTableSGI(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); - + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetColorTable(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } diff --git a/glx/singlepixswap.c b/glx/singlepixswap.c index 8dc304fa7..9eff5923d 100644 --- a/glx/singlepixswap.c +++ b/glx/singlepixswap.c @@ -53,6 +53,8 @@ __glXDispSwap_ReadPixels(__GLXclientState * cl, GLbyte * pc) int error; char *answer, answerBuffer[200]; + REQUEST_FIXED_SIZE(xGLXSingleReq, 28); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -114,6 +116,8 @@ __glXDispSwap_GetTexImage(__GLXclientState * cl, GLbyte * pc) char *answer, answerBuffer[200]; GLint width = 0, height = 0, depth = 1; + REQUEST_FIXED_SIZE(xGLXSingleReq, 20); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -184,6 +188,8 @@ __glXDispSwap_GetPolygonStipple(__GLXclientState * cl, GLbyte * pc) __GLX_DECLARE_SWAP_VARIABLES; + REQUEST_FIXED_SIZE(xGLXSingleReq, 4); + __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag); cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error); if (!cx) { @@ -251,15 +257,13 @@ GetSeparableFilter(__GLXclientState * cl, GLbyte * pc, GLXContextTag tag) compsize = __glGetTexImage_size(target, 1, format, type, width, 1, 1); compsize2 = __glGetTexImage_size(target, 1, format, type, height, 1, 1); - if (compsize < 0) + if ((compsize = safe_pad(compsize)) < 0) return BadLength; - if (compsize2 < 0) + if ((compsize2 = safe_pad(compsize2)) < 0) return BadLength; - compsize = __GLX_PAD(compsize); - compsize2 = __GLX_PAD(compsize2); glPixelStorei(GL_PACK_SWAP_BYTES, !swapBytes); - __GLX_GET_ANSWER_BUFFER(answer, cl, compsize + compsize2, 1); + __GLX_GET_ANSWER_BUFFER(answer, cl, safe_add(compsize, compsize2), 1); __glXClearErrorOccured(); glGetSeparableFilter(*(GLenum *) (pc + 0), *(GLenum *) (pc + 4), *(GLenum *) (pc + 8), answer, answer + compsize, NULL); @@ -285,7 +289,9 @@ int __glXDispSwap_GetSeparableFilter(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetSeparableFilter(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -293,7 +299,9 @@ int __glXDispSwap_GetSeparableFilterEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetSeparableFilter(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -367,7 +375,9 @@ int __glXDispSwap_GetConvolutionFilter(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetConvolutionFilter(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -375,7 +385,9 @@ int __glXDispSwap_GetConvolutionFilterEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetConvolutionFilter(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -441,7 +453,9 @@ int __glXDispSwap_GetHistogram(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetHistogram(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -449,7 +463,9 @@ int __glXDispSwap_GetHistogramEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetHistogram(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -507,7 +523,9 @@ int __glXDispSwap_GetMinmax(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetMinmax(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -515,7 +533,9 @@ int __glXDispSwap_GetMinmaxEXT(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetMinmax(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } @@ -581,7 +601,9 @@ int __glXDispSwap_GetColorTable(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_SINGLE_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXSingleReq, 16); return GetColorTable(cl, pc + __GLX_SINGLE_HDR_SIZE, tag); } @@ -589,6 +611,8 @@ int __glXDispSwap_GetColorTableSGI(__GLXclientState * cl, GLbyte * pc) { const GLXContextTag tag = __GLX_GET_VENDPRIV_CONTEXT_TAG(pc); + ClientPtr client = cl->client; + REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 16); return GetColorTable(cl, pc + __GLX_VENDPRIV_HDR_SIZE, tag); } From e883c170c15493ab3637c0a01890f5a7ca4e16a5 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 10 Nov 2014 12:13:48 -0500 Subject: [PATCH 32/37] glx: Pass remaining request length into ->varsize (v2) [CVE-2014-8098 8/8] v2: Handle more multiplies in indirect_reqsize.c (Julien Cristau) Reviewed-by: Julien Cristau Reviewed-by: Michal Srb Reviewed-by: Andy Ritger Signed-off-by: Adam Jackson Signed-off-by: Alan Coopersmith --- glx/glxcmds.c | 7 +- glx/glxserver.h | 2 +- glx/indirect_reqsize.c | 142 ++++++++++++++++---------------- glx/indirect_reqsize.h | 181 +++++++++++++++++++++++++---------------- glx/rensize.c | 27 ++++-- 5 files changed, 205 insertions(+), 154 deletions(-) diff --git a/glx/glxcmds.c b/glx/glxcmds.c index a7a517293..bd6cb8dc0 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -2067,7 +2067,8 @@ __glXDisp_Render(__GLXclientState * cl, GLbyte * pc) if (entry.varsize) { /* variable size command */ extra = (*entry.varsize) (pc + __GLX_RENDER_HDR_SIZE, - client->swapped); + client->swapped, + left - __GLX_RENDER_HDR_SIZE); if (extra < 0) { return BadLength; } @@ -2144,6 +2145,7 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) if (cl->largeCmdRequestsSoFar == 0) { __GLXrenderSizeData entry; int extra = 0; + int left = (req->length << 2) - sz_xGLXRenderLargeReq; size_t cmdlen; int err; @@ -2184,7 +2186,8 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) ** will be in the 1st request, so it's okay to do this. */ extra = (*entry.varsize) (pc + __GLX_RENDER_LARGE_HDR_SIZE, - client->swapped); + client->swapped, + left - __GLX_RENDER_LARGE_HDR_SIZE); if (extra < 0) { return BadLength; } diff --git a/glx/glxserver.h b/glx/glxserver.h index 948260149..9088ec478 100644 --- a/glx/glxserver.h +++ b/glx/glxserver.h @@ -177,7 +177,7 @@ typedef int (*__GLXprocPtr) (__GLXclientState *, char *pc); /* * Tables for computing the size of each rendering command. */ -typedef int (*gl_proto_size_func) (const GLbyte *, Bool); +typedef int (*gl_proto_size_func) (const GLbyte *, Bool, int); typedef struct { int bytes; diff --git a/glx/indirect_reqsize.c b/glx/indirect_reqsize.c index abd076604..020aae2fe 100644 --- a/glx/indirect_reqsize.c +++ b/glx/indirect_reqsize.c @@ -31,24 +31,22 @@ #include "indirect_size.h" #include "indirect_reqsize.h" -#define __GLX_PAD(x) (((x) + 3) & ~3) - #if defined(__CYGWIN__) || defined(__MINGW32__) #undef HAVE_ALIAS #endif #ifdef HAVE_ALIAS #define ALIAS2(from,to) \ - GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \ + GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap, int reqlen ) \ __attribute__ ((alias( # to ))); #define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize ) #else #define ALIAS(from,to) \ - GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \ - { return __glX ## to ## ReqSize( pc, swap ); } + GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap, int reqlen ) \ + { return __glX ## to ## ReqSize( pc, swap, reqlen ); } #endif int -__glXCallListsReqSize(const GLbyte * pc, Bool swap) +__glXCallListsReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 0); GLenum type = *(GLenum *) (pc + 4); @@ -60,11 +58,11 @@ __glXCallListsReqSize(const GLbyte * pc, Bool swap) } compsize = __glCallLists_size(type); - return __GLX_PAD((compsize * n)); + return safe_pad(safe_mul(compsize, n)); } int -__glXBitmapReqSize(const GLbyte * pc, Bool swap) +__glXBitmapReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -88,7 +86,7 @@ __glXBitmapReqSize(const GLbyte * pc, Bool swap) } int -__glXFogfvReqSize(const GLbyte * pc, Bool swap) +__glXFogfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 0); GLsizei compsize; @@ -98,11 +96,11 @@ __glXFogfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glFogfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXLightfvReqSize(const GLbyte * pc, Bool swap) +__glXLightfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -112,11 +110,11 @@ __glXLightfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glLightfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXLightModelfvReqSize(const GLbyte * pc, Bool swap) +__glXLightModelfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 0); GLsizei compsize; @@ -126,11 +124,11 @@ __glXLightModelfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glLightModelfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXMaterialfvReqSize(const GLbyte * pc, Bool swap) +__glXMaterialfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -140,11 +138,11 @@ __glXMaterialfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glMaterialfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXPolygonStippleReqSize(const GLbyte * pc, Bool swap) +__glXPolygonStippleReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -164,7 +162,7 @@ __glXPolygonStippleReqSize(const GLbyte * pc, Bool swap) } int -__glXTexParameterfvReqSize(const GLbyte * pc, Bool swap) +__glXTexParameterfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -174,11 +172,11 @@ __glXTexParameterfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glTexParameterfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXTexImage1DReqSize(const GLbyte * pc, Bool swap) +__glXTexImage1DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -206,7 +204,7 @@ __glXTexImage1DReqSize(const GLbyte * pc, Bool swap) } int -__glXTexImage2DReqSize(const GLbyte * pc, Bool swap) +__glXTexImage2DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -236,7 +234,7 @@ __glXTexImage2DReqSize(const GLbyte * pc, Bool swap) } int -__glXTexEnvfvReqSize(const GLbyte * pc, Bool swap) +__glXTexEnvfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -246,11 +244,11 @@ __glXTexEnvfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glTexEnvfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXTexGendvReqSize(const GLbyte * pc, Bool swap) +__glXTexGendvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -260,11 +258,11 @@ __glXTexGendvReqSize(const GLbyte * pc, Bool swap) } compsize = __glTexGendv_size(pname); - return __GLX_PAD((compsize * 8)); + return safe_pad(safe_mul(compsize, 8)); } int -__glXTexGenfvReqSize(const GLbyte * pc, Bool swap) +__glXTexGenfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -274,11 +272,11 @@ __glXTexGenfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glTexGenfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXPixelMapfvReqSize(const GLbyte * pc, Bool swap) +__glXPixelMapfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei mapsize = *(GLsizei *) (pc + 4); @@ -286,11 +284,11 @@ __glXPixelMapfvReqSize(const GLbyte * pc, Bool swap) mapsize = bswap_32(mapsize); } - return __GLX_PAD((mapsize * 4)); + return safe_pad(safe_mul(mapsize, 4)); } int -__glXPixelMapusvReqSize(const GLbyte * pc, Bool swap) +__glXPixelMapusvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei mapsize = *(GLsizei *) (pc + 4); @@ -298,11 +296,11 @@ __glXPixelMapusvReqSize(const GLbyte * pc, Bool swap) mapsize = bswap_32(mapsize); } - return __GLX_PAD((mapsize * 2)); + return safe_pad(safe_mul(mapsize, 2)); } int -__glXDrawPixelsReqSize(const GLbyte * pc, Bool swap) +__glXDrawPixelsReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -330,7 +328,7 @@ __glXDrawPixelsReqSize(const GLbyte * pc, Bool swap) } int -__glXPrioritizeTexturesReqSize(const GLbyte * pc, Bool swap) +__glXPrioritizeTexturesReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 0); @@ -338,11 +336,11 @@ __glXPrioritizeTexturesReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 4) + (n * 4)); + return safe_pad(safe_add(safe_mul(n, 4), safe_mul(n, 4))); } int -__glXTexSubImage1DReqSize(const GLbyte * pc, Bool swap) +__glXTexSubImage1DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -370,7 +368,7 @@ __glXTexSubImage1DReqSize(const GLbyte * pc, Bool swap) } int -__glXTexSubImage2DReqSize(const GLbyte * pc, Bool swap) +__glXTexSubImage2DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -400,7 +398,7 @@ __glXTexSubImage2DReqSize(const GLbyte * pc, Bool swap) } int -__glXColorTableReqSize(const GLbyte * pc, Bool swap) +__glXColorTableReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -428,7 +426,7 @@ __glXColorTableReqSize(const GLbyte * pc, Bool swap) } int -__glXColorTableParameterfvReqSize(const GLbyte * pc, Bool swap) +__glXColorTableParameterfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -438,11 +436,11 @@ __glXColorTableParameterfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glColorTableParameterfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXColorSubTableReqSize(const GLbyte * pc, Bool swap) +__glXColorSubTableReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -470,7 +468,7 @@ __glXColorSubTableReqSize(const GLbyte * pc, Bool swap) } int -__glXConvolutionFilter1DReqSize(const GLbyte * pc, Bool swap) +__glXConvolutionFilter1DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -498,7 +496,7 @@ __glXConvolutionFilter1DReqSize(const GLbyte * pc, Bool swap) } int -__glXConvolutionFilter2DReqSize(const GLbyte * pc, Bool swap) +__glXConvolutionFilter2DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = 0; @@ -528,7 +526,7 @@ __glXConvolutionFilter2DReqSize(const GLbyte * pc, Bool swap) } int -__glXConvolutionParameterfvReqSize(const GLbyte * pc, Bool swap) +__glXConvolutionParameterfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 4); GLsizei compsize; @@ -538,11 +536,11 @@ __glXConvolutionParameterfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glConvolutionParameterfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXTexImage3DReqSize(const GLbyte * pc, Bool swap) +__glXTexImage3DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = *(GLint *) (pc + 8); @@ -579,7 +577,7 @@ __glXTexImage3DReqSize(const GLbyte * pc, Bool swap) } int -__glXTexSubImage3DReqSize(const GLbyte * pc, Bool swap) +__glXTexSubImage3DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLint row_length = *(GLint *) (pc + 4); GLint image_height = *(GLint *) (pc + 8); @@ -613,7 +611,7 @@ __glXTexSubImage3DReqSize(const GLbyte * pc, Bool swap) } int -__glXCompressedTexImage1DReqSize(const GLbyte * pc, Bool swap) +__glXCompressedTexImage1DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei imageSize = *(GLsizei *) (pc + 20); @@ -621,11 +619,11 @@ __glXCompressedTexImage1DReqSize(const GLbyte * pc, Bool swap) imageSize = bswap_32(imageSize); } - return __GLX_PAD(imageSize); + return safe_pad(imageSize); } int -__glXCompressedTexImage2DReqSize(const GLbyte * pc, Bool swap) +__glXCompressedTexImage2DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei imageSize = *(GLsizei *) (pc + 24); @@ -633,11 +631,11 @@ __glXCompressedTexImage2DReqSize(const GLbyte * pc, Bool swap) imageSize = bswap_32(imageSize); } - return __GLX_PAD(imageSize); + return safe_pad(imageSize); } int -__glXCompressedTexImage3DReqSize(const GLbyte * pc, Bool swap) +__glXCompressedTexImage3DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei imageSize = *(GLsizei *) (pc + 28); @@ -645,11 +643,11 @@ __glXCompressedTexImage3DReqSize(const GLbyte * pc, Bool swap) imageSize = bswap_32(imageSize); } - return __GLX_PAD(imageSize); + return safe_pad(imageSize); } int -__glXCompressedTexSubImage3DReqSize(const GLbyte * pc, Bool swap) +__glXCompressedTexSubImage3DReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei imageSize = *(GLsizei *) (pc + 36); @@ -657,11 +655,11 @@ __glXCompressedTexSubImage3DReqSize(const GLbyte * pc, Bool swap) imageSize = bswap_32(imageSize); } - return __GLX_PAD(imageSize); + return safe_pad(imageSize); } int -__glXPointParameterfvReqSize(const GLbyte * pc, Bool swap) +__glXPointParameterfvReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum pname = *(GLenum *) (pc + 0); GLsizei compsize; @@ -671,11 +669,11 @@ __glXPointParameterfvReqSize(const GLbyte * pc, Bool swap) } compsize = __glPointParameterfv_size(pname); - return __GLX_PAD((compsize * 4)); + return safe_pad(safe_mul(compsize, 4)); } int -__glXDrawBuffersReqSize(const GLbyte * pc, Bool swap) +__glXDrawBuffersReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 0); @@ -683,11 +681,11 @@ __glXDrawBuffersReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 4)); + return safe_pad(safe_mul(n, 4)); } int -__glXProgramStringARBReqSize(const GLbyte * pc, Bool swap) +__glXProgramStringARBReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei len = *(GLsizei *) (pc + 8); @@ -695,11 +693,11 @@ __glXProgramStringARBReqSize(const GLbyte * pc, Bool swap) len = bswap_32(len); } - return __GLX_PAD(len); + return safe_pad(len); } int -__glXVertexAttribs1dvNVReqSize(const GLbyte * pc, Bool swap) +__glXVertexAttribs1dvNVReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 4); @@ -707,11 +705,11 @@ __glXVertexAttribs1dvNVReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 8)); + return safe_pad(safe_mul(n, 8)); } int -__glXVertexAttribs2dvNVReqSize(const GLbyte * pc, Bool swap) +__glXVertexAttribs2dvNVReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 4); @@ -719,11 +717,11 @@ __glXVertexAttribs2dvNVReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 16)); + return safe_pad(safe_mul(n, 16)); } int -__glXVertexAttribs3dvNVReqSize(const GLbyte * pc, Bool swap) +__glXVertexAttribs3dvNVReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 4); @@ -731,11 +729,11 @@ __glXVertexAttribs3dvNVReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 24)); + return safe_pad(safe_mul(n, 24)); } int -__glXVertexAttribs3fvNVReqSize(const GLbyte * pc, Bool swap) +__glXVertexAttribs3fvNVReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 4); @@ -743,11 +741,11 @@ __glXVertexAttribs3fvNVReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 12)); + return safe_pad(safe_mul(n, 12)); } int -__glXVertexAttribs3svNVReqSize(const GLbyte * pc, Bool swap) +__glXVertexAttribs3svNVReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 4); @@ -755,11 +753,11 @@ __glXVertexAttribs3svNVReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 6)); + return safe_pad(safe_mul(n, 6)); } int -__glXVertexAttribs4dvNVReqSize(const GLbyte * pc, Bool swap) +__glXVertexAttribs4dvNVReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLsizei n = *(GLsizei *) (pc + 4); @@ -767,7 +765,7 @@ __glXVertexAttribs4dvNVReqSize(const GLbyte * pc, Bool swap) n = bswap_32(n); } - return __GLX_PAD((n * 32)); + return safe_pad(safe_mul(n, 32)); } ALIAS(Fogiv, Fogfv) diff --git a/glx/indirect_reqsize.h b/glx/indirect_reqsize.h index 49d400c45..632a85b1c 100644 --- a/glx/indirect_reqsize.h +++ b/glx/indirect_reqsize.h @@ -36,115 +36,156 @@ #define PURE #endif -extern PURE _X_HIDDEN int __glXCallListsReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXBitmapReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXFogfvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXFogivReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXLightfvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXLightivReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXLightModelfvReqSize(const GLbyte * pc, - Bool swap); -extern PURE _X_HIDDEN int __glXLightModelivReqSize(const GLbyte * pc, - Bool swap); -extern PURE _X_HIDDEN int __glXMaterialfvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXMaterialivReqSize(const GLbyte * pc, Bool swap); +extern PURE _X_HIDDEN int __glXCallListsReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXBitmapReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXFogfvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXFogivReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXLightfvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXLightivReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXLightModelfvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXLightModelivReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXMaterialfvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXMaterialivReqSize(const GLbyte * pc, Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXPolygonStippleReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXTexParameterfvReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXTexParameterivReqSize(const GLbyte * pc, - Bool swap); -extern PURE _X_HIDDEN int __glXTexImage1DReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXTexImage2DReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXTexEnvfvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXTexEnvivReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXTexGendvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXTexGenfvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXTexGenivReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXMap1dReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXMap1fReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXMap2dReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXMap2fReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXPixelMapfvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXPixelMapuivReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXPixelMapusvReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXDrawPixelsReqSize(const GLbyte * pc, Bool swap); -extern PURE _X_HIDDEN int __glXDrawArraysReqSize(const GLbyte * pc, Bool swap); + Bool swap, int reqlen); +extern PURE _X_HIDDEN int __glXTexImage1DReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXTexImage2DReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXTexEnvfvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXTexEnvivReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXTexGendvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXTexGenfvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXTexGenivReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXMap1dReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXMap1fReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXMap2dReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXMap2fReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXPixelMapfvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXPixelMapuivReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXPixelMapusvReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXDrawPixelsReqSize(const GLbyte * pc, Bool swap, + int reqlen); +extern PURE _X_HIDDEN int __glXDrawArraysReqSize(const GLbyte * pc, Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXPrioritizeTexturesReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXTexSubImage1DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXTexSubImage2DReqSize(const GLbyte * pc, - Bool swap); -extern PURE _X_HIDDEN int __glXColorTableReqSize(const GLbyte * pc, Bool swap); + Bool swap, int reqlen); +extern PURE _X_HIDDEN int __glXColorTableReqSize(const GLbyte * pc, Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXColorTableParameterfvReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXColorTableParameterivReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXColorSubTableReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXConvolutionFilter1DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXConvolutionFilter2DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXConvolutionParameterfvReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXConvolutionParameterivReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXSeparableFilter2DReqSize(const GLbyte * pc, - Bool swap); -extern PURE _X_HIDDEN int __glXTexImage3DReqSize(const GLbyte * pc, Bool swap); + Bool swap, int reqlen); +extern PURE _X_HIDDEN int __glXTexImage3DReqSize(const GLbyte * pc, Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXTexSubImage3DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXCompressedTexImage1DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXCompressedTexImage2DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXCompressedTexImage3DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXCompressedTexSubImage1DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXCompressedTexSubImage2DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXCompressedTexSubImage3DReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXPointParameterfvReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXPointParameterivReqSize(const GLbyte * pc, - Bool swap); -extern PURE _X_HIDDEN int __glXDrawBuffersReqSize(const GLbyte * pc, Bool swap); + Bool swap, int reqlen); +extern PURE _X_HIDDEN int __glXDrawBuffersReqSize(const GLbyte * pc, Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXProgramStringARBReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXDeleteFramebuffersReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXDeleteRenderbuffersReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs1dvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs1fvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs1svNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs2dvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs2fvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs2svNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs3dvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs3fvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs3svNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs4dvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs4fvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs4svNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, int reqlen); extern PURE _X_HIDDEN int __glXVertexAttribs4ubvNVReqSize(const GLbyte * pc, - Bool swap); + Bool swap, + int reqlen); #undef PURE diff --git a/glx/rensize.c b/glx/rensize.c index d46334a71..6bfe99b2a 100644 --- a/glx/rensize.c +++ b/glx/rensize.c @@ -44,7 +44,7 @@ ((a & 0xff00U)<<8) | ((a & 0xffU)<<24)) int -__glXMap1dReqSize(const GLbyte * pc, Bool swap) +__glXMap1dReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum target; GLint order; @@ -61,7 +61,7 @@ __glXMap1dReqSize(const GLbyte * pc, Bool swap) } int -__glXMap1fReqSize(const GLbyte * pc, Bool swap) +__glXMap1fReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum target; GLint order; @@ -86,7 +86,7 @@ Map2Size(int k, int majorOrder, int minorOrder) } int -__glXMap2dReqSize(const GLbyte * pc, Bool swap) +__glXMap2dReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum target; GLint uorder, vorder; @@ -103,7 +103,7 @@ __glXMap2dReqSize(const GLbyte * pc, Bool swap) } int -__glXMap2fReqSize(const GLbyte * pc, Bool swap) +__glXMap2fReqSize(const GLbyte * pc, Bool swap, int reqlen) { GLenum target; GLint uorder, vorder; @@ -359,13 +359,14 @@ __glXTypeSize(GLenum enm) } int -__glXDrawArraysReqSize(const GLbyte * pc, Bool swap) +__glXDrawArraysReqSize(const GLbyte * pc, Bool swap, int reqlen) { __GLXdispatchDrawArraysHeader *hdr = (__GLXdispatchDrawArraysHeader *) pc; __GLXdispatchDrawArraysComponentHeader *compHeader; GLint numVertexes = hdr->numVertexes; GLint numComponents = hdr->numComponents; GLint arrayElementSize = 0; + GLint x, size; int i; if (swap) { @@ -374,6 +375,13 @@ __glXDrawArraysReqSize(const GLbyte * pc, Bool swap) } pc += sizeof(__GLXdispatchDrawArraysHeader); + reqlen -= sizeof(__GLXdispatchDrawArraysHeader); + + size = safe_mul(sizeof(__GLXdispatchDrawArraysComponentHeader), + numComponents); + if (size < 0 || reqlen < 0 || reqlen < size) + return -1; + compHeader = (__GLXdispatchDrawArraysComponentHeader *) pc; for (i = 0; i < numComponents; i++) { @@ -417,17 +425,18 @@ __glXDrawArraysReqSize(const GLbyte * pc, Bool swap) return -1; } - arrayElementSize += __GLX_PAD(numVals * __glXTypeSize(datatype)); + x = safe_pad(safe_mul(numVals, __glXTypeSize(datatype))); + if ((arrayElementSize = safe_add(arrayElementSize, x)) < 0) + return -1; pc += sizeof(__GLXdispatchDrawArraysComponentHeader); } - return ((numComponents * sizeof(__GLXdispatchDrawArraysComponentHeader)) + - (numVertexes * arrayElementSize)); + return safe_add(size, safe_mul(numVertexes, arrayElementSize)); } int -__glXSeparableFilter2DReqSize(const GLbyte * pc, Bool swap) +__glXSeparableFilter2DReqSize(const GLbyte * pc, Bool swap, int reqlen) { __GLXdispatchConvolutionFilterHeader *hdr = (__GLXdispatchConvolutionFilterHeader *) pc; From 7e7630bbb775573eea2a2335adb9d190c3e1e971 Mon Sep 17 00:00:00 2001 From: Robert Morell Date: Wed, 12 Nov 2014 18:51:43 -0800 Subject: [PATCH 33/37] glx: Fix mask truncation in __glXGetAnswerBuffer [CVE-2014-8093 6/6] On a system where sizeof(unsigned) != sizeof(intptr_t), the unary bitwise not operation will result in a mask that clears all high bits from temp_buf in the expression: temp_buf = (temp_buf + mask) & ~mask; Signed-off-by: Robert Morell Reviewed-by: Alan Coopersmith Signed-off-by: Alan Coopersmith --- glx/indirect_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glx/indirect_util.c b/glx/indirect_util.c index de8149127..9ba28157c 100644 --- a/glx/indirect_util.c +++ b/glx/indirect_util.c @@ -73,7 +73,7 @@ __glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size, void *local_buffer, size_t local_size, unsigned alignment) { void *buffer = local_buffer; - const unsigned mask = alignment - 1; + const intptr_t mask = alignment - 1; if (local_size < required_size) { size_t worst_case_size; From b20912c3d45cbbde3c443e6c3d9e189092fe65e1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Dec 2014 09:30:57 -0800 Subject: [PATCH 34/37] dbe: Call to DDX SwapBuffers requires address of int, not unsigned int [CVE-2014-8097 pt. 2] When the local types used to walk the DBE request were changed, this changed the type of the parameter passed to the DDX SwapBuffers API, but there wasn't a matching change in the API definition. At this point, with the API frozen, I just stuck a new variable in with the correct type. Because we've already bounds-checked nStuff to be smaller than UINT32_MAX / sizeof(DbeSwapInfoRec), we know it will fit in a signed int without overflow. Signed-off-by: Keith Packard Signed-off-by: Alan Coopersmith --- dbe/dbe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dbe/dbe.c b/dbe/dbe.c index df2ad5c51..e5d928d7b 100644 --- a/dbe/dbe.c +++ b/dbe/dbe.c @@ -452,6 +452,7 @@ ProcDbeSwapBuffers(ClientPtr client) int error; unsigned int i, j; unsigned int nStuff; + int nStuff_i; /* DDX API requires int for nStuff */ REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); nStuff = stuff->n; /* use local variable for performance. */ @@ -527,9 +528,10 @@ ProcDbeSwapBuffers(ClientPtr client) * could deal with cross-screen synchronization. */ - while (nStuff > 0) { + nStuff_i = nStuff; + while (nStuff_i > 0) { pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow); - error = (*pDbeScreenPriv->SwapBuffers) (client, &nStuff, swapInfo); + error = (*pDbeScreenPriv->SwapBuffers) (client, &nStuff_i, swapInfo); if (error != Success) { free(swapInfo); return error; From 61b17c0f10307e25e51e30e6fb1d3e3127f82d86 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Dec 2014 09:30:58 -0800 Subject: [PATCH 35/37] glx: Can't mix declarations and code in X.org sources [CVE-2014-8098 pt. 9] We're using compiler compatibility settings which generate warnings when a variable is declared after the first statement. Signed-off-by: Keith Packard Reviewed-by: Alan Coopersmith Signed-off-by: Alan Coopersmith --- glx/clientinfo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glx/clientinfo.c b/glx/clientinfo.c index c5fef3074..74ad91991 100644 --- a/glx/clientinfo.c +++ b/glx/clientinfo.c @@ -36,13 +36,14 @@ set_client_info(__GLXclientState * cl, xGLXSetClientInfoARBReq * req, ClientPtr client = cl->client; char *gl_extensions; char *glx_extensions; + int size; REQUEST_AT_LEAST_SIZE(xGLXSetClientInfoARBReq); /* Verify that the size of the packet matches the size inferred from the * sizes specified for the various fields. */ - int size = sz_xGLXSetClientInfoARBReq; + size = sz_xGLXSetClientInfoARBReq; size = safe_add(size, safe_mul(req->numVersions, bytes_per_version)); size = safe_add(size, safe_pad(req->numGLExtensionBytes)); size = safe_add(size, safe_pad(req->numGLXExtensionBytes)); From 9802a0162f738de03585ca3f3b8a8266494f7d45 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Dec 2014 09:30:59 -0800 Subject: [PATCH 36/37] Missing parens in REQUEST_FIXED_SIZE macro [CVE-2014-8092 pt. 5] The 'n' parameter must be surrounded by parens in both places to prevent precedence from mis-computing things. Signed-off-by: Keith Packard Reviewed-by: Alan Coopersmith Signed-off-by: Alan Coopersmith --- include/dix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dix.h b/include/dix.h index 21176a8c3..921156b4c 100644 --- a/include/dix.h +++ b/include/dix.h @@ -80,7 +80,7 @@ SOFTWARE. #define REQUEST_FIXED_SIZE(req, n)\ if (((sizeof(req) >> 2) > client->req_len) || \ - ((n >> 2) >= client->req_len) || \ + (((n) >> 2) >= client->req_len) || \ ((((uint64_t) sizeof(req) + (n) + 3) >> 2) != (uint64_t) client->req_len)) \ return(BadLength) From 1559a94395258fd73e369f1a2c98a44bfe21a486 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Dec 2014 09:31:00 -0800 Subject: [PATCH 37/37] dix: GetHosts bounds check using wrong pointer value [CVE-2014-8092 pt. 6] GetHosts saves the pointer to allocated memory in *data, and then wants to bounds-check writes to that region, but was mistakenly using a bare 'data' instead of '*data'. Also, data is declared as void **, so we need a cast to turn it into a byte pointer so we can actually do pointer comparisons. Signed-off-by: Keith Packard Reviewed-by: Alan Coopersmith Signed-off-by: Alan Coopersmith --- os/access.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/access.c b/os/access.c index f393c8d54..28f2d3213 100644 --- a/os/access.c +++ b/os/access.c @@ -1308,7 +1308,7 @@ GetHosts(void **data, int *pnHosts, int *pLen, BOOL * pEnabled) } for (host = validhosts; host; host = host->next) { len = host->len; - if ((ptr + sizeof(xHostEntry) + len) > (data + n)) + if ((ptr + sizeof(xHostEntry) + len) > ((unsigned char *) *data + n)) break; ((xHostEntry *) ptr)->family = host->family; ((xHostEntry *) ptr)->length = len;