Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Aug 2010 20:48:09 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r211592 - in stable/8: bin/sh tools/regression/bin/sh/expansion
Message-ID:  <201008212048.o7LKm9Zb080779@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Sat Aug 21 20:48:09 2010
New Revision: 211592
URL: http://svn.freebsd.org/changeset/base/211592

Log:
  MFC r211155: sh: Fix heap-based buffer overflow in pathname generation.
  
  The buffer for generated pathnames could be too small in some cases. It
  happened to be always at least PATH_MAX long, so there was never an overflow
  if the resulting pathnames would be usable.
  
  This bug may be abused if a script subjects input from an untrusted source
  to pathname generation, which a bad idea anyhow. Most shell scripts do not
  work on untrusted data. secteam@ says no advisory is necessary.
  
  PR:		bin/148733
  Reported by:	Changming Sun snnn119 at gmail com

Added:
  stable/8/tools/regression/bin/sh/expansion/pathname3.0
     - copied unchanged from r211155, head/tools/regression/bin/sh/expansion/pathname3.0
Modified:
  stable/8/bin/sh/expand.c
Directory Properties:
  stable/8/bin/sh/   (props changed)
  stable/8/tools/regression/bin/sh/   (props changed)

Modified: stable/8/bin/sh/expand.c
==============================================================================
--- stable/8/bin/sh/expand.c	Sat Aug 21 19:31:58 2010	(r211591)
+++ stable/8/bin/sh/expand.c	Sat Aug 21 20:48:09 2010	(r211592)
@@ -1074,8 +1074,8 @@ ifsbreakup(char *string, struct arglist 
  * should be escapes.  The results are stored in the list exparg.
  */
 
-STATIC char *expdir;
-
+STATIC char expdir[PATH_MAX];
+#define expdir_end (expdir + sizeof(expdir))
 
 STATIC void
 expandmeta(struct strlist *str, int flag __unused)
@@ -1098,14 +1098,7 @@ expandmeta(struct strlist *str, int flag
 		}
 		savelastp = exparg.lastp;
 		INTOFF;
-		if (expdir == NULL) {
-			int i = strlen(str->text);
-			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
-		}
-
 		expmeta(expdir, str->text);
-		ckfree(expdir);
-		expdir = NULL;
 		INTON;
 		if (exparg.lastp == savelastp) {
 			/*
@@ -1194,6 +1187,8 @@ expmeta(char *enddir, char *name)
 			*enddir++ = *p;
 			if (*p == '\0')
 				break;
+			if (enddir == expdir_end)
+				return;
 		}
 		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
 			addfname(expdir);
@@ -1208,6 +1203,8 @@ expmeta(char *enddir, char *name)
 			if (*p == CTLESC)
 				p++;
 			*enddir++ = *p++;
+			if (enddir == expdir_end)
+				return;
 		}
 	}
 	if (enddir == expdir) {
@@ -1241,15 +1238,17 @@ expmeta(char *enddir, char *name)
 		if (dp->d_name[0] == '.' && ! matchdot)
 			continue;
 		if (patmatch(start, dp->d_name, 0)) {
-			if (atend) {
-				scopy(dp->d_name, enddir);
+			if (enddir + dp->d_namlen + 1 > expdir_end)
+				continue;
+			memcpy(enddir, dp->d_name, dp->d_namlen + 1);
+			if (atend)
 				addfname(expdir);
-			} else {
-				for (p = enddir, q = dp->d_name;
-				     (*p++ = *q++) != '\0';)
+			else {
+				if (enddir + dp->d_namlen + 2 > expdir_end)
 					continue;
-				p[-1] = '/';
-				expmeta(p, endname);
+				enddir[dp->d_namlen] = '/';
+				enddir[dp->d_namlen + 1] = '\0';
+				expmeta(enddir + dp->d_namlen + 1, endname);
 			}
 		}
 	}

Copied: stable/8/tools/regression/bin/sh/expansion/pathname3.0 (from r211155, head/tools/regression/bin/sh/expansion/pathname3.0)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/tools/regression/bin/sh/expansion/pathname3.0	Sat Aug 21 20:48:09 2010	(r211592, copy of r211155, head/tools/regression/bin/sh/expansion/pathname3.0)
@@ -0,0 +1,29 @@
+# $FreeBSD$
+
+v=12345678
+v=$v$v$v$v
+v=$v$v$v$v
+v=$v$v$v$v
+v=$v$v$v$v
+v=$v$v$v$v
+# 8192 bytes
+v=${v##???}
+[ /*/$v = "/*/$v" ] || exit 1
+
+s=////
+s=$s$s$s$s
+s=$s$s$s$s
+s=$s$s$s$s
+s=$s$s$s$s
+# 1024 bytes
+s=${s##??????????}
+[ /var/empt[y]/$s/$v = "/var/empt[y]/$s/$v" ] || exit 2
+while [ ${#s} -lt 1034 ]; do
+	set -- /.${s}et[c]
+	[ ${#s} -gt 1018 ] || [ "$1" = /.${s}etc ] || exit 3
+	set -- /.${s}et[c]/
+	[ ${#s} -gt 1017 ] || [ "$1" = /.${s}etc/ ] || exit 4
+	set -- /.${s}et[c]/.
+	[ ${#s} -gt 1016 ] || [ "$1" = /.${s}etc/. ] || exit 5
+	s=$s/
+done



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008212048.o7LKm9Zb080779>