Author: jilles
Date: Tue Aug 10 22:45:59 2010
New Revision: 211155
URL: http://svn.freebsd.org/changeset/base/211155

Log:
  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
  MFC after:    10 days

Added:
  head/tools/regression/bin/sh/expansion/pathname3.0   (contents, props changed)
Modified:
  head/bin/sh/expand.c

Modified: head/bin/sh/expand.c
==============================================================================
--- head/bin/sh/expand.c        Tue Aug 10 19:50:51 2010        (r211154)
+++ head/bin/sh/expand.c        Tue Aug 10 22:45:59 2010        (r211155)
@@ -1082,8 +1082,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)
@@ -1106,14 +1106,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) {
                        /*
@@ -1202,6 +1195,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);
@@ -1216,6 +1211,8 @@ expmeta(char *enddir, char *name)
                        if (*p == CTLESC)
                                p++;
                        *enddir++ = *p++;
+                       if (enddir == expdir_end)
+                               return;
                }
        }
        if (enddir == expdir) {
@@ -1249,15 +1246,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);
                        }
                }
        }

Added: head/tools/regression/bin/sh/expansion/pathname3.0
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/regression/bin/sh/expansion/pathname3.0  Tue Aug 10 22:45:59 
2010        (r211155)
@@ -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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to