Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Maintenance:3335
xorg-x11-server.openSUSE_12.3_Update
U_Xi_unvalidated_lengths_in_Xinput_extension.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File U_Xi_unvalidated_lengths_in_Xinput_extension.patch of Package xorg-x11-server.openSUSE_12.3_Update
Subject: Xi: unvalidated lengths in Xinput extension References: bnc#907268, CVE-2014-8095 Patch-Mainline: Upstream Signed-off-by: Michal Srb <msrb@suse.com> 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 <alan.coopersmith@oracle.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> --- 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(-) Index: xorg-server-1.13.2/Xi/chgdctl.c =================================================================== --- xorg-server-1.13.2.orig/Xi/chgdctl.c +++ xorg-server-1.13.2/Xi/chgdctl.c @@ -78,7 +78,7 @@ SProcXChangeDeviceControl(ClientPtr clie 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 clien 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); @@ -185,6 +185,10 @@ ProcXChangeDeviceControl(ClientPtr clien break; case DEVICE_ENABLE: e = (xDeviceEnableCtl *) &stuff[1]; + if ((len != bytes_to_int32(sizeof(xDeviceEnableCtl)))) { + ret = BadLength; + goto out; + } status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e); Index: xorg-server-1.13.2/Xi/chgfctl.c =================================================================== --- xorg-server-1.13.2.orig/Xi/chgfctl.c +++ xorg-server-1.13.2/Xi/chgfctl.c @@ -467,6 +467,8 @@ ProcXChangeFeedbackControl(ClientPtr cli xStringFeedbackCtl *f = ((xStringFeedbackCtl *) &stuff[1]); if (client->swapped) { + if (len < bytes_to_int32(sizeof(xStringFeedbackCtl))) + return BadLength; swaps(&f->num_keysyms); } if (len != Index: xorg-server-1.13.2/Xi/sendexev.c =================================================================== --- xorg-server-1.13.2.orig/Xi/sendexev.c +++ xorg-server-1.13.2/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]); Index: xorg-server-1.13.2/Xi/xiallowev.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xiallowev.c +++ xorg-server-1.13.2/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); } Index: xorg-server-1.13.2/Xi/xichangecursor.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xichangecursor.c +++ xorg-server-1.13.2/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)); } Index: xorg-server-1.13.2/Xi/xichangehierarchy.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xichangehierarchy.c +++ xorg-server-1.13.2/Xi/xichangehierarchy.c @@ -401,7 +401,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 }; @@ -411,21 +411,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) @@ -436,6 +461,7 @@ ProcXIChangeHierarchy(ClientPtr client) { xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; + CHANGE_SIZE_MATCH(xXIRemoveMasterInfo); rc = remove_master(client, r, flags); if (rc != Success) goto unwind; @@ -445,6 +471,7 @@ ProcXIChangeHierarchy(ClientPtr client) { xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; + CHANGE_SIZE_MATCH(xXIDetachSlaveInfo); rc = detach_slave(client, c, flags); if (rc != Success) goto unwind; @@ -454,6 +481,7 @@ ProcXIChangeHierarchy(ClientPtr client) { xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; + CHANGE_SIZE_MATCH(xXIAttachSlaveInfo); rc = attach_slave(client, c, flags); if (rc != Success) goto unwind; @@ -461,6 +489,7 @@ ProcXIChangeHierarchy(ClientPtr client) break; } + len -= any->length * 4; any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); } Index: xorg-server-1.13.2/Xi/xigetclientpointer.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xigetclientpointer.c +++ xorg-server-1.13.2/Xi/xigetclientpointer.c @@ -50,6 +50,7 @@ int SProcXIGetClientPointer(ClientPtr client) { REQUEST(xXIGetClientPointerReq); + REQUEST_SIZE_MATCH(xXIGetClientPointerReq); swaps(&stuff->length); swapl(&stuff->win); Index: xorg-server-1.13.2/Xi/xigrabdev.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xigrabdev.c +++ xorg-server-1.13.2/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); @@ -69,7 +74,7 @@ ProcXIGrabDevice(ClientPtr client) int mask_len; 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) @@ -120,6 +125,7 @@ int SProcXIUngrabDevice(ClientPtr client) { REQUEST(xXIUngrabDeviceReq); + REQUEST_SIZE_MATCH(xXIUngrabDeviceReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -137,6 +143,7 @@ ProcXIUngrabDevice(ClientPtr client) TimeStamp time; REQUEST(xXIUngrabDeviceReq); + REQUEST_SIZE_MATCH(xXIUngrabDeviceReq); ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); if (ret != Success) Index: xorg-server-1.13.2/Xi/xipassivegrab.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xipassivegrab.c +++ xorg-server-1.13.2/Xi/xipassivegrab.c @@ -53,6 +53,7 @@ SProcXIPassiveGrabDevice(ClientPtr clien uint32_t *mods; REQUEST(xXIPassiveGrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -63,6 +64,8 @@ SProcXIPassiveGrabDevice(ClientPtr clien 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; @@ -248,6 +252,7 @@ SProcXIPassiveUngrabDevice(ClientPtr cli uint32_t *modifiers; REQUEST(xXIPassiveUngrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); swaps(&stuff->length); swapl(&stuff->grab_window); @@ -255,6 +260,8 @@ SProcXIPassiveUngrabDevice(ClientPtr cli 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++) @@ -273,7 +280,8 @@ ProcXIPassiveUngrabDevice(ClientPtr clie 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; Index: xorg-server-1.13.2/Xi/xiproperty.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xiproperty.c +++ xorg-server-1.13.2/Xi/xiproperty.c @@ -1010,10 +1010,9 @@ int SProcXListDeviceProperties(ClientPtr client) { REQUEST(xListDevicePropertiesReq); + REQUEST_SIZE_MATCH(xListDevicePropertiesReq); swaps(&stuff->length); - - REQUEST_SIZE_MATCH(xListDevicePropertiesReq); return (ProcXListDeviceProperties(client)); } @@ -1034,10 +1033,10 @@ int SProcXDeleteDeviceProperty(ClientPtr client) { REQUEST(xDeleteDevicePropertyReq); + REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); swaps(&stuff->length); swapl(&stuff->property); - REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); return (ProcXDeleteDeviceProperty(client)); } @@ -1045,13 +1044,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)); } @@ -1250,11 +1249,10 @@ int SProcXIListProperties(ClientPtr client) { REQUEST(xXIListPropertiesReq); + REQUEST_SIZE_MATCH(xXIListPropertiesReq); swaps(&stuff->length); swaps(&stuff->deviceid); - - REQUEST_SIZE_MATCH(xXIListPropertiesReq); return (ProcXIListProperties(client)); } @@ -1276,11 +1274,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)); } @@ -1288,6 +1286,7 @@ int SProcXIGetProperty(ClientPtr client) { REQUEST(xXIGetPropertyReq); + REQUEST_SIZE_MATCH(xXIGetPropertyReq); swaps(&stuff->length); swaps(&stuff->deviceid); @@ -1295,7 +1294,6 @@ SProcXIGetProperty(ClientPtr client) swapl(&stuff->type); swapl(&stuff->offset); swapl(&stuff->len); - REQUEST_SIZE_MATCH(xXIGetPropertyReq); return (ProcXIGetProperty(client)); } Index: xorg-server-1.13.2/Xi/xiquerydevice.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xiquerydevice.c +++ xorg-server-1.13.2/Xi/xiquerydevice.c @@ -54,6 +54,7 @@ int SProcXIQueryDevice(ClientPtr client) { REQUEST(xXIQueryDeviceReq); + REQUEST_SIZE_MATCH(xXIQueryDeviceReq); swaps(&stuff->length); swaps(&stuff->deviceid); Index: xorg-server-1.13.2/Xi/xiquerypointer.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xiquerypointer.c +++ xorg-server-1.13.2/Xi/xiquerypointer.c @@ -62,6 +62,8 @@ int SProcXIQueryPointer(ClientPtr client) { REQUEST(xXIQueryPointerReq); + REQUEST_SIZE_MATCH(xXIQueryPointerReq); + swaps(&stuff->length); swaps(&stuff->deviceid); swapl(&stuff->win); Index: xorg-server-1.13.2/Xi/xiselectev.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xiselectev.c +++ xorg-server-1.13.2/Xi/xiselectev.c @@ -63,6 +63,7 @@ int SProcXISelectEvents(ClientPtr client) { int i; + int len; xXIEventMask *evmask; REQUEST(xXISelectEventsReq); @@ -71,10 +72,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); } Index: xorg-server-1.13.2/Xi/xisetclientpointer.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xisetclientpointer.c +++ xorg-server-1.13.2/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)); } Index: xorg-server-1.13.2/Xi/xisetdevfocus.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xisetdevfocus.c +++ xorg-server-1.13.2/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); Index: xorg-server-1.13.2/Xi/xiwarppointer.c =================================================================== --- xorg-server-1.13.2.orig/Xi/xiwarppointer.c +++ xorg-server-1.13.2/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); Index: xorg-server-1.13.2/include/dix.h =================================================================== --- xorg-server-1.13.2.orig/include/dix.h +++ xorg-server-1.13.2/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) || \
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor