Commit 19a9cd60 authored by Tobias Stoeckmann's avatar Tobias Stoeckmann Committed by Matthieu Herrb

Properly validate server responses.

By validating length fields from server responses, out of boundary
accesses and endless loops can be mitigated.
Signed-off-by: Tobias Stoeckmann's avatarTobias Stoeckmann <tobias@stoeckmann.org>
Reviewed-by: Matthieu Herrb's avatarMatthieu Herrb <matthieu@herrb.eu>
parent 2286282f
......@@ -114,7 +114,8 @@ XGetDeviceMotionEvents(
}
/* 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);
......
......@@ -92,7 +92,8 @@ XGetDeviceButtonMapping(
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);
......
......@@ -93,7 +93,8 @@ XGetDeviceControl(
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 @@ XGetDeviceControl(
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)
......
......@@ -73,6 +73,7 @@ XGetFeedbackControl(
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 @@ XGetFeedbackControl(
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 @@ XGetFeedbackControl(
case StringFeedbackClass:
{
xStringFeedbackState *strf = (xStringFeedbackState *) f;
if ((char *)f + sizeof(*strf) > end)
goto out;
size += sizeof(XStringFeedbackState) +
(strf->num_syms_supported * sizeof(KeySym));
}
......
......@@ -54,6 +54,7 @@ SOFTWARE.
#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 @@ XGetDeviceKeyMapping(register Display * dpy, XDevice * dev,
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
......
......@@ -53,6 +53,7 @@ SOFTWARE.
#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 @@ XGetDeviceModifierMapping(
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)
......
......@@ -26,6 +26,7 @@
#include <config.h>
#endif
#include <limits.h>
#include <stdint.h>
#include <X11/Xlibint.h>
#include <X11/extensions/XI2proto.h>
......@@ -43,6 +44,7 @@ XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return)
xXIQueryDeviceReq *req;
xXIQueryDeviceReply reply;
char *ptr;
char *end;
int i;
char *buf;
......@@ -60,14 +62,24 @@ XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return)
if (!_XReply(dpy, (xReply*) &reply, 0, xFalse))
goto error;
*ndevices_return = reply.num_devices;
info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
if (reply.length < INT_MAX / 4)
{
*ndevices_return = reply.num_devices;
info = Xmalloc((reply.num_devices + 1) * sizeof(XIDeviceInfo));
}
else
{
*ndevices_return = 0;
info = NULL;
}
if (!info)
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 +91,9 @@ XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return)
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 +102,23 @@ XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return)
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,6 +129,12 @@ XIQueryDevice(Display *dpy, int deviceid, int *ndevices_return)
SyncHandle();
return info;
error_loop:
while (--i >= 0)
{
Xfree(info[i].name);
Xfree(info[i].classes);
}
error:
UnlockDisplay(dpy);
error_unlocked:
......
......@@ -74,7 +74,7 @@ static int pad_to_xid(int base_size)
}
static size_t
SizeClassInfo(xAnyClassPtr *any, int num_classes)
SizeClassInfo(xAnyClassPtr *any, size_t len, int num_classes)
{
int size = 0;
int j;
......@@ -90,6 +90,8 @@ SizeClassInfo(xAnyClassPtr *any, int num_classes)
{
xValuatorInfoPtr v;
if (len < sizeof(v))
return 0;
v = (xValuatorInfoPtr) *any;
size += pad_to_xid(sizeof(XValuatorInfo) +
(v->num_axes * sizeof(XAxisInfo)));
......@@ -98,6 +100,8 @@ SizeClassInfo(xAnyClassPtr *any, int num_classes)
default:
break;
}
if ((*any)->length > len)
return 0;
*any = (xAnyClassPtr) ((char *)(*any) + (*any)->length);
}
......@@ -170,7 +174,7 @@ XListInputDevices(
register Display *dpy,
int *ndevices)
{
size_t size;
size_t s, size;
xListInputDevicesReq *req;
xListInputDevicesReply rep;
xDeviceInfo *list, *slist = NULL;
......@@ -178,6 +182,7 @@ XListInputDevices(
XDeviceInfo *clist = NULL;
xAnyClassPtr any, sav_any;
XAnyClassPtr Any;
char *end = NULL;
unsigned char *nptr, *Nptr;
int i;
unsigned long rlen;
......@@ -213,16 +218,20 @@ XListInputDevices(
any = (xAnyClassPtr) ((char *)list + (*ndevices * sizeof(xDeviceInfo)));
sav_any = any;
end = (char *)list + rlen;
for (i = 0; i < *ndevices; i++, list++) {
size += SizeClassInfo(&any, (int)list->num_classes);
s = SizeClassInfo(&any, end - (char *)any, (int)list->num_classes);
if (!s)
goto out;
size += s;
}
Nptr = ((unsigned char *)list) + rlen + 1;
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);
......
......@@ -53,6 +53,7 @@ SOFTWARE.
#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 @@ XOpenDevice(
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 */
......
......@@ -73,7 +73,7 @@ XQueryDeviceState(
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 @@ XQueryDeviceState(
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 @@ XQueryDeviceState(
_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 @@ XQueryDeviceState(
case ValuatorClass:
{
xValuatorState *v = (xValuatorState *) any;
if ((char *)any + sizeof(xValuatorState) > end)
goto out;
size += (sizeof(XValuatorState) +
(v->num_valuators * sizeof(int)));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment