From bc8e0f77eec9ca5181609828450dc2dbbb475be8 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Wed, 20 Oct 2010 19:08:20 +0200 Subject: [PATCH] libc - Fix security issue in globbing code There is a report about memory exhaustion in CVE-2010-2632 which also affected us. This patch, adopted from NetBSD, fixes the issue. Tested-by: thomas@ and me OK: dillon@ --- lib/libc/gen/glob.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c index 0f25c58767..9a88a4749c 100644 --- a/lib/libc/gen/glob.c +++ b/lib/libc/gen/glob.c @@ -137,6 +137,14 @@ typedef char Char; #define ismeta(c) (((c)&M_QUOTE) != 0) +#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 + static int compare(const void *, const void *); static int g_Ctoc(const Char *, char *, size_t); static int g_lstat(const Char *, struct stat *, glob_t *); @@ -162,6 +170,9 @@ static int match(const Char *, const Char *, const Char *); static void qprintf(const char *, const Char *); #endif +/* 0 = malloc(), 1 = stat(), 2 = readdir() */ +static size_t limits[] = { 0, 0, 0 }; + int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) @@ -560,6 +571,14 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_last, const Char *pattern, if (g_lstat(pathbuf, &sb, pglob)) return(0); + if ((pglob->gl_flags & GLOB_LIMIT) && + limits[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) && @@ -643,6 +662,14 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last, const Char *pattern, size_t clen; mbstate_t mbs; + if ((pglob->gl_flags & GLOB_LIMIT) && + limits[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) { + errno = 0; + *pathend++ = SEP; + *pathend = EOS; + return GLOB_NOSPACE; + } + /* Initial DOT must be matched literally. */ if (dp->d_name[0] == DOT && *pattern != DOT && !(pglob->gl_flags & GLOB_PERIOD)) @@ -729,6 +756,7 @@ globextend(const Char *path, glob_t *pglob, size_t *limit) for (p = path; *p++;) continue; len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */ + limits[GLOB_INDEX_MALLOC] += len; if ((copy = malloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { free(copy); @@ -737,6 +765,12 @@ globextend(const Char *path, glob_t *pglob, size_t *limit) pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; } pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + if ((pglob->gl_flags & GLOB_LIMIT) && + (newsize + limits[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) { + errno = 0; + return GLOB_NOSPACE; + } + return(copy == NULL ? GLOB_NOSPACE : 0); } -- 2.41.0