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