Blob Blame Raw
From 6149f39ada50f7ebc6b0cb7756490a0fea967bd1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Fri, 4 Jan 2013 13:33:11 +0100
Subject: [PATCH 1/2] Fix CVE-2012-6089

Upstream fix ported to 5.10.2:

From a9a6fc8a2a9cf3b9154b490a4b1ffaa8be4d723c Mon Sep 17 00:00:00 2001
From: Jan Wielemaker <J.Wielemaker@cs.vu.nl>
Date: Sun, 16 Dec 2012 18:13:17 +0100
Subject: [PATCH] FIXED: Possible buffer overrun in patch canonisation code.

Pushes pointers on an automatic array without checking for overflow.
Can be used for DoS attacks.  Will be extremely hard to make it execute
arbitrary code.
---
 src/pl-buffer.h |  2 ++
 src/pl-os.c     | 19 +++++++++++--------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/pl-buffer.h b/src/pl-buffer.h
index d4149c1..000bca5 100644
--- a/src/pl-buffer.h
+++ b/src/pl-buffer.h
@@ -79,6 +79,8 @@ void	growBuffer(Buffer b, size_t minfree);
 				  sizeof((b)->static_buffer))
 #define emptyBuffer(b)           ((b)->top  = (b)->base)
 #define isEmptyBuffer(b)         ((b)->top == (b)->base)
+#define popBuffer(b,type) \
+	((b)->top -= sizeof(type), *(type*)(b)->top)
 
 #define discardBuffer(b) \
 	do \
diff --git a/src/pl-os.c b/src/pl-os.c
index c6aaefc..4d008d6 100644
--- a/src/pl-os.c
+++ b/src/pl-os.c
@@ -1081,8 +1081,7 @@ cleanupExpand(void)
 char *
 canoniseFileName(char *path)
 { char *out = path, *in = path, *start = path;
-  char *osave[100];
-  int  osavep = 0;
+  tmp_buffer saveb;
 
 #ifdef O_HASDRIVES			/* C: */
   if ( in[1] == ':' && isLetter(in[0]) )
@@ -1110,7 +1109,8 @@ canoniseFileName(char *path)
     in += 2;
   if ( in[0] == '/' )
     *out++ = '/';
-  osave[osavep++] = out;
+  initBuffer(&saveb);
+  addBuffer(&saveb, out, char*);
 
   while(*in)
   { if (*in == '/')
@@ -1126,15 +1126,15 @@ canoniseFileName(char *path)
 	  }
 	  if ( in[2] == EOS )		/* delete trailing /. */
 	  { *out = EOS;
-	    return path;
+	    goto out;
 	  }
 	  if ( in[2] == '.' && (in[3] == '/' || in[3] == EOS) )
-	  { if ( osavep > 0 )		/* delete /foo/../ */
-	    { out = osave[--osavep];
+	  { if ( !isEmptyBuffer(&saveb) )		/* delete /foo/../ */
+	    { out = popBuffer(&saveb, char*);
 	      in += 3;
 	      if ( in[0] == EOS && out > start+1 )
 	      { out[-1] = EOS;		/* delete trailing / */
-		return path;
+		goto out;
 	      }
 	      goto again;
 	    } else if (	start[0] == '/' && out == start+1 )
@@ -1148,12 +1148,15 @@ canoniseFileName(char *path)
 	in++;
       if ( out > path && out[-1] != '/' )
 	*out++ = '/';
-      osave[osavep++] = out;
+      addBuffer(&saveb, out, char*);
     } else
       *out++ = *in++;
   }
   *out++ = *in++;
 
+out:
+  discardBuffer(&saveb);
+
   return path;
 }
 
-- 
1.7.11.7