Module Name:    src
Committed By:   riz
Date:           Mon Jul 19 18:14:09 UTC 2010

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

Log Message:
Pull up following revision(s) (requested by christos in ticket #1430):
        lib/libc/gen/glob.c: revision 1.25
        lib/libc/gen/glob.c: revision 1.26
        lib/libc/gen/glob.3: revision 1.37
        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.
Avoid DoS attacks for patterns that have braces. Noted by Maksymilian
Arciemowicz.
XXX: Pullup to 5.x


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.13.24.1 src/crypto/dist/ssh/sftp-glob.c
cvs rdiff -u -r1.23 -r1.23.8.1 src/crypto/dist/ssh/sftp.c
cvs rdiff -u -r1.32 -r1.32.8.1 src/lib/libc/gen/glob.3
cvs rdiff -u -r1.23 -r1.23.4.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.24.1
--- src/crypto/dist/ssh/sftp-glob.c:1.13	Thu Sep 28 21:22:15 2006
+++ src/crypto/dist/ssh/sftp-glob.c	Mon Jul 19 18:14:09 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.24.1 2010/07/19 18:14:09 riz Exp $	*/
 /* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <d...@openbsd.org>
@@ -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.24.1 2010/07/19 18:14:09 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_ALTDIRFUNC|GLOB_LIMIT, errfunc, pglob));
 }

Index: src/crypto/dist/ssh/sftp.c
diff -u src/crypto/dist/ssh/sftp.c:1.23 src/crypto/dist/ssh/sftp.c:1.23.8.1
--- src/crypto/dist/ssh/sftp.c:1.23	Sun Apr  6 23:38:19 2008
+++ src/crypto/dist/ssh/sftp.c	Mon Jul 19 18:14:09 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: sftp.c,v 1.23 2008/04/06 23:38:19 christos Exp $	*/
+/*	$NetBSD: sftp.c,v 1.23.8.1 2010/07/19 18:14:09 riz Exp $	*/
 /* $OpenBSD: sftp.c,v 1.99 2008/01/20 00:38:30 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <d...@openbsd.org>
@@ -17,7 +17,7 @@
  */
 
 #include "includes.h"
-__RCSID("$NetBSD: sftp.c,v 1.23 2008/04/06 23:38:19 christos Exp $");
+__RCSID("$NetBSD: sftp.c,v 1.23.8.1 2010/07/19 18:14:09 riz Exp $");
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/wait.h>
@@ -521,7 +521,7 @@
 
 	memset(&g, 0, sizeof(g));
 	debug3("Looking up %s", src);
-	if (glob(src, GLOB_NOCHECK, NULL, &g)) {
+	if (glob(src, GLOB_NOCHECK|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.32 src/lib/libc/gen/glob.3:1.32.8.1
--- src/lib/libc/gen/glob.3:1.32	Fri Feb 22 18:33:51 2008
+++ src/lib/libc/gen/glob.3	Mon Jul 19 18:14:09 2010
@@ -1,4 +1,4 @@
-.\"	$NetBSD: glob.3,v 1.32 2008/02/22 18:33:51 christos Exp $
+.\"	$NetBSD: glob.3,v 1.32.8.1 2010/07/19 18:14:09 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 February 22, 2008
+.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.23 src/lib/libc/gen/glob.c:1.23.4.1
--- src/lib/libc/gen/glob.c:1.23	Mon May 26 13:06:38 2008
+++ src/lib/libc/gen/glob.c	Mon Jul 19 18:14:08 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: glob.c,v 1.23 2008/05/26 13:06:38 ad Exp $	*/
+/*	$NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 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.23 2008/05/26 13:06:38 ad Exp $");
+__RCSID("$NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -87,10 +87,13 @@
 #define NO_GETPW_R
 #endif
 
-#if !defined(ARG_MAX)
-#include <limits.h>
-#define	ARG_MAX	_POSIX_ARG_MAX
-#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)
@@ -155,7 +158,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 *);
@@ -163,8 +166,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 *);
@@ -177,6 +181,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);
 
@@ -212,9 +218,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);
 }
 
 /*
@@ -223,7 +229,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;
@@ -233,13 +239,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);
 }
 
 
@@ -249,7 +255,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;
@@ -294,7 +301,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;
 	}
 
@@ -341,7 +348,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;
@@ -454,13 +461,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);
@@ -523,7 +529,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) {	
@@ -537,7 +543,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;
 		}
@@ -610,6 +616,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) &&
@@ -726,6 +739,14 @@
 		u_char *sc;
 		Char *dc;
 
+		if ((pglob->gl_flags & GLOB_LIMIT) &&
+		    limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) {
+			errno = 0;
+			*pathend++ = SEP;
+			*pathend = EOS;
+			return GLOB_NOSPACE;
+		}
+
 		/*
 		 * Initial DOT must be matched literally, unless we have
 		 * GLOB_PERIOD set.
@@ -772,7 +793,8 @@
 			*pathend = EOS;
 			continue;
 		}
-		error = glob2(pathbuf, --dc, pathlim, restpattern, pglob, limit);
+		error = glob2(pathbuf, --dc, pathlim, restpattern, pglob,
+		    limit);
 		if (error)
 			break;
 	}
@@ -834,7 +856,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);
@@ -844,7 +866,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