summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@oracle.com>2013-03-09 22:55:23 -0800
committerAlan Coopersmith <alan.coopersmith@oracle.com>2013-05-23 08:13:26 -0700
commit528419b9ef437e7eeafb41bf45e8ff7d818bd845 (patch)
treed3cb5f094541bbfd954790eb05a3469b608d1627
parent242f92b490a695fbab244af5bad11b71f897c732 (diff)
downloadxorg-lib-libXi-528419b9ef437e7eeafb41bf45e8ff7d818bd845.tar.gz
integer overflow in XIGetSelectedEvents() [CVE-2013-1984 6/8]
If the number of events or masks reported by the server is large enough that it overflows when multiplied by the size of the appropriate struct, or the sizes overflow as they are totaled up, then memory corruption can occur when more bytes are copied from the X server reply than the size of the buffer we allocated to hold them. v2: check that reply size fits inside the data read from the server, so that we don't read out of bounds either Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com> Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r--src/XISelEv.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/XISelEv.c b/src/XISelEv.c
index f871222..0471bef 100644
--- a/src/XISelEv.c
+++ b/src/XISelEv.c
@@ -42,6 +42,7 @@ in this Software without prior written authorization from the author.
#include <X11/extensions/ge.h>
#include <X11/extensions/geproto.h>
#include "XIint.h"
+#include <limits.h>
int
XISelectEvents(Display* dpy, Window win, XIEventMask* masks, int num_masks)
@@ -101,13 +102,14 @@ out:
XIEventMask*
XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
{
- int i, len = 0;
+ unsigned int i, len = 0;
unsigned char *mask;
XIEventMask *mask_out = NULL;
xXIEventMask *mask_in = NULL, *mi;
xXIGetSelectedEventsReq *req;
xXIGetSelectedEventsReply reply;
XExtDisplayInfo *info = XInput_find_display(dpy);
+ size_t rbytes;
*num_masks_return = -1;
LockDisplay(dpy);
@@ -129,11 +131,16 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
goto out;
}
- mask_in = Xmalloc(reply.length * 4);
- if (!mask_in)
+ if (reply.length < (INT_MAX >> 2)) {
+ rbytes = (unsigned long) reply.length << 2;
+ mask_in = Xmalloc(rbytes);
+ }
+ if (!mask_in) {
+ _XEatDataWords(dpy, reply.length);
goto out;
+ }
- _XRead(dpy, (char*)mask_in, reply.length * 4);
+ _XRead(dpy, (char*)mask_in, rbytes);
/*
* This function takes interleaved xXIEventMask structs & masks off
@@ -148,8 +155,14 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return)
for (i = 0, mi = mask_in; i < reply.num_masks; i++)
{
- len += mi->mask_len * 4;
- mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4);
+ unsigned int mask_bytes = mi->mask_len * 4;
+ len += mask_bytes;
+ if (len > INT_MAX)
+ goto out;
+ if ((sizeof(xXIEventMask) + mask_bytes) > rbytes)
+ goto out;
+ rbytes -= (sizeof(xXIEventMask) + mask_bytes);
+ mi = (xXIEventMask*)((char*)mi + mask_bytes);
mi++;
}