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

Bug#852966: marked as done (jessie-pu: package libxi/2:1.7.4-1+deb8u1)



Your message dated Sat, 09 Dec 2017 10:47:53 +0000
with message-id <1512816473.1994.32.camel@adam-barratt.org.uk>
and subject line Closing bugs for updates included in jessie point release
has caused the Debian Bug report #852966,
regarding jessie-pu: package libxi/2:1.7.4-1+deb8u1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
852966: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=852966
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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


--- End Message ---
--- Begin Message ---
Version: 8.10

Hi,

Each of the updates referenced in these bugs was included in this
morning's jessie point release. Thanks!

Regards,

Adam

--- End Message ---

Reply to: