Blame SOURCES/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch

0fd959
From 757fe009c45278807d6951d6380292de9133f0f8 Mon Sep 17 00:00:00 2001
0fd959
From: Alan Coopersmith <alan.coopersmith@oracle.com>
0fd959
Date: Sun, 26 Jan 2014 10:54:41 -0800
0fd959
Subject: [PATCH 08/33] Xi: unvalidated lengths in Xinput extension
0fd959
 [CVE-2014-8095]
0fd959
0fd959
Multiple functions in the Xinput extension handling of requests from
0fd959
clients failed to check that the length of the request sent by the
0fd959
client was large enough to perform all the required operations and
0fd959
thus could read or write to memory outside the bounds of the request
0fd959
buffer.
0fd959
0fd959
This commit includes the creation of a new REQUEST_AT_LEAST_EXTRA_SIZE
0fd959
macro in include/dix.h for the common case of needing to ensure a
0fd959
request is large enough to include both the request itself and a
0fd959
minimum amount of extra data following the request header.
0fd959
0fd959
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
0fd959
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
0fd959
Signed-off-by: Fedora X Ninjas <x@fedoraproject.org>
0fd959
---
0fd959
 Xi/chgdctl.c            |  8 ++++++--
0fd959
 Xi/chgfctl.c            |  2 ++
0fd959
 Xi/sendexev.c           |  3 +++
0fd959
 Xi/xiallowev.c          |  2 ++
0fd959
 Xi/xichangecursor.c     |  2 +-
0fd959
 Xi/xichangehierarchy.c  | 35 ++++++++++++++++++++++++++++++++---
0fd959
 Xi/xigetclientpointer.c |  1 +
0fd959
 Xi/xigrabdev.c          |  9 ++++++++-
0fd959
 Xi/xipassivegrab.c      | 12 ++++++++++--
0fd959
 Xi/xiproperty.c         | 14 ++++++--------
0fd959
 Xi/xiquerydevice.c      |  1 +
0fd959
 Xi/xiquerypointer.c     |  2 ++
0fd959
 Xi/xiselectev.c         |  8 ++++++++
0fd959
 Xi/xisetclientpointer.c |  3 ++-
0fd959
 Xi/xisetdevfocus.c      |  4 ++++
0fd959
 Xi/xiwarppointer.c      |  2 ++
0fd959
 include/dix.h           |  4 ++++
0fd959
 17 files changed, 94 insertions(+), 18 deletions(-)
0fd959
0fd959
diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c
0fd959
index d078aa2..b3ee867 100644
0fd959
--- a/Xi/chgdctl.c
0fd959
+++ b/Xi/chgdctl.c
0fd959
@@ -78,7 +78,7 @@ SProcXChangeDeviceControl(ClientPtr client)
0fd959
 
0fd959
     REQUEST(xChangeDeviceControlReq);
0fd959
     swaps(&stuff->length);
0fd959
-    REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);
0fd959
+    REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl));
0fd959
     swaps(&stuff->control);
0fd959
     ctl = (xDeviceCtl *) &stuff[1];
0fd959
     swaps(&ctl->control);
0fd959
@@ -115,7 +115,7 @@ ProcXChangeDeviceControl(ClientPtr client)
0fd959
     xDeviceEnableCtl *e;
0fd959
 
0fd959
     REQUEST(xChangeDeviceControlReq);
0fd959
-    REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);
0fd959
+    REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl));
0fd959
 
0fd959
     len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq));
0fd959
     ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess);
0fd959
@@ -192,6 +192,10 @@ ProcXChangeDeviceControl(ClientPtr client)
0fd959
         break;
0fd959
     case DEVICE_ENABLE:
0fd959
         e = (xDeviceEnableCtl *) &stuff[1];
0fd959
+        if ((len != bytes_to_int32(sizeof(xDeviceEnableCtl)))) {
0fd959
+            ret = BadLength;
0fd959
+            goto out;
0fd959
+        }
0fd959
 
0fd959
         if (IsXTestDevice(dev, NULL))
0fd959
             status = !Success;
0fd959
diff --git a/Xi/chgfctl.c b/Xi/chgfctl.c
0fd959
index 6dcf60c..224c2ba 100644
0fd959
--- a/Xi/chgfctl.c
0fd959
+++ b/Xi/chgfctl.c
0fd959
@@ -467,6 +467,8 @@ ProcXChangeFeedbackControl(ClientPtr client)
0fd959
         xStringFeedbackCtl *f = ((xStringFeedbackCtl *) &stuff[1]);
0fd959
 
0fd959
         if (client->swapped) {
0fd959
+            if (len < bytes_to_int32(sizeof(xStringFeedbackCtl)))
0fd959
+                return BadLength;
0fd959
             swaps(&f->num_keysyms);
0fd959
         }
0fd959
         if (len !=
0fd959
diff --git a/Xi/sendexev.c b/Xi/sendexev.c
0fd959
index 3c21386..183f88d 100644
0fd959
--- a/Xi/sendexev.c
0fd959
+++ b/Xi/sendexev.c
0fd959
@@ -135,6 +135,9 @@ ProcXSendExtensionEvent(ClientPtr client)
0fd959
     if (ret != Success)
0fd959
         return ret;
0fd959
 
0fd959
+    if (stuff->num_events == 0)
0fd959
+        return ret;
0fd959
+
0fd959
     /* The client's event type must be one defined by an extension. */
0fd959
 
0fd959
     first = ((xEvent *) &stuff[1]);
0fd959
diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c
0fd959
index ebef233..ca263ef 100644
0fd959
--- a/Xi/xiallowev.c
0fd959
+++ b/Xi/xiallowev.c
0fd959
@@ -48,6 +48,7 @@ int
0fd959
 SProcXIAllowEvents(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIAllowEventsReq);
0fd959
+    REQUEST_AT_LEAST_SIZE(xXIAllowEventsReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
@@ -55,6 +56,7 @@ SProcXIAllowEvents(ClientPtr client)
0fd959
     if (stuff->length > 3) {
0fd959
         xXI2_2AllowEventsReq *req_xi22 = (xXI2_2AllowEventsReq *) stuff;
0fd959
 
0fd959
+        REQUEST_AT_LEAST_SIZE(xXI2_2AllowEventsReq);
0fd959
         swapl(&req_xi22->touchid);
0fd959
         swapl(&req_xi22->grab_window);
0fd959
     }
0fd959
diff --git a/Xi/xichangecursor.c b/Xi/xichangecursor.c
0fd959
index 0be6bc0..33e9e9c 100644
0fd959
--- a/Xi/xichangecursor.c
0fd959
+++ b/Xi/xichangecursor.c
0fd959
@@ -57,11 +57,11 @@ int
0fd959
 SProcXIChangeCursor(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIChangeCursorReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIChangeCursorReq);
0fd959
     swaps(&stuff->length);
0fd959
     swapl(&stuff->win);
0fd959
     swapl(&stuff->cursor);
0fd959
     swaps(&stuff->deviceid);
0fd959
-    REQUEST_SIZE_MATCH(xXIChangeCursorReq);
0fd959
     return (ProcXIChangeCursor(client));
0fd959
 }
0fd959
 
0fd959
diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
0fd959
index e2f4b8a..8e3415b 100644
0fd959
--- a/Xi/xichangehierarchy.c
0fd959
+++ b/Xi/xichangehierarchy.c
0fd959
@@ -407,7 +407,7 @@ int
0fd959
 ProcXIChangeHierarchy(ClientPtr client)
0fd959
 {
0fd959
     xXIAnyHierarchyChangeInfo *any;
0fd959
-    int required_len = sizeof(xXIChangeHierarchyReq);
0fd959
+    size_t len;			/* length of data remaining in request */
0fd959
     int rc = Success;
0fd959
     int flags[MAXDEVICES] = { 0 };
0fd959
 
0fd959
@@ -417,21 +417,46 @@ ProcXIChangeHierarchy(ClientPtr client)
0fd959
     if (!stuff->num_changes)
0fd959
         return rc;
0fd959
 
0fd959
+    if (stuff->length > (INT_MAX >> 2))
0fd959
+        return BadAlloc;
0fd959
+    len = (stuff->length << 2) - sizeof(xXIAnyHierarchyChangeInfo);
0fd959
+
0fd959
     any = (xXIAnyHierarchyChangeInfo *) &stuff[1];
0fd959
     while (stuff->num_changes--) {
0fd959
+        if (len < sizeof(xXIAnyHierarchyChangeInfo)) {
0fd959
+            rc = BadLength;
0fd959
+            goto unwind;
0fd959
+        }
0fd959
+
0fd959
         SWAPIF(swaps(&any->type));
0fd959
         SWAPIF(swaps(&any->length));
0fd959
 
0fd959
-        required_len += any->length;
0fd959
-        if ((stuff->length * 4) < required_len)
0fd959
+        if ((any->length > (INT_MAX >> 2)) || (len < (any->length << 2)))
0fd959
             return BadLength;
0fd959
 
0fd959
+#define CHANGE_SIZE_MATCH(type) \
0fd959
+    do { \
0fd959
+        if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \
0fd959
+            rc = BadLength; \
0fd959
+            goto unwind; \
0fd959
+        } \
0fd959
+    } while(0)
0fd959
+
0fd959
         switch (any->type) {
0fd959
         case XIAddMaster:
0fd959
         {
0fd959
             xXIAddMasterInfo *c = (xXIAddMasterInfo *) any;
0fd959
 
0fd959
+            /* Variable length, due to appended name string */
0fd959
+            if (len < sizeof(xXIAddMasterInfo)) {
0fd959
+                rc = BadLength;
0fd959
+                goto unwind;
0fd959
+            }
0fd959
             SWAPIF(swaps(&c->name_len));
0fd959
+            if (c->name_len > (len - sizeof(xXIAddMasterInfo))) {
0fd959
+                rc = BadLength;
0fd959
+                goto unwind;
0fd959
+            }
0fd959
 
0fd959
             rc = add_master(client, c, flags);
0fd959
             if (rc != Success)
0fd959
@@ -442,6 +467,7 @@ ProcXIChangeHierarchy(ClientPtr client)
0fd959
         {
0fd959
             xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any;
0fd959
 
0fd959
+            CHANGE_SIZE_MATCH(xXIRemoveMasterInfo);
0fd959
             rc = remove_master(client, r, flags);
0fd959
             if (rc != Success)
0fd959
                 goto unwind;
0fd959
@@ -451,6 +477,7 @@ ProcXIChangeHierarchy(ClientPtr client)
0fd959
         {
0fd959
             xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any;
0fd959
 
0fd959
+            CHANGE_SIZE_MATCH(xXIDetachSlaveInfo);
0fd959
             rc = detach_slave(client, c, flags);
0fd959
             if (rc != Success)
0fd959
                 goto unwind;
0fd959
@@ -460,6 +487,7 @@ ProcXIChangeHierarchy(ClientPtr client)
0fd959
         {
0fd959
             xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any;
0fd959
 
0fd959
+            CHANGE_SIZE_MATCH(xXIAttachSlaveInfo);
0fd959
             rc = attach_slave(client, c, flags);
0fd959
             if (rc != Success)
0fd959
                 goto unwind;
0fd959
@@ -467,6 +495,7 @@ ProcXIChangeHierarchy(ClientPtr client)
0fd959
             break;
0fd959
         }
0fd959
 
0fd959
+        len -= any->length * 4;
0fd959
         any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4);
0fd959
     }
0fd959
 
0fd959
diff --git a/Xi/xigetclientpointer.c b/Xi/xigetclientpointer.c
0fd959
index 3c90d58..306dd39 100644
0fd959
--- a/Xi/xigetclientpointer.c
0fd959
+++ b/Xi/xigetclientpointer.c
0fd959
@@ -50,6 +50,7 @@ int
0fd959
 SProcXIGetClientPointer(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIGetClientPointerReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIGetClientPointerReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swapl(&stuff->win);
0fd959
diff --git a/Xi/xigrabdev.c b/Xi/xigrabdev.c
0fd959
index 63d95bc..e2a2ae3 100644
0fd959
--- a/Xi/xigrabdev.c
0fd959
+++ b/Xi/xigrabdev.c
0fd959
@@ -47,6 +47,11 @@ int
0fd959
 SProcXIGrabDevice(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIGrabDeviceReq);
0fd959
+    /*
0fd959
+     * Check here for at least the length of the struct we swap, then
0fd959
+     * let ProcXIGrabDevice check the full size after we swap mask_len.
0fd959
+     */
0fd959
+    REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
@@ -71,7 +76,7 @@ ProcXIGrabDevice(ClientPtr client)
0fd959
     unsigned int pointer_mode;
0fd959
 
0fd959
     REQUEST(xXIGrabDeviceReq);
0fd959
-    REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq);
0fd959
+    REQUEST_FIXED_SIZE(xXIGrabDeviceReq, ((size_t) stuff->mask_len) * 4);
0fd959
 
0fd959
     ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
0fd959
     if (ret != Success)
0fd959
@@ -131,6 +136,7 @@ int
0fd959
 SProcXIUngrabDevice(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIUngrabDeviceReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIUngrabDeviceReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
@@ -148,6 +154,7 @@ ProcXIUngrabDevice(ClientPtr client)
0fd959
     TimeStamp time;
0fd959
 
0fd959
     REQUEST(xXIUngrabDeviceReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIUngrabDeviceReq);
0fd959
 
0fd959
     ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
0fd959
     if (ret != Success)
0fd959
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
0fd959
index eccec0a..a714a44 100644
0fd959
--- a/Xi/xipassivegrab.c
0fd959
+++ b/Xi/xipassivegrab.c
0fd959
@@ -53,6 +53,7 @@ SProcXIPassiveGrabDevice(ClientPtr client)
0fd959
     uint32_t *mods;
0fd959
 
0fd959
     REQUEST(xXIPassiveGrabDeviceReq);
0fd959
+    REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
@@ -63,6 +64,8 @@ SProcXIPassiveGrabDevice(ClientPtr client)
0fd959
     swaps(&stuff->mask_len);
0fd959
     swaps(&stuff->num_modifiers);
0fd959
 
0fd959
+    REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
0fd959
+        ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4);
0fd959
     mods = (uint32_t *) &stuff[1];
0fd959
 
0fd959
     for (i = 0; i < stuff->num_modifiers; i++, mods++) {
0fd959
@@ -92,7 +95,8 @@ ProcXIPassiveGrabDevice(ClientPtr client)
0fd959
     int mask_len;
0fd959
 
0fd959
     REQUEST(xXIPassiveGrabDeviceReq);
0fd959
-    REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
0fd959
+    REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq,
0fd959
+        ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4);
0fd959
 
0fd959
     if (stuff->deviceid == XIAllDevices)
0fd959
         dev = inputInfo.all_devices;
0fd959
@@ -248,6 +252,7 @@ SProcXIPassiveUngrabDevice(ClientPtr client)
0fd959
     uint32_t *modifiers;
0fd959
 
0fd959
     REQUEST(xXIPassiveUngrabDeviceReq);
0fd959
+    REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swapl(&stuff->grab_window);
0fd959
@@ -255,6 +260,8 @@ SProcXIPassiveUngrabDevice(ClientPtr client)
0fd959
     swapl(&stuff->detail);
0fd959
     swaps(&stuff->num_modifiers);
0fd959
 
0fd959
+    REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
0fd959
+                       ((uint32_t) stuff->num_modifiers) << 2);
0fd959
     modifiers = (uint32_t *) &stuff[1];
0fd959
 
0fd959
     for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
0fd959
@@ -273,7 +280,8 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
0fd959
     int i, rc;
0fd959
 
0fd959
     REQUEST(xXIPassiveUngrabDeviceReq);
0fd959
-    REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
0fd959
+    REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq,
0fd959
+                       ((uint32_t) stuff->num_modifiers) << 2);
0fd959
 
0fd959
     if (stuff->deviceid == XIAllDevices)
0fd959
         dev = inputInfo.all_devices;
0fd959
diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c
0fd959
index 796ba09..c99e282 100644
0fd959
--- a/Xi/xiproperty.c
0fd959
+++ b/Xi/xiproperty.c
0fd959
@@ -1013,10 +1013,9 @@ int
0fd959
 SProcXListDeviceProperties(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xListDevicePropertiesReq);
0fd959
+    REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
-
0fd959
-    REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
0fd959
     return (ProcXListDeviceProperties(client));
0fd959
 }
0fd959
 
0fd959
@@ -1037,10 +1036,10 @@ int
0fd959
 SProcXDeleteDeviceProperty(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xDeleteDevicePropertyReq);
0fd959
+    REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swapl(&stuff->property);
0fd959
-    REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
0fd959
     return (ProcXDeleteDeviceProperty(client));
0fd959
 }
0fd959
 
0fd959
@@ -1048,13 +1047,13 @@ int
0fd959
 SProcXGetDeviceProperty(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xGetDevicePropertyReq);
0fd959
+    REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swapl(&stuff->property);
0fd959
     swapl(&stuff->type);
0fd959
     swapl(&stuff->longOffset);
0fd959
     swapl(&stuff->longLength);
0fd959
-    REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
0fd959
     return (ProcXGetDeviceProperty(client));
0fd959
 }
0fd959
 
0fd959
@@ -1253,11 +1252,10 @@ int
0fd959
 SProcXIListProperties(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIListPropertiesReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIListPropertiesReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
-
0fd959
-    REQUEST_SIZE_MATCH(xXIListPropertiesReq);
0fd959
     return (ProcXIListProperties(client));
0fd959
 }
0fd959
 
0fd959
@@ -1279,11 +1277,11 @@ int
0fd959
 SProcXIDeleteProperty(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIDeletePropertyReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
     swapl(&stuff->property);
0fd959
-    REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
0fd959
     return (ProcXIDeleteProperty(client));
0fd959
 }
0fd959
 
0fd959
@@ -1291,6 +1289,7 @@ int
0fd959
 SProcXIGetProperty(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIGetPropertyReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIGetPropertyReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
@@ -1298,7 +1297,6 @@ SProcXIGetProperty(ClientPtr client)
0fd959
     swapl(&stuff->type);
0fd959
     swapl(&stuff->offset);
0fd959
     swapl(&stuff->len);
0fd959
-    REQUEST_SIZE_MATCH(xXIGetPropertyReq);
0fd959
     return (ProcXIGetProperty(client));
0fd959
 }
0fd959
 
0fd959
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
0fd959
index 4e544f0..67a9a4f 100644
0fd959
--- a/Xi/xiquerydevice.c
0fd959
+++ b/Xi/xiquerydevice.c
0fd959
@@ -54,6 +54,7 @@ int
0fd959
 SProcXIQueryDevice(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIQueryDeviceReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
0fd959
 
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
diff --git a/Xi/xiquerypointer.c b/Xi/xiquerypointer.c
0fd959
index e9bdd42..7ec0c85 100644
0fd959
--- a/Xi/xiquerypointer.c
0fd959
+++ b/Xi/xiquerypointer.c
0fd959
@@ -63,6 +63,8 @@ int
0fd959
 SProcXIQueryPointer(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIQueryPointerReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIQueryPointerReq);
0fd959
+
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
     swapl(&stuff->win);
0fd959
diff --git a/Xi/xiselectev.c b/Xi/xiselectev.c
0fd959
index 45a996e..168579f 100644
0fd959
--- a/Xi/xiselectev.c
0fd959
+++ b/Xi/xiselectev.c
0fd959
@@ -114,6 +114,7 @@ int
0fd959
 SProcXISelectEvents(ClientPtr client)
0fd959
 {
0fd959
     int i;
0fd959
+    int len;
0fd959
     xXIEventMask *evmask;
0fd959
 
0fd959
     REQUEST(xXISelectEventsReq);
0fd959
@@ -122,10 +123,17 @@ SProcXISelectEvents(ClientPtr client)
0fd959
     swapl(&stuff->win);
0fd959
     swaps(&stuff->num_masks);
0fd959
 
0fd959
+    len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq));
0fd959
     evmask = (xXIEventMask *) &stuff[1];
0fd959
     for (i = 0; i < stuff->num_masks; i++) {
0fd959
+        if (len < bytes_to_int32(sizeof(xXIEventMask)))
0fd959
+            return BadLength;
0fd959
+        len -= bytes_to_int32(sizeof(xXIEventMask));
0fd959
         swaps(&evmask->deviceid);
0fd959
         swaps(&evmask->mask_len);
0fd959
+        if (len < evmask->mask_len)
0fd959
+            return BadLength;
0fd959
+        len -= evmask->mask_len;
0fd959
         evmask =
0fd959
             (xXIEventMask *) (((char *) &evmask[1]) + evmask->mask_len * 4);
0fd959
     }
0fd959
diff --git a/Xi/xisetclientpointer.c b/Xi/xisetclientpointer.c
0fd959
index 38ff51e..24d4a53 100644
0fd959
--- a/Xi/xisetclientpointer.c
0fd959
+++ b/Xi/xisetclientpointer.c
0fd959
@@ -51,10 +51,11 @@ int
0fd959
 SProcXISetClientPointer(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXISetClientPointerReq);
0fd959
+    REQUEST_SIZE_MATCH(xXISetClientPointerReq);
0fd959
+
0fd959
     swaps(&stuff->length);
0fd959
     swapl(&stuff->win);
0fd959
     swaps(&stuff->deviceid);
0fd959
-    REQUEST_SIZE_MATCH(xXISetClientPointerReq);
0fd959
     return (ProcXISetClientPointer(client));
0fd959
 }
0fd959
 
0fd959
diff --git a/Xi/xisetdevfocus.c b/Xi/xisetdevfocus.c
0fd959
index 372ec24..96a9a16 100644
0fd959
--- a/Xi/xisetdevfocus.c
0fd959
+++ b/Xi/xisetdevfocus.c
0fd959
@@ -44,6 +44,8 @@ int
0fd959
 SProcXISetFocus(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXISetFocusReq);
0fd959
+    REQUEST_AT_LEAST_SIZE(xXISetFocusReq);
0fd959
+
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
     swapl(&stuff->focus);
0fd959
@@ -56,6 +58,8 @@ int
0fd959
 SProcXIGetFocus(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIGetFocusReq);
0fd959
+    REQUEST_AT_LEAST_SIZE(xXIGetFocusReq);
0fd959
+
0fd959
     swaps(&stuff->length);
0fd959
     swaps(&stuff->deviceid);
0fd959
 
0fd959
diff --git a/Xi/xiwarppointer.c b/Xi/xiwarppointer.c
0fd959
index 3f051f7..780758a 100644
0fd959
--- a/Xi/xiwarppointer.c
0fd959
+++ b/Xi/xiwarppointer.c
0fd959
@@ -56,6 +56,8 @@ int
0fd959
 SProcXIWarpPointer(ClientPtr client)
0fd959
 {
0fd959
     REQUEST(xXIWarpPointerReq);
0fd959
+    REQUEST_SIZE_MATCH(xXIWarpPointerReq);
0fd959
+
0fd959
     swaps(&stuff->length);
0fd959
     swapl(&stuff->src_win);
0fd959
     swapl(&stuff->dst_win);
0fd959
diff --git a/include/dix.h b/include/dix.h
0fd959
index 7c36932..72adad3 100644
0fd959
--- a/include/dix.h
0fd959
+++ b/include/dix.h
0fd959
@@ -74,6 +74,10 @@ SOFTWARE.
0fd959
     if ((sizeof(req) >> 2) > client->req_len )\
0fd959
          return(BadLength)
0fd959
 
0fd959
+#define REQUEST_AT_LEAST_EXTRA_SIZE(req, extra)  \
0fd959
+    if (((sizeof(req) + ((uint64_t) extra)) >> 2) > client->req_len ) \
0fd959
+         return(BadLength)
0fd959
+
0fd959
 #define REQUEST_FIXED_SIZE(req, n)\
0fd959
     if (((sizeof(req) >> 2) > client->req_len) || \
0fd959
         ((n >> 2) >= client->req_len) || \
0fd959
-- 
0fd959
1.9.3
0fd959