From 62c1e47de0448242a0dd1f5226be93f92a06824f Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 10 Mar 2013 00:16:22 -0800 Subject: sign extension issue in XListInputDevices() [CVE-2013-1995] nptr is (signed) char, which can be negative, and will sign extend when added to the int size, which means size can be subtracted from, leading to allocating too small a buffer to hold the data being copied from the X server's reply. v2: check that string size fits inside the data read from the server, so that we don't read out of bounds either Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer (cherry picked from commit 81b4df8ac6aa1520c41c3526961014a6f115cc46) --- src/XListDev.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/XListDev.c b/src/XListDev.c index 71dbd95..8d0bdf6 100644 --- a/src/XListDev.c +++ b/src/XListDev.c @@ -73,7 +73,7 @@ static int pad_to_xid(int base_size) return ((base_size + padsize - 1)/padsize) * padsize; } -static int +static size_t SizeClassInfo(xAnyClassPtr *any, int num_classes) { int size = 0; @@ -169,7 +169,7 @@ XListInputDevices( register Display *dpy, int *ndevices) { - int size; + size_t size; xListInputDevicesReq *req; xListInputDevicesReply rep; xDeviceInfo *list, *slist = NULL; @@ -177,7 +177,7 @@ XListInputDevices( XDeviceInfo *clist = NULL; xAnyClassPtr any, sav_any; XAnyClassPtr Any; - char *nptr, *Nptr; + unsigned char *nptr, *Nptr; int i; unsigned long rlen; XExtDisplayInfo *info = XInput_find_display(dpy); @@ -216,9 +216,12 @@ XListInputDevices( size += SizeClassInfo(&any, (int)list->num_classes); } - for (i = 0, nptr = (char *)any; i < *ndevices; i++) { + Nptr = ((unsigned char *)list) + rlen + 1; + for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) { size += *nptr + 1; nptr += (*nptr + 1); + if (nptr > Nptr) + goto out; } clist = (XDeviceInfoPtr) Xmalloc(size); @@ -244,8 +247,8 @@ XListInputDevices( } clist = sclist; - nptr = (char *)any; - Nptr = (char *)Any; + nptr = (unsigned char *)any; + Nptr = (unsigned char *)Any; for (i = 0; i < *ndevices; i++, clist++) { clist->name = (char *)Nptr; memcpy(Nptr, nptr + 1, *nptr); @@ -255,6 +258,7 @@ XListInputDevices( } } + out: XFree((char *)slist); UnlockDisplay(dpy); SyncHandle(); -- cgit v1.2.1