[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#852966: jessie-pu: package libxi/2:1.7.4-1+deb8u1



Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
Usertags: pu

I think this is the last one for this round.  It's also the one I'm
least confident about.  But it's been in sid and wheezy-lts for a while,
and a couple of issues have already been found and fixed, so maybe it's
ok.

Cheers,
Julien

diff -u libxi-1.7.4/debian/changelog libxi-1.7.4/debian/changelog
--- libxi-1.7.4/debian/changelog
+++ libxi-1.7.4/debian/changelog
@@ -1,3 +1,11 @@
+libxi (2:1.7.4-1+deb8u1) jessie; urgency=medium
+
+  * Insufficient validation of data from the X server can cause out of
+    boundary memory access or endless loops.  Addresses CVE-2016-7945 and
+    CVE-2016-7946.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 28 Jan 2017 16:17:42 +0100
+
 libxi (2:1.7.4-1) unstable; urgency=low
 
   * New upstream release.
only in patch2:
unchanged:
--- libxi-1.7.4.orig/man/XListInputDevices.txt
+++ libxi-1.7.4/man/XListInputDevices.txt
@@ -220,5 +220,13 @@
    Floating. If the device is a master device, attached specifies
    the device ID of the master device this device is paired with.
 
-   To free the XDeviceInfo array created by XListInputDevices, use
-   XFreeDeviceList.
+RETURN VALUE
+------------
+
+   XListInputDevices returns a pointer to an array of XDeviceInfo
+   structs and sets ndevices_return to the number of elements in
+   that array. To free the XDeviceInfo array created by
+   XListInputDevices, use XFreeDeviceList.
+
+   On error, XListInputDevices returns NULL and ndevices_return is
+   left unmodified.
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XGMotion.c
+++ libxi-1.7.4/src/XGMotion.c
@@ -114,7 +114,8 @@
     }
     /* rep.axes is a CARD8, so assume max number of axes for bounds check */
     if (rep.nEvents <
-	(INT_MAX / (sizeof(XDeviceTimeCoord) + (UCHAR_MAX * sizeof(int))))) {
+	(INT_MAX / (sizeof(XDeviceTimeCoord) + (UCHAR_MAX * sizeof(int)))) &&
+	rep.nEvents * (rep.axes + 1) <= rep.length) {
 	size_t bsize = rep.nEvents *
 	    (sizeof(XDeviceTimeCoord) + (rep.axes * sizeof(int)));
 	bufp = Xmalloc(bsize);
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XGetBMap.c
+++ libxi-1.7.4/src/XGetBMap.c
@@ -92,7 +92,8 @@
 
     status = _XReply(dpy, (xReply *) & rep, 0, xFalse);
     if (status == 1) {
-	if (rep.length <= (sizeof(mapping) >> 2)) {
+	if (rep.length <= (sizeof(mapping) >> 2) &&
+	    rep.nElts <= (rep.length << 2)) {
 	    unsigned long nbytes = rep.length << 2;
 	    _XRead(dpy, (char *)mapping, nbytes);
 
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XGetDCtl.c
+++ libxi-1.7.4/src/XGetDCtl.c
@@ -93,7 +93,8 @@
     if (rep.length > 0) {
 	unsigned long nbytes;
 	size_t size = 0;
-	if (rep.length < (INT_MAX >> 2)) {
+	if (rep.length < (INT_MAX >> 2) &&
+	    (rep.length << 2) >= sizeof(xDeviceState)) {
 	    nbytes = (unsigned long) rep.length << 2;
 	    d = Xmalloc(nbytes);
 	}
@@ -117,7 +118,8 @@
 	    size_t val_size;
 
 	    r = (xDeviceResolutionState *) d;
-	    if (r->num_valuators >= (INT_MAX / (3 * sizeof(int))))
+	    if (sizeof(xDeviceResolutionState) > nbytes ||
+		r->num_valuators >= (INT_MAX / (3 * sizeof(int))))
 		goto out;
 	    val_size = 3 * sizeof(int) * r->num_valuators;
 	    if ((sizeof(xDeviceResolutionState) + val_size) > nbytes)
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XGetFCtl.c
+++ libxi-1.7.4/src/XGetFCtl.c
@@ -73,6 +73,7 @@
     XFeedbackState *Sav = NULL;
     xFeedbackState *f = NULL;
     xFeedbackState *sav = NULL;
+    char *end = NULL;
     xGetFeedbackControlReq *req;
     xGetFeedbackControlReply rep;
     XExtDisplayInfo *info = XInput_find_display(dpy);
@@ -105,10 +106,12 @@
 	    goto out;
 	}
 	sav = f;
+	end = (char *)f + nbytes;
 	_XRead(dpy, (char *)f, nbytes);
 
 	for (i = 0; i < *num_feedbacks; i++) {
-	    if (f->length > nbytes)
+	    if ((char *)f + sizeof(*f) > end ||
+	        f->length == 0 || f->length > nbytes)
 		goto out;
 	    nbytes -= f->length;
 
@@ -125,6 +128,8 @@
 	    case StringFeedbackClass:
 	    {
 		xStringFeedbackState *strf = (xStringFeedbackState *) f;
+		if ((char *)f + sizeof(*strf) > end)
+		    goto out;
 		size += sizeof(XStringFeedbackState) +
 		    (strf->num_syms_supported * sizeof(KeySym));
 	    }
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XGetKMap.c
+++ libxi-1.7.4/src/XGetKMap.c
@@ -54,6 +54,7 @@
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include <X11/Xlibint.h>
@@ -93,9 +94,16 @@
 	return (KeySym *) NULL;
     }
     if (rep.length > 0) {
-	*syms_per_code = rep.keySymsPerKeyCode;
-	nbytes = (long)rep.length << 2;
-	mapping = (KeySym *) Xmalloc((unsigned)nbytes);
+	if (rep.length < INT_MAX >> 2 &&
+	    rep.length == rep.keySymsPerKeyCode * keycount) {
+	    *syms_per_code = rep.keySymsPerKeyCode;
+	    nbytes = (long)rep.length << 2;
+	    mapping = (KeySym *) Xmalloc((unsigned)nbytes);
+	} else {
+	    *syms_per_code = 0;
+	    nbytes = 0;
+	    mapping = NULL;
+	}
 	if (mapping)
 	    _XRead(dpy, (char *)mapping, nbytes);
 	else
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XGetMMap.c
+++ libxi-1.7.4/src/XGetMMap.c
@@ -53,6 +53,7 @@
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include <X11/Xlibint.h>
@@ -85,8 +86,14 @@
 	SyncHandle();
 	return (XModifierKeymap *) NULL;
     }
-    nbytes = (unsigned long)rep.length << 2;
-    res = (XModifierKeymap *) Xmalloc(sizeof(XModifierKeymap));
+    if (rep.length < (INT_MAX >> 2) &&
+	rep.numKeyPerModifier == rep.length >> 1) {
+	nbytes = (unsigned long)rep.length << 2;
+	res = (XModifierKeymap *) Xmalloc(sizeof(XModifierKeymap));
+    } else {
+	nbytes = 0;
+	res = NULL;
+    }
     if (res) {
 	res->modifiermap = (KeyCode *) Xmalloc(nbytes);
 	if (res->modifiermap)
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XIQueryDevice.c
+++ libxi-1.7.4/src/XIQueryDevice.c
@@ -26,6 +26,7 @@
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <stdint.h>
 #include <X11/Xlibint.h>
 #include <X11/extensions/XI2proto.h>
@@ -43,8 +44,9 @@
     xXIQueryDeviceReq   *req;
     xXIQueryDeviceReply reply;
     char                *ptr;
+    char                *end;
     int                 i;
-    char                *buf;
+    char                *buf = NULL;
 
     XExtDisplayInfo *extinfo = XInput_find_display(dpy);
 
@@ -60,14 +62,25 @@
     if (!_XReply(dpy, (xReply*) &reply, 0, xFalse))
         goto error;
 
-    *ndevices_return = reply.num_devices;
-    info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
-    if (!info)
+    if (reply.length < INT_MAX / 4)
+    {
+	*ndevices_return = reply.num_devices;
+	info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
+	buf = Xmalloc(reply.length * 4);
+    }
+    else
+    {
+	*ndevices_return = 0;
+	info = NULL;
+	buf = NULL;
+    }
+
+    if (!info || !buf)
         goto error;
 
-    buf = Xmalloc(reply.length * 4);
     _XRead(dpy, buf, reply.length * 4);
     ptr = buf;
+    end = buf + reply.length * 4;
 
     /* info is a null-terminated array */
     info[reply.num_devices].name = NULL;
@@ -79,6 +92,9 @@
         XIDeviceInfo    *lib = &info[i];
         xXIDeviceInfo   *wire = (xXIDeviceInfo*)ptr;
 
+        if (ptr + sizeof(xXIDeviceInfo) > end)
+            goto error_loop;
+
         lib->deviceid    = wire->deviceid;
         lib->use         = wire->use;
         lib->attachment  = wire->attachment;
@@ -87,12 +103,23 @@
 
         ptr += sizeof(xXIDeviceInfo);
 
+        if (ptr + wire->name_len > end)
+            goto error_loop;
+
         lib->name = Xcalloc(wire->name_len + 1, 1);
+        if (lib->name == NULL)
+            goto error_loop;
         strncpy(lib->name, ptr, wire->name_len);
+        lib->name[wire->name_len] = '\0';
         ptr += ((wire->name_len + 3)/4) * 4;
 
         sz = size_classes((xXIAnyInfo*)ptr, nclasses);
         lib->classes = Xmalloc(sz);
+        if (lib->classes == NULL)
+        {
+            Xfree(lib->name);
+            goto error_loop;
+        }
         ptr += copy_classes(lib, (xXIAnyInfo*)ptr, &nclasses);
         /* We skip over unused classes */
         lib->num_classes = nclasses;
@@ -103,7 +130,15 @@
     SyncHandle();
     return info;
 
+error_loop:
+    while (--i >= 0)
+    {
+        Xfree(info[i].name);
+        Xfree(info[i].classes);
+    }
 error:
+    Xfree(info);
+    Xfree(buf);
     UnlockDisplay(dpy);
     SyncHandle();
     *ndevices_return = -1;
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XListDev.c
+++ libxi-1.7.4/src/XListDev.c
@@ -73,35 +73,42 @@
     return ((base_size + padsize - 1)/padsize) * padsize;
 }
 
-static size_t
-SizeClassInfo(xAnyClassPtr *any, int num_classes)
+static int
+SizeClassInfo(xAnyClassPtr *any, size_t len, int num_classes, size_t *size)
 {
-    int size = 0;
     int j;
+    size_t sz = 0;
+
     for (j = 0; j < num_classes; j++) {
         switch ((*any)->class) {
             case KeyClass:
-                size += pad_to_xid(sizeof(XKeyInfo));
+                sz += pad_to_xid(sizeof(XKeyInfo));
                 break;
             case ButtonClass:
-                size += pad_to_xid(sizeof(XButtonInfo));
+                sz += pad_to_xid(sizeof(XButtonInfo));
                 break;
             case ValuatorClass:
                 {
                     xValuatorInfoPtr v;
 
+                    if (len < sizeof(v))
+                        return 1;
                     v = (xValuatorInfoPtr) *any;
-                    size += pad_to_xid(sizeof(XValuatorInfo) +
+                    sz += pad_to_xid(sizeof(XValuatorInfo) +
                         (v->num_axes * sizeof(XAxisInfo)));
                     break;
                 }
             default:
                 break;
         }
+        if ((*any)->length > len)
+            return 1;
         *any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
     }
 
-    return size;
+    *size = sz;
+
+    return 0;
 }
 
 static void
@@ -168,9 +175,9 @@
 XDeviceInfo *
 XListInputDevices(
     register Display	*dpy,
-    int			*ndevices)
+    int			*ndevices_return)
 {
-    size_t size;
+    size_t s, size;
     xListInputDevicesReq *req;
     xListInputDevicesReply rep;
     xDeviceInfo *list, *slist = NULL;
@@ -178,10 +185,12 @@
     XDeviceInfo *clist = NULL;
     xAnyClassPtr any, sav_any;
     XAnyClassPtr Any;
+    char *end = NULL;
     unsigned char *nptr, *Nptr;
     int i;
     unsigned long rlen;
     XExtDisplayInfo *info = XInput_find_display(dpy);
+    int ndevices;
 
     LockDisplay(dpy);
     if (_XiCheckExtInit(dpy, XInput_Initial_Release, info) == -1)
@@ -197,8 +206,8 @@
 	return (XDeviceInfo *) NULL;
     }
 
-    if ((*ndevices = rep.ndevices)) {	/* at least 1 input device */
-	size = *ndevices * sizeof(XDeviceInfo);
+    if ((ndevices = rep.ndevices)) {	/* at least 1 input device */
+	size = ndevices * sizeof(XDeviceInfo);
 	if (rep.length < (INT_MAX >> 2)) {
 	    rlen = rep.length << 2;	/* multiply length by 4    */
 	    slist = list = Xmalloc(rlen);
@@ -211,18 +220,21 @@
 	}
 	_XRead(dpy, (char *)list, rlen);
 
-	any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo)));
+	any = (xAnyClassPtr) ((char *)list + (ndevices * sizeof(xDeviceInfo)));
 	sav_any = any;
-	for (i = 0; i < *ndevices; i++, list++) {
-            size += SizeClassInfo(&any, (int)list->num_classes);
+	end = (char *)list + rlen;
+	for (i = 0; i < ndevices; i++, list++) {
+            if(SizeClassInfo(&any, end - (char *)any, (int)list->num_classes, &s))
+                goto out;
+            size += s;
 	}
 
-	Nptr = ((unsigned char *)list) + rlen + 1;
-	for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) {
+	Nptr = ((unsigned char *)list) + rlen;
+	for (i = 0, nptr = (unsigned char *)any; i < ndevices; i++) {
+	    if (nptr >= Nptr)
+		goto out;
 	    size += *nptr + 1;
 	    nptr += (*nptr + 1);
-	    if (nptr > Nptr)
-		goto out;
 	}
 
 	clist = (XDeviceInfoPtr) Xmalloc(size);
@@ -234,10 +246,10 @@
 	}
 	sclist = clist;
 	Any = (XAnyClassPtr) ((char *)clist +
-			      (*ndevices * sizeof(XDeviceInfo)));
+			      (ndevices * sizeof(XDeviceInfo)));
 	list = slist;
 	any = sav_any;
-	for (i = 0; i < *ndevices; i++, list++, clist++) {
+	for (i = 0; i < ndevices; i++, list++, clist++) {
 	    clist->type = list->type;
 	    clist->id = list->id;
 	    clist->use = list->use;
@@ -250,7 +262,7 @@
 	clist = sclist;
 	nptr = (unsigned char *)any;
 	Nptr = (unsigned char *)Any;
-	for (i = 0; i < *ndevices; i++, clist++) {
+	for (i = 0; i < ndevices; i++, clist++) {
 	    clist->name = (char *)Nptr;
 	    memcpy(Nptr, nptr + 1, *nptr);
 	    Nptr += (*nptr);
@@ -259,6 +271,8 @@
 	}
     }
 
+    *ndevices_return = ndevices;
+
   out:
     XFree((char *)slist);
     UnlockDisplay(dpy);
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XOpenDev.c
+++ libxi-1.7.4/src/XOpenDev.c
@@ -53,6 +53,7 @@
 #include <config.h>
 #endif
 
+#include <limits.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include <X11/Xlibint.h>
@@ -86,9 +87,15 @@
 	return (XDevice *) NULL;
     }
 
-    rlen = rep.length << 2;
-    dev = (XDevice *) Xmalloc(sizeof(XDevice) + rep.num_classes *
-			      sizeof(XInputClassInfo));
+    if (rep.length < INT_MAX >> 2 &&
+	(rep.length << 2) >= rep.num_classes * sizeof(xInputClassInfo)) {
+	rlen = rep.length << 2;
+	dev = (XDevice *) Xmalloc(sizeof(XDevice) + rep.num_classes *
+				  sizeof(XInputClassInfo));
+    } else {
+	rlen = 0;
+	dev = NULL;
+    }
     if (dev) {
 	int dlen;	/* data length */
 
only in patch2:
unchanged:
--- libxi-1.7.4.orig/src/XQueryDv.c
+++ libxi-1.7.4/src/XQueryDv.c
@@ -73,7 +73,7 @@
     xQueryDeviceStateReply rep;
     XDeviceState *state = NULL;
     XInputClass *any, *Any;
-    char *data = NULL;
+    char *data = NULL, *end = NULL;
     XExtDisplayInfo *info = XInput_find_display(dpy);
 
     LockDisplay(dpy);
@@ -92,6 +92,7 @@
 	if (rep.length < (INT_MAX >> 2)) {
 	    rlen = (unsigned long) rep.length << 2;
 	    data = Xmalloc(rlen);
+	    end = data + rlen;
 	}
 	if (!data) {
 	    _XEatDataWords(dpy, rep.length);
@@ -100,7 +101,8 @@
 	_XRead(dpy, data, rlen);
 
 	for (i = 0, any = (XInputClass *) data; i < (int)rep.num_classes; i++) {
-	    if (any->length > rlen)
+	    if ((char *)any + sizeof(XInputClass) > end ||
+		any->length == 0 || any->length > rlen)
 		goto out;
 	    rlen -= any->length;
 
@@ -114,6 +116,8 @@
 	    case ValuatorClass:
 	    {
 		xValuatorState *v = (xValuatorState *) any;
+		if ((char *)any + sizeof(xValuatorState) > end)
+		    goto out;
 		size += (sizeof(XValuatorState) +
 			 (v->num_valuators * sizeof(int)));
 	    }

Attachment: signature.asc
Description: PGP signature


Reply to: