source: build-files/src-patches/1-SA-13:01.libc.patch @ 1620346

9.1-release9.2-releasereleng/10.0releng/10.0.1
Last change on this file since 1620346 was 1620346, checked in by Kris Moore <kris@…>, 12 months ago

Initial import of PC-BSD /current/ SVN repo

  • Property mode set to 100644
File size: 6.8 KB
RevLine 
[1620346]1Index: lib/libc/gen/glob.c
2===================================================================
3--- lib/libc/gen/glob.c (revision 246357)
4+++ lib/libc/gen/glob.c (working copy)
5@@ -94,6 +94,25 @@ __FBSDID("$FreeBSD$");
6 
7 #include "collate.h"
8 
9+/*
10+ * glob(3) expansion limits. Stop the expansion if any of these limits
11+ * is reached. This caps the runtime in the face of DoS attacks. See
12+ * also CVE-2010-2632
13+ */
14+#define        GLOB_LIMIT_BRACE        128     /* number of brace calls */
15+#define        GLOB_LIMIT_PATH         65536   /* number of path elements */
16+#define        GLOB_LIMIT_READDIR      16384   /* number of readdirs */
17+#define        GLOB_LIMIT_STAT         1024    /* number of stat system calls */
18+#define        GLOB_LIMIT_STRING       ARG_MAX /* maximum total size for paths */
19+
20+struct glob_limit {
21+       size_t  l_brace_cnt;
22+       size_t  l_path_lim;
23+       size_t  l_readdir_cnt; 
24+       size_t  l_stat_cnt;     
25+       size_t  l_string_cnt;
26+};
27+
28 #define        DOLLAR          '$'
29 #define        DOT             '.'
30 #define        EOS             '\0'
31@@ -153,15 +172,18 @@ static const Char *g_strchr(const Char *, wchar_t)
32 static Char    *g_strcat(Char *, const Char *);
33 #endif
34 static int      g_stat(Char *, struct stat *, glob_t *);
35-static int      glob0(const Char *, glob_t *, size_t *);
36-static int      glob1(Char *, glob_t *, size_t *);
37-static int      glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
38-static int      glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *);
39-static int      globextend(const Char *, glob_t *, size_t *);
40-static const Char *   
41+static int      glob0(const Char *, glob_t *, struct glob_limit *);
42+static int      glob1(Char *, glob_t *, struct glob_limit *);
43+static int      glob2(Char *, Char *, Char *, Char *, glob_t *,
44+    struct glob_limit *);
45+static int      glob3(Char *, Char *, Char *, Char *, Char *, glob_t *,
46+    struct glob_limit *);
47+static int      globextend(const Char *, glob_t *, struct glob_limit *);
48+static const Char *
49                 globtilde(const Char *, Char *, size_t, glob_t *);
50-static int      globexp1(const Char *, glob_t *, size_t *);
51-static int      globexp2(const Char *, const Char *, glob_t *, int *, size_t *);
52+static int      globexp1(const Char *, glob_t *, struct glob_limit *);
53+static int      globexp2(const Char *, const Char *, glob_t *, int *,
54+    struct glob_limit *);
55 static int      match(Char *, Char *, Char *);
56 #ifdef DEBUG
57 static void     qprintf(const char *, Char *);
58@@ -171,8 +193,8 @@ int
59 glob(const char * __restrict pattern, int flags,
60         int (*errfunc)(const char *, int), glob_t * __restrict pglob)
61 {
62+       struct glob_limit limit = { 0, 0, 0, 0, 0 };
63        const char *patnext;
64-       size_t limit;
65        Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
66        mbstate_t mbs;
67        wchar_t wc;
68@@ -186,11 +208,10 @@ glob(const char * __restrict pattern, int flags,
69                        pglob->gl_offs = 0;
70        }
71        if (flags & GLOB_LIMIT) {
72-               limit = pglob->gl_matchc;
73-               if (limit == 0)
74-                       limit = ARG_MAX;
75-       } else
76-               limit = 0;
77+               limit.l_path_lim = pglob->gl_matchc;
78+               if (limit.l_path_lim == 0)
79+                       limit.l_path_lim = GLOB_LIMIT_PATH;
80+       }
81        pglob->gl_flags = flags & ~GLOB_MAGCHAR;
82        pglob->gl_errfunc = errfunc;
83        pglob->gl_matchc = 0;
84@@ -243,11 +264,17 @@ glob(const char * __restrict pattern, int flags,
85  * characters
86  */
87 static int
88-globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
89+globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
90 {
91        const Char* ptr = pattern;
92        int rv;
93 
94+       if ((pglob->gl_flags & GLOB_LIMIT) &&
95+           limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
96+               errno = 0;
97+               return (GLOB_NOSPACE);
98+       }
99+
100        /* Protect a single {}, for find(1), like csh */
101        if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
102                return glob0(pattern, pglob, limit);
103@@ -266,7 +293,8 @@ static int
104  * If it fails then it tries to glob the rest of the pattern and returns.
105  */
106 static int
107-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *limit)
108+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
109+    struct glob_limit *limit)
110 {
111        int     i;
112        Char   *lm, *ls;
113@@ -436,7 +464,7 @@ globtilde(const Char *pattern, Char *patbuf, size_
114  * if things went well, nonzero if errors occurred.
115  */
116 static int
117-glob0(const Char *pattern, glob_t *pglob, size_t *limit)
118+glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
119 {
120        const Char *qpatnext;
121        int err;
122@@ -529,7 +557,7 @@ compare(const void *p, const void *q)
123 }
124 
125 static int
126-glob1(Char *pattern, glob_t *pglob, size_t *limit)
127+glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit)
128 {
129        Char pathbuf[MAXPATHLEN];
130 
131@@ -547,7 +575,7 @@ static int
132  */
133 static int
134 glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
135-      glob_t *pglob, size_t *limit)
136+      glob_t *pglob, struct glob_limit *limit)
137 {
138        struct stat sb;
139        Char *p, *q;
140@@ -563,6 +591,15 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_
141                        if (g_lstat(pathbuf, &sb, pglob))
142                                return(0);
143 
144+                       if ((pglob->gl_flags & GLOB_LIMIT) &&
145+                           limit->l_stat_cnt++ >= GLOB_LIMIT_STAT) {
146+                               errno = 0;
147+                               if (pathend + 1 > pathend_last)
148+                                       return (GLOB_ABORTED);
149+                               *pathend++ = SEP;
150+                               *pathend = EOS;
151+                               return (GLOB_NOSPACE);
152+                       }
153                        if (((pglob->gl_flags & GLOB_MARK) &&
154                            pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
155                            || (S_ISLNK(sb.st_mode) &&
156@@ -606,7 +643,7 @@ glob2(Char *pathbuf, Char *pathend, Char *pathend_
157 static int
158 glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
159       Char *pattern, Char *restpattern,
160-      glob_t *pglob, size_t *limit)
161+      glob_t *pglob, struct glob_limit *limit)
162 {
163        struct dirent *dp;
164        DIR *dirp;
165@@ -652,6 +689,19 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_
166                size_t clen;
167                mbstate_t mbs;
168 
169+               if ((pglob->gl_flags & GLOB_LIMIT) &&
170+                   limit->l_readdir_cnt++ >= GLOB_LIMIT_READDIR) {
171+                       errno = 0;
172+                       if (pathend + 1 > pathend_last)
173+                               err = GLOB_ABORTED;
174+                       else {
175+                               *pathend++ = SEP;
176+                               *pathend = EOS;
177+                               err = GLOB_NOSPACE;
178+                       }
179+                       break;
180+               }
181+
182                /* Initial DOT must be matched literally. */
183                if (dp->d_name[0] == DOT && *pattern != DOT)
184                        continue;
185@@ -702,14 +752,15 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_
186  *     gl_pathv points to (gl_offs + gl_pathc + 1) items.
187  */
188 static int
189-globextend(const Char *path, glob_t *pglob, size_t *limit)
190+globextend(const Char *path, glob_t *pglob, struct glob_limit *limit)
191 {
192        char **pathv;
193        size_t i, newsize, len;
194        char *copy;
195        const Char *p;
196 
197-       if (*limit && pglob->gl_pathc > *limit) {
198+       if ((pglob->gl_flags & GLOB_LIMIT) &&
199+           pglob->gl_matchc > limit->l_path_lim) {
200                errno = 0;
201                return (GLOB_NOSPACE);
202        }
203@@ -737,6 +788,12 @@ static int
204        for (p = path; *p++;)
205                continue;
206        len = MB_CUR_MAX * (size_t)(p - path);  /* XXX overallocation */
207+       limit->l_string_cnt += len;
208+       if ((pglob->gl_flags & GLOB_LIMIT) &&
209+           limit->l_string_cnt >= GLOB_LIMIT_STRING) {
210+               errno = 0;
211+               return (GLOB_NOSPACE);
212+       }
213        if ((copy = malloc(len)) != NULL) {
214                if (g_Ctoc(path, copy, len)) {
215                        free(copy);
Note: See TracBrowser for help on using the repository browser.