X-Git-Url: https://git.piment-noir.org/?p=deb_xorg-server.git;a=blobdiff_plain;f=debian%2Fpatches%2FCVE-2014-8xxx%2F0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch;fp=debian%2Fpatches%2FCVE-2014-8xxx%2F0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch;h=421f07084b741738027d4ccd3bab5a10758f41bf;hp=0000000000000000000000000000000000000000;hb=7217e0ca50bba73dad94782e67980aeeb24ab693;hpb=a09e091a5c996d46a398abb27b06fe504591673f diff --git a/debian/patches/CVE-2014-8xxx/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch b/debian/patches/CVE-2014-8xxx/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch new file mode 100644 index 0000000..421f070 --- /dev/null +++ b/debian/patches/CVE-2014-8xxx/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch @@ -0,0 +1,551 @@ +From 54fa1f815507cd27280f661be7a64f2f2e6c579e Mon Sep 17 00:00:00 2001 +From: Alan Coopersmith +Date: Sun, 26 Jan 2014 10:54:41 -0800 +Subject: [PATCH 08/33] 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 d078aa2..b3ee867 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 6dcf60c..224c2ba 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 3c21386..183f88d 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 ebef233..ca263ef 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 7a1bb7a..8e6255b 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 9e36354..2732445 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 3c90d58..306dd39 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 63d95bc..e2a2ae3 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 700622d..9241ffd 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 463607d..8e8e4b0 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 4e544f0..67a9a4f 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 e9bdd42..7ec0c85 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 45a996e..168579f 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 38ff51e..24d4a53 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 372ec24..96a9a16 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 3f051f7..780758a 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 e0c6ed8..21176a8 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) || \ +-- +1.7.9.2 +