From 164bf4dfe839b1cc75cdeee378a243d04a8200e4 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat, 2 Mar 2013 13:18:48 -0800
Subject: [PATCH] integer overflows in TransFileName() [CVE-2013-1981 9/13]

When trying to process file paths the tokens %H, %L, & %S are expanded
to $HOME, the standard compose file path & the xlocaledir path.
If enough of these tokens are repeated and values like $HOME are set to
very large values, the calculation of the total string size required to
hold the expanded path can overflow, resulting in allocating a smaller
string than the amount of data we'll write to it.

Simply restrict all of these values, and the total path size to PATH_MAX,
because really, that's all you should need for a filename path.

Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Matthieu Herrb <matthieu.herrb@laas.fr>
---
 modules/im/ximcp/Makefile.am |  1 +
 modules/im/ximcp/imLcPrs.c   | 45 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 35 insertions(+), 11 deletions(-)

Index: libX11-1.1.5/modules/im/ximcp/imLcPrs.c
===================================================================
--- libX11-1.1.5.orig/modules/im/ximcp/imLcPrs.c
+++ libX11-1.1.5/modules/im/ximcp/imLcPrs.c
@@ -44,6 +44,7 @@ OR PERFORMANCE OF THIS SOFTWARE.
 #include <sys/stat.h>
 #include <stdio.h>
 #include <limits.h>
+#include "pathmax.h"
 
 extern int _Xmbstowcs(
     wchar_t	*wstr,
@@ -305,8 +306,8 @@ static char*
 TransFileName(Xim im, char *name)
 {
    char *home = NULL, *lcCompose = NULL;
-   char *i = name, *ret, *j;
-   int l = 0;
+   char *i = name, *ret = NULL, *j;
+   size_t l = 0;
 
    while (*i) {
       if (*i == '%') {
@@ -316,25 +317,39 @@ TransFileName(Xim im, char *name)
                  l++;
    	         break;
    	      case 'H':
-   	         home = getenv("HOME");
-   	         if (home)
-                     l += strlen(home);
+		 if (home == NULL)
+		      home = getenv("HOME");
+		 if (home) {
+		      size_t Hsize = strlen(home);
+		      if (Hsize > PATH_MAX)
+			  /* your home directory length is ridiculous */
+			  goto end;
+		      l += Hsize;
+		 }
    	         break;
    	      case 'L':
                  lcCompose = _XlcFileName(im->core.lcd, COMPOSE_FILE);
-                 if (lcCompose)
-                     l += strlen(lcCompose);
+		 if (lcCompose) {
+		      size_t Lsize = strlen(lcCompose);
+		      if (Lsize > PATH_MAX)
+			  /* your compose pathname length is ridiculous */
+			  goto end;
+		      l += Lsize;
+		 }
    	         break;
    	  }
       } else {
       	  l++;
       }
       i++;
+      if (l > PATH_MAX)
+	  /* your expanded path length is ridiculous */
+	  goto end;
    }
 
    j = ret = Xmalloc(l+1);
    if (ret == NULL)
-      return ret;
+      goto end;
    i = name;
    while (*i) {
       if (*i == '%') {
@@ -353,7 +368,6 @@ TransFileName(Xim im, char *name)
    	         if (lcCompose) {
                     strcpy(j, lcCompose);
                     j += strlen(lcCompose);
-                    Xfree(lcCompose);
                  }
    	         break;
    	  }
@@ -363,6 +377,8 @@ TransFileName(Xim im, char *name)
       }
    }
    *j = '\0';
+end:
+   Xfree(lcCompose);
    return ret;
 }
 
Index: libX11-1.1.5/src/pathmax.h
===================================================================
--- /dev/null
+++ libX11-1.1.5/src/pathmax.h
@@ -0,0 +1,81 @@
+
+/***********************************************************
+
+Copyright 1987, 1988, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice 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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Provides a single definition of PATH_MAX instead of replicating this mess
+ * in multiple files
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/Xos.h>
+
+#ifndef X_NOT_POSIX
+#ifdef _POSIX_SOURCE
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+#ifndef PATH_MAX
+#ifdef WIN32
+#define PATH_MAX 512
+#else
+#include <sys/param.h>
+#endif
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
