From 99c644fc8488657bdd106717df7446d606f9ef22 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 8 Mar 2013 19:55:55 -0800
Subject: [PATCH] integer overflow in XineramaQueryScreens() [CVE-2013-1985]

If the reported number of screens is too large, the calculations to
allocate memory for them may overflow, leaving us writing beyond the
bounds of the allocation.

Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
 src/Xinerama.c | 44 ++++++++++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 16 deletions(-)

Index: libXinerama-1.0.3/src/Xinerama.c
===================================================================
--- libXinerama-1.0.3.orig/src/Xinerama.c
+++ libXinerama-1.0.3/src/Xinerama.c
@@ -34,6 +34,7 @@ Equipment Corporation.
 #include <X11/extensions/panoramiXext.h>
 #include <X11/extensions/panoramiXproto.h>
 #include <X11/extensions/Xinerama.h>
+#include "eat.h"
 
 
 static XExtensionInfo _panoramiX_ext_info_data;
@@ -290,24 +291,36 @@ XineramaQueryScreens(
 	return NULL;
     }
 
-    if(rep.number) {
-	if((scrnInfo = Xmalloc(sizeof(XineramaScreenInfo) * rep.number))) {
-	    xXineramaScreenInfo scratch;
-	    int i;
-
-	    for(i = 0; i < rep.number; i++) {
-		_XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo);
-		scrnInfo[i].screen_number = i;
-		scrnInfo[i].x_org 	  = scratch.x_org;
-		scrnInfo[i].y_org 	  = scratch.y_org;
-		scrnInfo[i].width 	  = scratch.width;
-		scrnInfo[i].height 	  = scratch.height;
-	    }
-
-	    *number = rep.number;
-	} else
-	    _XEatData(dpy, rep.length << 2);
+    /*
+     * rep.number is a CARD32 so could be as large as 2^32
+     * The X11 protocol limits the total screen size to 64k x 64k,
+     * and no screen can be smaller than a pixel.  While technically
+     * that means we could theoretically reach 2^32 screens, and that's
+     * not even taking overlap into account, Xorg is currently limited
+     * to 16 screens, and few known servers have a much higher limit,
+     * so 1024 seems more than enough to prevent both integer overflow
+     * and insane X server responses causing massive memory allocation.
+     */
+    if ((rep.number > 0) && (rep.number <= 1024))
+       scrnInfo = Xmalloc(sizeof(XineramaScreenInfo) * rep.number);
+    if (scrnInfo != NULL) {
+       int i;
+
+       for (i = 0; i < rep.number; i++) {
+	   xXineramaScreenInfo scratch;
+
+	   _XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo);
+
+	   scrnInfo[i].screen_number = i;
+	   scrnInfo[i].x_org   = scratch.x_org;
+	   scrnInfo[i].y_org   = scratch.y_org;
+	   scrnInfo[i].width   = scratch.width;
+	   scrnInfo[i].height  = scratch.height;
+       }
+
+       *number = rep.number;
     } else {
+	_XEatDataWords(dpy, rep.length);
 	*number = 0;
     }
 
Index: libXinerama-1.0.3/src/eat.h
===================================================================
--- /dev/null
+++ libXinerama-1.0.3/src/eat.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef HAVE__XEATDATAWORDS
+#include <X11/Xmd.h>  /* for LONG64 on 64-bit platforms */
+#include <limits.h>
+
+static inline void _XEatDataWords(Display *dpy, unsigned long n)
+{
+# ifndef LONG64
+    if (n >= (ULONG_MAX >> 2))
+        _XIOError(dpy);
+# endif
+    _XEatData (dpy, n << 2);
+}
+#endif
