Module Name:    src
Committed By:   riz
Date:           Thu Aug  5 01:46:31 UTC 2010

Modified Files:
        src/crypto/dist/ssh [netbsd-4-0]: sftp-glob.c sftp.c
        src/lib/libc/gen [netbsd-4-0]: glob.3 glob.c

Log Message:
Pull up following revision(s) (requested by christos in ticket #1399):
        lib/libc/gen/glob.c: patch
        lib/libc/gen/glob.3: revision 1.37 via patch
        crypto/dist/ssh/sftp.c: patch
        crypto/dist/ssh/sftp-glob.c: patch
Add GLOB_LIMIT to the glob calls to prevent DoS attacks.
Apply more limits to GLOB_LIMIT, number of stat(2) calls from me and number
of readdir(3) calls from Maksymilian Arciemowicz. Also reduce the memory
used by matches strings from Maksymilian Arciemowicz.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.13.12.1 src/crypto/dist/ssh/sftp-glob.c
cvs rdiff -u -r1.21 -r1.21.6.1 src/crypto/dist/ssh/sftp.c
cvs rdiff -u -r1.30 -r1.30.12.1 src/lib/libc/gen/glob.3
cvs rdiff -u -r1.18 -r1.18.10.1 src/lib/libc/gen/glob.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/crypto/dist/ssh/sftp-glob.c
diff -u src/crypto/dist/ssh/sftp-glob.c:1.13 src/crypto/dist/ssh/sftp-glob.c:1.13.12.1
--- src/crypto/dist/ssh/sftp-glob.c:1.13	Thu Sep 28 21:22:15 2006
+++ src/crypto/dist/ssh/sftp-glob.c	Thu Aug  5 01:46:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: sftp-glob.c,v 1.13 2006/09/28 21:22:15 christos Exp $	*/
+/*	$NetBSD: sftp-glob.c,v 1.13.12.1 2010/08/05 01:46:31 riz Exp $	*/
 /* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <[email protected]>
@@ -17,7 +17,7 @@
  */
 
 #include "includes.h"
-__RCSID("$NetBSD: sftp-glob.c,v 1.13 2006/09/28 21:22:15 christos Exp $");
+__RCSID("$NetBSD: sftp-glob.c,v 1.13.12.1 2010/08/05 01:46:31 riz Exp $");
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -121,5 +121,5 @@
 	memset(&cur, 0, sizeof(cur));
 	cur.conn = conn;
 
-	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
+	return(glob(pattern, flags|GLOB_LIMIT|GLOB_ALTDIRFUNC, errfunc, pglob));
 }

Index: src/crypto/dist/ssh/sftp.c
diff -u src/crypto/dist/ssh/sftp.c:1.21 src/crypto/dist/ssh/sftp.c:1.21.6.1
--- src/crypto/dist/ssh/sftp.c:1.21	Thu Sep 28 21:22:15 2006
+++ src/crypto/dist/ssh/sftp.c	Thu Aug  5 01:46:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: sftp.c,v 1.21 2006/09/28 21:22:15 christos Exp $	*/
+/*	$NetBSD: sftp.c,v 1.21.6.1 2010/08/05 01:46:31 riz Exp $	*/
 /* $OpenBSD: sftp.c,v 1.91 2006/08/03 03:34:42 deraadt Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <[email protected]>
@@ -17,7 +17,7 @@
  */
 
 #include "includes.h"
-__RCSID("$NetBSD: sftp.c,v 1.21 2006/09/28 21:22:15 christos Exp $");
+__RCSID("$NetBSD: sftp.c,v 1.21.6.1 2010/08/05 01:46:31 riz Exp $");
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/wait.h>
@@ -594,7 +594,7 @@
 
 	memset(&g, 0, sizeof(g));
 	debug3("Looking up %s", src);
-	if (glob(src, 0, NULL, &g)) {
+	if (glob(src, GLOB_LIMIT, NULL, &g)) {
 		error("File \"%s\" not found.", src);
 		err = -1;
 		goto out;

Index: src/lib/libc/gen/glob.3
diff -u src/lib/libc/gen/glob.3:1.30 src/lib/libc/gen/glob.3:1.30.12.1
--- src/lib/libc/gen/glob.3:1.30	Sun Mar 26 18:11:22 2006
+++ src/lib/libc/gen/glob.3	Thu Aug  5 01:46:31 2010
@@ -1,4 +1,4 @@
-.\"	$NetBSD: glob.3,v 1.30 2006/03/26 18:11:22 christos Exp $
+.\"	$NetBSD: glob.3,v 1.30.12.1 2010/08/05 01:46:31 riz Exp $
 .\"
 .\" Copyright (c) 1989, 1991, 1993, 1994
 .\"	The Regents of the University of California.  All rights reserved.
@@ -31,7 +31,7 @@
 .\"
 .\"     @(#)glob.3	8.3 (Berkeley) 4/16/94
 .\"
-.Dd March 22, 2006
+.Dd July 6, 2010
 .Dt GLOB 3
 .Os
 .Sh NAME
@@ -253,8 +253,13 @@
 .Ql ~
 to user name home directories.
 .It Dv GLOB_LIMIT
-Limit the amount of memory used by matches to
-.Li ARG_MAX .
+Limit the amount of memory used to store matched strings to
+.Li 64K ,
+the number of
+.Xr stat 2
+calls to 128, and the number of
+.Xr readdir 3
+calls to 16K.
 This option should be set for programs that can be coerced to a denial of
 service attack via patterns that expand to a very large number of matches,
 such as a long string of

Index: src/lib/libc/gen/glob.c
diff -u src/lib/libc/gen/glob.c:1.18 src/lib/libc/gen/glob.c:1.18.10.1
--- src/lib/libc/gen/glob.c:1.18	Fri Dec  1 18:57:29 2006
+++ src/lib/libc/gen/glob.c	Thu Aug  5 01:46:31 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: glob.c,v 1.18 2006/12/01 18:57:29 christos Exp $	*/
+/*	$NetBSD: glob.c,v 1.18.10.1 2010/08/05 01:46:31 riz Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93";
 #else
-__RCSID("$NetBSD: glob.c,v 1.18 2006/12/01 18:57:29 christos Exp $");
+__RCSID("$NetBSD: glob.c,v 1.18.10.1 2010/08/05 01:46:31 riz Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -82,6 +82,14 @@
 #define NO_GETPW_R
 #endif
 
+#define	GLOB_LIMIT_MALLOC	65536
+#define	GLOB_LIMIT_STAT		128
+#define	GLOB_LIMIT_READDIR	16384
+
+#define	GLOB_INDEX_MALLOC	0
+#define	GLOB_INDEX_STAT		1
+#define	GLOB_INDEX_READDIR	2
+
 /*
  * XXX: For NetBSD 1.4.x compatibility. (kill me l8r)
  */
@@ -145,7 +153,7 @@
 static DIR	*g_opendir(Char *, glob_t *);
 static Char	*g_strchr(const Char *, int);
 static int	 g_stat(Char *, __gl_stat_t *, glob_t *);
-static int	 glob0(const Char *, glob_t *);
+static int	 glob0(const Char *, glob_t *, size_t *);
 static int	 glob1(Char *, glob_t *, size_t *);
 static int	 glob2(Char *, Char *, Char *, Char *, glob_t *,
     size_t *);
@@ -153,8 +161,9 @@
     size_t *);
 static int	 globextend(const Char *, glob_t *, size_t *);
 static const Char *globtilde(const Char *, Char *, size_t, glob_t *);
-static int	 globexp1(const Char *, glob_t *);
-static int	 globexp2(const Char *, const Char *, glob_t *, int *);
+static int	 globexp1(const Char *, glob_t *, size_t *);
+static int	 globexp2(const Char *, const Char *, glob_t *, int *,
+    size_t *);
 static int	 match(Char *, Char *, Char *);
 #ifdef DEBUG
 static void	 qprintf(const char *, Char *);
@@ -167,6 +176,8 @@
 	const u_char *patnext;
 	int c;
 	Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
+	/* 0 = malloc(), 1 = stat(), 2 = readdir() */
+	size_t limit[] = { 0, 0, 0 };
 
 	_DIAGASSERT(pattern != NULL);
 
@@ -202,9 +213,9 @@
 	*bufnext = EOS;
 
 	if (flags & GLOB_BRACE)
-	    return globexp1(patbuf, pglob);
+	    return globexp1(patbuf, pglob, limit);
 	else
-	    return glob0(patbuf, pglob);
+	    return glob0(patbuf, pglob, limit);
 }
 
 /*
@@ -213,7 +224,7 @@
  * characters
  */
 static int
-globexp1(const Char *pattern, glob_t *pglob)
+globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
 {
 	const Char* ptr = pattern;
 	int rv;
@@ -223,13 +234,13 @@
 
 	/* Protect a single {}, for find(1), like csh */
 	if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
-		return glob0(pattern, pglob);
+		return glob0(pattern, pglob, limit);
 
 	while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
-		if (!globexp2(ptr, pattern, pglob, &rv))
+		if (!globexp2(ptr, pattern, pglob, &rv, limit))
 			return rv;
 
-	return glob0(pattern, pglob);
+	return glob0(pattern, pglob, limit);
 }
 
 
@@ -239,7 +250,8 @@
  * If it fails then it tries to glob the rest of the pattern and returns.
  */
 static int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
+    size_t *limit)
 {
 	int     i;
 	Char   *lm, *ls;
@@ -284,7 +296,7 @@
 		 * we use `pattern', not `patbuf' here so that that
 		 * unbalanced braces are passed to the match
 		 */
-		*rv = glob0(pattern, pglob);
+		*rv = glob0(pattern, pglob, limit);
 		return 0;
 	}
 
@@ -331,7 +343,7 @@
 #ifdef DEBUG
 				qprintf("globexp2:", patbuf);
 #endif
-				*rv = globexp1(patbuf, pglob);
+				*rv = globexp1(patbuf, pglob, limit);
 
 				/* move after the comma, to the next string */
 				pl = pm + 1;
@@ -444,13 +456,12 @@
  * to find no matches.
  */
 static int
-glob0(const Char *pattern, glob_t *pglob)
+glob0(const Char *pattern, glob_t *pglob, size_t *limit)
 {
 	const Char *qpatnext;
 	int c, error;
 	__gl_size_t oldpathc;
 	Char *bufnext, patbuf[MAXPATHLEN+1];
-	size_t limit = 0;
 
 	_DIAGASSERT(pattern != NULL);
 	_DIAGASSERT(pglob != NULL);
@@ -513,7 +524,7 @@
 	qprintf("glob0:", patbuf);
 #endif
 
-	if ((error = glob1(patbuf, pglob, &limit)) != 0)
+	if ((error = glob1(patbuf, pglob, limit)) != 0)
 		return error;
 
 	if (pglob->gl_pathc == oldpathc) {	
@@ -527,7 +538,7 @@
 		if ((pglob->gl_flags & GLOB_NOCHECK) ||
 		    ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR))
 		     == GLOB_NOMAGIC)) {
-			return globextend(pattern, pglob, &limit);
+			return globextend(pattern, pglob, limit);
 		} else {
 			return GLOB_NOMATCH;
 		}
@@ -598,6 +609,13 @@
 			if (g_lstat(pathbuf, &sb, pglob))
 				return 0;
 		
+			if ((pglob->gl_flags & GLOB_LIMIT) &&
+			    limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) {
+				errno = 0;
+				*pathend++ = SEP;
+				*pathend = EOS;
+				return GLOB_NOSPACE;
+			}
 			if (((pglob->gl_flags & GLOB_MARK) &&
 			    pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
 			    (S_ISLNK(sb.st_mode) &&
@@ -706,6 +724,14 @@
 		     dc <= pathlim && (*dc++ = *sc++) != EOS;)
 			continue;
 
+		if ((pglob->gl_flags & GLOB_LIMIT) &&
+		    limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) {
+			errno = 0;
+			*pathend++ = SEP;
+			*pathend = EOS;
+			return GLOB_NOSPACE;
+		}
+
 		/*
 		 * Have we filled the buffer without seeing EOS?
 		 */
@@ -729,7 +755,8 @@
 			*pathend = EOS;
 			continue;
 		}
-		error = glob2(pathbuf, --dc, pathlim, restpattern, pglob, limit);
+		error = glob2(pathbuf, --dc, pathlim, restpattern, pglob,
+		    limit);
 		if (error)
 			break;
 	}
@@ -791,7 +818,7 @@
 	for (p = path; *p++;)
 		continue;
 	len = (size_t)(p - path);
-	*limit += len;
+	limit[GLOB_INDEX_MALLOC] += len;
 	if ((copy = malloc(len)) != NULL) {
 		if (g_Ctoc(path, copy, len)) {
 			free(copy);
@@ -801,7 +828,8 @@
 	}
 	pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
 
-	if ((pglob->gl_flags & GLOB_LIMIT) && (newsize + *limit) >= ARG_MAX) {
+	if ((pglob->gl_flags & GLOB_LIMIT) &&
+	    (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) {
 		errno = 0;
 		return GLOB_NOSPACE;
 	}

Reply via email to