2cdf25d
From 6970d8c3c8b96b294159b4029c1428813568e20b Mon Sep 17 00:00:00 2001
2cdf25d
From: Dave Airlie <airlied@redhat.com>
2cdf25d
Date: Sat, 19 Jan 2008 06:37:58 +1000
2cdf25d
Subject: [PATCH] CVE-2007-6429: EVI and MIT-SHM Vunerability updated patch
d134ef1
d134ef1
---
2cdf25d
 Xext/EVI.c       |   15 ++++++++++++++-
2cdf25d
 Xext/sampleEVI.c |   29 ++++++++++++++++++++++++-----
2cdf25d
 Xext/shm.c       |   52 ++++++++++++++++++++++++++++++++++++++++++++--------
2cdf25d
 3 files changed, 82 insertions(+), 14 deletions(-)
d134ef1
2cdf25d
diff --git a/Xext/EVI.c b/Xext/EVI.c
2cdf25d
index 4bd050c..a637bae 100644
2cdf25d
--- a/Xext/EVI.c
2cdf25d
+++ b/Xext/EVI.c
2cdf25d
@@ -34,6 +34,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
2cdf25d
 #include <X11/extensions/XEVIstr.h>
2cdf25d
 #include "EVIstruct.h"
2cdf25d
 #include "modinit.h"
2cdf25d
+#include "scrnintstr.h"
2cdf25d
 
2cdf25d
 static EviPrivPtr eviPriv;
2cdf25d
 
2cdf25d
@@ -84,10 +85,22 @@ ProcEVIGetVisualInfo(ClientPtr client)
2cdf25d
 {
2cdf25d
     REQUEST(xEVIGetVisualInfoReq);
2cdf25d
     xEVIGetVisualInfoReply rep;
2cdf25d
-    int n, n_conflict, n_info, sz_info, sz_conflict;
2cdf25d
+    int i, n, n_conflict, n_info, sz_info, sz_conflict;
2cdf25d
     VisualID32 *conflict;
2cdf25d
+    unsigned int total_visuals = 0;
2cdf25d
     xExtendedVisualInfo *eviInfo;
2cdf25d
     int status;
2cdf25d
+
2cdf25d
+    /*
2cdf25d
+     * do this first, otherwise REQUEST_FIXED_SIZE can overflow.  we assume
2cdf25d
+     * here that you don't have more than 2^32 visuals over all your screens;
2cdf25d
+     * this seems like a safe assumption.
2cdf25d
+     */
2cdf25d
+    for (i = 0; i < screenInfo.numScreens; i++)
2cdf25d
+	total_visuals += screenInfo.screens[i]->numVisuals;
2cdf25d
+    if (stuff->n_visual > total_visuals)
2cdf25d
+	return BadValue;
2cdf25d
+
2cdf25d
     REQUEST_FIXED_SIZE(xEVIGetVisualInfoReq, stuff->n_visual * sz_VisualID32);
2cdf25d
     status = eviPriv->getVisualInfo((VisualID32 *)&stuff[1], (int)stuff->n_visual,
2cdf25d
 		&eviInfo, &n_info, &conflict, &n_conflict);
2cdf25d
diff --git a/Xext/sampleEVI.c b/Xext/sampleEVI.c
2cdf25d
index 7508aa7..b8f39c7 100644
2cdf25d
--- a/Xext/sampleEVI.c
2cdf25d
+++ b/Xext/sampleEVI.c
2cdf25d
@@ -34,6 +34,13 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
ac5c859
 #include <X11/extensions/XEVIstr.h>
ac5c859
 #include "EVIstruct.h"
ac5c859
 #include "scrnintstr.h"
ac5c859
+
ac5c859
+#if HAVE_STDINT_H
ac5c859
+#include <stdint.h>
277f8aa
+#elif !defined(INT_MAX)
277f8aa
+#define INT_MAX 0x7fffffff
ac5c859
+#endif
ac5c859
+
ac5c859
 static int sampleGetVisualInfo(
ac5c859
     VisualID32 *visual,
ac5c859
     int n_visual,
2cdf25d
@@ -42,24 +49,36 @@ static int sampleGetVisualInfo(
ac5c859
     VisualID32 **conflict_rn,
ac5c859
     int *n_conflict_rn)
ac5c859
 {
ac5c859
-    int max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens;
ac5c859
+    unsigned int max_sz_evi;
ac5c859
     VisualID32 *temp_conflict;
ac5c859
     xExtendedVisualInfo *evi;
ac5c859
-    int max_visuals = 0, max_sz_conflict, sz_conflict = 0;
ac5c859
+    unsigned int max_visuals = 0, max_sz_conflict, sz_conflict = 0;
ac5c859
     register int visualI, scrI, sz_evi = 0, conflictI, n_conflict;
ac5c859
-    *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi);
ac5c859
-    if (!*evi_rn)
ac5c859
-         return BadAlloc;
ac5c859
+
ac5c859
+    if (n_visual > UINT32_MAX/(sz_xExtendedVisualInfo * screenInfo.numScreens))
ac5c859
+	return BadAlloc;
ac5c859
+    max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens;
ac5c859
+    
ac5c859
     for (scrI = 0; scrI < screenInfo.numScreens; scrI++) {
ac5c859
         if (screenInfo.screens[scrI]->numVisuals > max_visuals)
ac5c859
             max_visuals = screenInfo.screens[scrI]->numVisuals;
ac5c859
     }
ac5c859
+
ac5c859
+    if (n_visual > UINT32_MAX/(sz_VisualID32 * screenInfo.numScreens 
ac5c859
+			       * max_visuals)) 
ac5c859
+	return BadAlloc;
ac5c859
     max_sz_conflict = n_visual * sz_VisualID32 * screenInfo.numScreens * max_visuals;
ac5c859
+
ac5c859
+    *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi);
ac5c859
+    if (!*evi_rn)
ac5c859
+         return BadAlloc;
ac5c859
+
ac5c859
     temp_conflict = (VisualID32 *)xalloc(max_sz_conflict);
ac5c859
     if (!temp_conflict) {
ac5c859
         xfree(*evi_rn);
ac5c859
         return BadAlloc;
ac5c859
     }
ac5c859
+
ac5c859
     for (scrI = 0; scrI < screenInfo.numScreens; scrI++) {
ac5c859
         for (visualI = 0; visualI < n_visual; visualI++) {
ac5c859
 	    evi[sz_evi].core_visual_id = visual[visualI];
2cdf25d
diff --git a/Xext/shm.c b/Xext/shm.c
2cdf25d
index e3d7a23..0f7a7eb 100644
2cdf25d
--- a/Xext/shm.c
2cdf25d
+++ b/Xext/shm.c
2cdf25d
@@ -757,6 +757,8 @@ ProcPanoramiXShmCreatePixmap(
2cdf25d
     int i, j, result, rc;
e002a5a
     ShmDescPtr shmdesc;
e002a5a
     REQUEST(xShmCreatePixmapReq);
e002a5a
+    unsigned int width, height, depth;
e002a5a
+    unsigned long size;
e002a5a
     PanoramiXRes *newPix;
e002a5a
 
e002a5a
     REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
2cdf25d
@@ -770,11 +772,18 @@ ProcPanoramiXShmCreatePixmap(
2cdf25d
 	return rc;
2cdf25d
 
e002a5a
     VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
e002a5a
-    if (!stuff->width || !stuff->height)
e002a5a
+
e002a5a
+    width = stuff->width;
e002a5a
+    height = stuff->height;
e002a5a
+    depth = stuff->depth;
e002a5a
+    if (!width || !height || !depth)
e002a5a
     {
e002a5a
 	client->errorValue = 0;
e002a5a
         return BadValue;
e002a5a
     }
e002a5a
+    if (width > 32767 || height > 32767)
e002a5a
+        return BadAlloc;
e002a5a
+
e002a5a
     if (stuff->depth != 1)
e002a5a
     {
e002a5a
         pDepth = pDraw->pScreen->allowedDepths;
2cdf25d
@@ -784,10 +793,19 @@ ProcPanoramiXShmCreatePixmap(
277f8aa
 	client->errorValue = stuff->depth;
e002a5a
         return BadValue;
e002a5a
     }
277f8aa
+
e002a5a
 CreatePmap:
e002a5a
-    VERIFY_SHMSIZE(shmdesc, stuff->offset,
e002a5a
-		   PixmapBytePad(stuff->width, stuff->depth) * stuff->height,
e002a5a
-		   client);
277f8aa
+    /* now w/h/d are valid; but will they overflow a 32-bit pointer? */
277f8aa
+    size = PixmapBytePad(width, depth) * height;
277f8aa
+    if (sizeof(void *) == 4 && BitsPerPixel(depth) > 8) {
277f8aa
+        if (size < width * height)
277f8aa
+            return BadAlloc;
277f8aa
+        /* thankfully, offset is unsigned */
277f8aa
+        if (stuff->offset + size < size)
277f8aa
+            return BadAlloc;
277f8aa
+    }
277f8aa
+
e002a5a
+    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
e002a5a
 
e002a5a
     if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes))))
e002a5a
 	return BadAlloc;
2cdf25d
@@ -1086,6 +1104,8 @@ ProcShmCreatePixmap(client)
2cdf25d
     register int i, rc;
e002a5a
     ShmDescPtr shmdesc;
e002a5a
     REQUEST(xShmCreatePixmapReq);
e002a5a
+    unsigned int width, height, depth;
e002a5a
+    unsigned long size;
e002a5a
 
e002a5a
     REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
e002a5a
     client->errorValue = stuff->pid;
2cdf25d
@@ -1098,11 +1118,18 @@ ProcShmCreatePixmap(client)
2cdf25d
 	return rc;
2cdf25d
 
e002a5a
     VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
e002a5a
-    if (!stuff->width || !stuff->height)
e002a5a
+    
e002a5a
+    width = stuff->width;
e002a5a
+    height = stuff->height;
e002a5a
+    depth = stuff->depth;
e002a5a
+    if (!width || !height || !depth)
e002a5a
     {
e002a5a
 	client->errorValue = 0;
e002a5a
         return BadValue;
e002a5a
     }
e002a5a
+    if (width > 32767 || height > 32767)
e002a5a
+	return BadAlloc;
e002a5a
+
e002a5a
     if (stuff->depth != 1)
e002a5a
     {
e002a5a
         pDepth = pDraw->pScreen->allowedDepths;
2cdf25d
@@ -1112,10 +1139,19 @@ ProcShmCreatePixmap(client)
277f8aa
 	client->errorValue = stuff->depth;
e002a5a
         return BadValue;
e002a5a
     }
277f8aa
+
e002a5a
 CreatePmap:
e002a5a
-    VERIFY_SHMSIZE(shmdesc, stuff->offset,
e002a5a
-		   PixmapBytePad(stuff->width, stuff->depth) * stuff->height,
e002a5a
-		   client);
277f8aa
+    /* now w/h/d are valid; but will they overflow a 32-bit pointer? */
277f8aa
+    size = PixmapBytePad(width, depth) * height;
277f8aa
+    if (sizeof(void *) == 4 && BitsPerPixel(depth) > 8) {
277f8aa
+        if (size < width * height)
277f8aa
+            return BadAlloc;
277f8aa
+        /* thankfully, offset is unsigned */
277f8aa
+        if (stuff->offset + size < size)
277f8aa
+            return BadAlloc;
277f8aa
+    }
277f8aa
+
e002a5a
+    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
e002a5a
     pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)(
e002a5a
 			    pDraw->pScreen, stuff->width,
e002a5a
 			    stuff->height, stuff->depth,
2cdf25d
-- 
2cdf25d
1.5.3.6
2cdf25d