diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-03-18 17:18:59 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2001-03-18 17:18:59 +0000 |
commit | d773be8ce3c0486ddd93899ef375d48e5e6483d3 (patch) | |
tree | 2ca09deeb7b13881b21b195d139c7c246b364191 /lib | |
parent | 76b15e633a7523ef1aabc770eb49e1d85031a18c (diff) |
GLOB_LIMIT changes from christos
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/gen/glob.3 | 20 | ||||
-rw-r--r-- | lib/libc/gen/glob.c | 60 |
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); } |