From 98861f0e2b4d7045430e7839a3aca12c6beaed56 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sat, 9 Mar 2013 22:55:23 -0800 Subject: [PATCH 12/16] 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 Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer (cherry picked from commit 528419b9ef437e7eeafb41bf45e8ff7d818bd845) (cherry picked from commit cabe9d3f00a28aa05dcb14c114196a30278b5e22) --- src/XISelEv.c | 25 +++++++++++++++++++------ 1 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/XISelEv.c b/src/XISelEv.c index bd5a29a..008ec60 100644 --- a/src/XISelEv.c +++ b/src/XISelEv.c @@ -39,6 +39,7 @@ in this Software without prior written authorization from the author. #include #include #include "XIint.h" +#include int XISelectEvents(Display* dpy, Window win, XIEventMask* masks, int num_masks) @@ -98,13 +99,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); @@ -126,11 +128,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 @@ -145,8 +152,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++; } -- 1.7.7.1