summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2001-03-18 17:18:59 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2001-03-18 17:18:59 +0000
commitd773be8ce3c0486ddd93899ef375d48e5e6483d3 (patch)
tree2ca09deeb7b13881b21b195d139c7c246b364191 /lib
parent76b15e633a7523ef1aabc770eb49e1d85031a18c (diff)
GLOB_LIMIT changes from christos
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gen/glob.320
-rw-r--r--lib/libc/gen/glob.c60
2 files changed, 55 insertions, 25 deletions
diff --git a/lib/libc/gen/glob.3 b/lib/libc/gen/glob.3
index a15cd927e54..a43f73c4df7 100644
--- a/lib/libc/gen/glob.3
+++ b/lib/libc/gen/glob.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: glob.3,v 1.16 2000/12/24 00:30:49 aaron Exp $
+.\" $OpenBSD: glob.3,v 1.17 2001/03/18 17:18:58 deraadt Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
@@ -255,6 +255,13 @@ compatibility with older sources.
Expand patterns that start with
.Ql ~
to user name home directories.
+.It Dv GLOB_LIMIT
+Limit the amount of memory used by matches to
+.Li ARG_MAX
+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
+.Li */../*/..
.El
.Pp
If, during the search, a directory is encountered that cannot be opened
@@ -364,7 +371,13 @@ in the include file
.Aq Pa glob.h :
.Bl -tag -width GLOB_NOCHECK
.It Dv GLOB_NOSPACE
-An attempt to allocate memory failed.
+An attempt to allocate memory failed, or if
+.Va errno
+was 0
+.Li GLOB_LIMIT
+was specified in the flags and
+.Li ARG_MAX or more
+patterns were matched.
.It Dv GLOB_ABORTED
The scan was stopped because an error was encountered and either
.Dv GLOB_ERR
@@ -416,8 +429,9 @@ Note, however, that the flags
.Dv GLOB_MAGCHAR ,
.Dv GLOB_NOMAGIC ,
.Dv GLOB_QUOTE ,
-and
.Dv GLOB_TILDE ,
+and
+.Dv GLOB_LIMIT
and the fields
.Fa gl_matchc
and
diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c
index bb222ebf909..f4e1fe610f5 100644
--- a/lib/libc/gen/glob.c
+++ b/lib/libc/gen/glob.c
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
#else
-static char rcsid[] = "$OpenBSD: glob.c,v 1.8 1998/08/14 21:39:30 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: glob.c,v 1.9 2001/03/18 17:18:58 deraadt Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -140,11 +140,13 @@ static Char *g_strcat __P((Char *, const Char *));
#endif
static int g_stat __P((Char *, struct stat *, glob_t *));
static int glob0 __P((const Char *, glob_t *));
-static int glob1 __P((Char *, glob_t *));
-static int glob2 __P((Char *, Char *, Char *, glob_t *));
-static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *));
-static int globextend __P((const Char *, glob_t *));
-static const Char * globtilde __P((const Char *, Char *, size_t, glob_t *));
+static int glob1 __P((Char *, glob_t *, size_t *));
+static int glob2 __P((Char *, Char *, Char *, glob_t *, size_t *));
+static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *,
+ size_t *));
+static int globextend __P((const Char *, glob_t *, size_t *));
+static const Char *
+ globtilde __P((const Char *, Char *, size_t, glob_t *));
static int globexp1 __P((const Char *, glob_t *));
static int globexp2 __P((const Char *, const Char *, glob_t *, int *));
static int match __P((Char *, Char *, Char *));
@@ -406,6 +408,7 @@ glob0(pattern, pglob)
const Char *qpatnext;
int c, err, oldpathc;
Char *bufnext, patbuf[MAXPATHLEN+1];
+ size_t limit = 0;
qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char),
pglob);
@@ -464,7 +467,7 @@ glob0(pattern, pglob)
qprintf("glob0:", patbuf);
#endif
- if ((err = glob1(patbuf, pglob)) != 0)
+ if ((err = glob1(patbuf, pglob, &limit)) != 0)
return(err);
/*
@@ -477,7 +480,7 @@ glob0(pattern, pglob)
if ((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & GLOB_NOMAGIC) &&
!(pglob->gl_flags & GLOB_MAGCHAR)))
- return(globextend(pattern, pglob));
+ return(globextend(pattern, pglob, &limit));
else
return(GLOB_NOMATCH);
}
@@ -495,16 +498,17 @@ compare(p, q)
}
static int
-glob1(pattern, pglob)
+glob1(pattern, pglob, limitp)
Char *pattern;
glob_t *pglob;
+ size_t *limitp;
{
Char pathbuf[MAXPATHLEN+1];
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
if (*pattern == EOS)
return(0);
- return(glob2(pathbuf, pathbuf, pattern, pglob));
+ return(glob2(pathbuf, pathbuf, pattern, pglob, limitp));
}
/*
@@ -513,9 +517,10 @@ glob1(pattern, pglob)
* meta characters.
*/
static int
-glob2(pathbuf, pathend, pattern, pglob)
+glob2(pathbuf, pathend, pattern, pglob, limitp)
Char *pathbuf, *pathend, *pattern;
glob_t *pglob;
+ size_t *limitp;
{
struct stat sb;
Char *p, *q;
@@ -540,7 +545,7 @@ glob2(pathbuf, pathend, pattern, pglob)
*pathend = EOS;
}
++pglob->gl_matchc;
- return(globextend(pathbuf, pglob));
+ return(globextend(pathbuf, pglob, limitp));
}
/* Find end of next segment, copy tentatively to pathend. */
@@ -558,15 +563,17 @@ glob2(pathbuf, pathend, pattern, pglob)
while (*pattern == SEP)
*pathend++ = *pattern++;
} else /* Need expansion, recurse. */
- return(glob3(pathbuf, pathend, pattern, p, pglob));
+ return(glob3(pathbuf, pathend, pattern, p, pglob,
+ limitp));
}
/* NOTREACHED */
}
static int
-glob3(pathbuf, pathend, pattern, restpattern, pglob)
+glob3(pathbuf, pathend, pattern, restpattern, pglob, limitp)
Char *pathbuf, *pathend, *pattern, *restpattern;
glob_t *pglob;
+ size_t *limitp;
{
register struct dirent *dp;
DIR *dirp;
@@ -616,7 +623,7 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob)
*pathend = EOS;
continue;
}
- err = glob2(pathbuf, --dc, restpattern, pglob);
+ err = glob2(pathbuf, --dc, restpattern, pglob, limitp);
if (err)
break;
}
@@ -644,20 +651,20 @@ glob3(pathbuf, pathend, pattern, restpattern, pglob)
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
static int
-globextend(path, pglob)
+globextend(path, pglob, limitp)
const Char *path;
glob_t *pglob;
+ size_t *limitp;
{
register char **pathv;
register int i;
- u_int newsize;
+ u_int newsize, len;
char *copy;
const Char *p;
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
- pathv = pglob->gl_pathv ?
- realloc((char *)pglob->gl_pathv, newsize) :
- malloc(newsize);
+ pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) :
+ malloc(newsize);
if (pathv == NULL) {
if (pglob->gl_pathv)
free(pglob->gl_pathv);
@@ -674,11 +681,20 @@ globextend(path, pglob)
for (p = path; *p++;)
continue;
- if ((copy = malloc(p - path)) != NULL) {
+ len = (size_t)(p - path);
+ *limitp += len;
+ if ((copy = malloc(len)) != NULL) {
g_Ctoc(path, copy);
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
}
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ newsize + *limitp >= ARG_MAX) {
+ errno = 0;
+ return(GLOB_NOSPACE);
+ }
+
return(copy == NULL ? GLOB_NOSPACE : 0);
}
@@ -821,7 +837,7 @@ g_strcat(dst, src)
continue;
--dst;
while((*dst++ = *src++) != EOS)
- continue;
+ continue;
return (sdst);
}