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;
}