]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/glibc/glibc-rh1111460.patch
Merge branch 'master' of ssh://git.ipfire.org/pub/git/ipfire-2.x into seventeen-geoip
[ipfire-2.x.git] / src / patches / glibc / glibc-rh1111460.patch
1 commit 7cbcdb3699584db8913ca90f705d6337633ee10f
2 Author: Siddhesh Poyarekar <siddhesh@redhat.com>
3 Date: Fri Oct 25 10:22:12 2013 +0530
4
5 Fix stack overflow due to large AF_INET6 requests
6
7 Resolves #16072 (CVE-2013-4458).
8
9 This patch fixes another stack overflow in getaddrinfo when it is
10 called with AF_INET6. The AF_UNSPEC case was fixed as CVE-2013-1914,
11 but the AF_INET6 case went undetected back then.
12
13 commit 91ce40854d0b7f865cf5024ef95a8026b76096f3
14 Author: Florian Weimer <fweimer@redhat.com>
15 Date: Fri Aug 16 09:38:52 2013 +0200
16
17 CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
18
19 * sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
20 member.
21 * sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
22 member.
23 * sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
24 * sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
25 Return delayed error code. Remove GETDENTS_64BIT_ALIGNED
26 conditional.
27 * sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
28 GETDENTS_64BIT_ALIGNED.
29 * sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
30 * manual/filesys.texi (Reading/Closing Directory): Document
31 ENAMETOOLONG return value of readdir_r. Recommend readdir more
32 strongly.
33 * manual/conf.texi (Limits for Files): Add portability note to
34 NAME_MAX, PATH_MAX.
35 (Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
36
37 diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
38 index e6ce4cf..8ff74b4 100644
39 --- a/sysdeps/posix/getaddrinfo.c
40 +++ b/sysdeps/posix/getaddrinfo.c
41 @@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
42 &rc, &herrno, NULL, &localcanon)); \
43 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
44 break; \
45 - tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
46 + if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \
47 + tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \
48 + alloca_used); \
49 + else \
50 + { \
51 + char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \
52 + 2 * tmpbuflen); \
53 + if (newp == NULL) \
54 + { \
55 + result = -EAI_MEMORY; \
56 + goto free_and_return; \
57 + } \
58 + tmpbuf = newp; \
59 + malloc_tmpbuf = true; \
60 + tmpbuflen = 2 * tmpbuflen; \
61 + } \
62 } \
63 if (status == NSS_STATUS_SUCCESS && rc == 0) \
64 h = &th; \
65 @@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
66 { \
67 __set_h_errno (herrno); \
68 _res.options = old_res_options; \
69 - return -EAI_SYSTEM; \
70 + result = -EAI_SYSTEM; \
71 + goto free_and_return; \
72 } \
73 if (herrno == TRY_AGAIN) \
74 no_data = EAI_AGAIN; \
75
76 diff --git a/manual/conf.texi b/manual/conf.texi
77 index 7eb8b36..c720063 100644
78 --- a/manual/conf.texi
79 +++ b/manual/conf.texi
80 @@ -1149,6 +1149,9 @@ typed ahead as input. @xref{I/O Queues}.
81 @comment POSIX.1
82 @deftypevr Macro int NAME_MAX
83 The uniform system limit (if any) for the length of a file name component.
84 +
85 +@strong{Portability Note:} On some systems, the GNU C Library defines
86 +@code{NAME_MAX}, but does not actually enforce this limit.
87 @end deftypevr
88
89 @comment limits.h
90 @@ -1157,6 +1160,9 @@ including the terminating null character.
91 @deftypevr Macro int PATH_MAX
92 The uniform system limit (if any) for the length of an entire file name (that
93 is, the argument given to system calls such as @code{open}).
94 +
95 +@strong{Portability Note:} The GNU C Library does not enforce this limit
96 +even if @code{PATH_MAX} is defined.
97 @end deftypevr
98
99 @cindex limits, pipe buffer size
100 @@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
101 Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
102 @end table
103
104 +@strong{Portability Note:} On some systems, the GNU C Library does not
105 +enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
106 +
107 @node Utility Limits
108 @section Utility Program Capacity Limits
109
110 diff --git a/manual/filesys.texi b/manual/filesys.texi
111 index 1df9cf2..814c210 100644
112 --- a/manual/filesys.texi
113 +++ b/manual/filesys.texi
114 @@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
115 @comment POSIX.1
116 @deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
117 This function reads the next entry from the directory. It normally
118 -returns a pointer to a structure containing information about the file.
119 -This structure is statically allocated and can be rewritten by a
120 -subsequent call.
121 +returns a pointer to a structure containing information about the
122 +file. This structure is associated with the @var{dirstream} handle
123 +and can be rewritten by a subsequent call.
124
125 @strong{Portability Note:} On some systems @code{readdir} may not
126 return entries for @file{.} and @file{..}, even though these are always
127 @@ -461,19 +461,61 @@ conditions are defined for this function:
128 The @var{dirstream} argument is not valid.
129 @end table
130
131 -@code{readdir} is not thread safe. Multiple threads using
132 -@code{readdir} on the same @var{dirstream} may overwrite the return
133 -value. Use @code{readdir_r} when this is critical.
134 +To distinguish between an end-of-directory condition or an error, you
135 +must set @code{errno} to zero before calling @code{readdir}. To avoid
136 +entering an infinite loop, you should stop reading from the directory
137 +after the first error.
138 +
139 +In POSIX.1-2008, @code{readdir} is not thread-safe. In the GNU C Library
140 +implementation, it is safe to call @code{readdir} concurrently on
141 +different @var{dirstream}s, but multiple threads accessing the same
142 +@var{dirstream} result in undefined behavior. @code{readdir_r} is a
143 +fully thread-safe alternative, but suffers from poor portability (see
144 +below). It is recommended that you use @code{readdir}, with external
145 +locking if multiple threads access the same @var{dirstream}.
146 @end deftypefun
147
148 @comment dirent.h
149 @comment GNU
150 @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
151 -This function is the reentrant version of @code{readdir}. Like
152 -@code{readdir} it returns the next entry from the directory. But to
153 -prevent conflicts between simultaneously running threads the result is
154 -not stored in statically allocated memory. Instead the argument
155 -@var{entry} points to a place to store the result.
156 +This function is a version of @code{readdir} which performs internal
157 +locking. Like @code{readdir} it returns the next entry from the
158 +directory. To prevent conflicts between simultaneously running
159 +threads the result is stored inside the @var{entry} object.
160 +
161 +@strong{Portability Note:} It is recommended to use @code{readdir}
162 +instead of @code{readdir_r} for the following reasons:
163 +
164 +@itemize @bullet
165 +@item
166 +On systems which do not define @code{NAME_MAX}, it may not be possible
167 +to use @code{readdir_r} safely because the caller does not specify the
168 +length of the buffer for the directory entry.
169 +
170 +@item
171 +On some systems, @code{readdir_r} cannot read directory entries with
172 +very long names. If such a name is encountered, the GNU C Library
173 +implementation of @code{readdir_r} returns with an error code of
174 +@code{ENAMETOOLONG} after the final directory entry has been read. On
175 +other systems, @code{readdir_r} may return successfully, but the
176 +@code{d_name} member may not be NUL-terminated or may be truncated.
177 +
178 +@item
179 +POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
180 +even when access to the same @var{dirstream} is serialized. But in
181 +current implementations (including the GNU C Library), it is safe to call
182 +@code{readdir} concurrently on different @var{dirstream}s, so there is
183 +no need to use @code{readdir_r} in most multi-threaded programs. In
184 +the rare case that multiple threads need to read from the same
185 +@var{dirstream}, it is still better to use @code{readdir} and external
186 +synchronization.
187 +
188 +@item
189 +It is expected that future versions of POSIX will obsolete
190 +@code{readdir_r} and mandate the level of thread safety for
191 +@code{readdir} which is provided by the GNU C Library and other
192 +implementations today.
193 +@end itemize
194
195 Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
196 to @var{entry}. If there are no more entries in the directory or an
197 @@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
198 null pointer and returns a nonzero error code, also stored in
199 @code{errno}, as described for @code{readdir}.
200
201 -@strong{Portability Note:} On some systems @code{readdir_r} may not
202 -return a NUL terminated string for the file name, even when there is no
203 -@code{d_reclen} field in @code{struct dirent} and the file
204 -name is the maximum allowed size. Modern systems all have the
205 -@code{d_reclen} field, and on old systems multi-threading is not
206 -critical. In any case there is no such problem with the @code{readdir}
207 -function, so that even on systems without the @code{d_reclen} member one
208 -could use multiple threads by using external locking.
209 -
210 It is also important to look at the definition of the @code{struct
211 dirent} type. Simply passing a pointer to an object of this type for
212 the second parameter of @code{readdir_r} might not be enough. Some
213 diff --git a/sysdeps/unix/dirstream.h b/sysdeps/unix/dirstream.h
214 index a7a074d..8e8570d 100644
215 --- a/sysdeps/unix/dirstream.h
216 +++ b/sysdeps/unix/dirstream.h
217 @@ -39,6 +39,8 @@ struct __dirstream
218
219 off_t filepos; /* Position of next entry to read. */
220
221 + int errcode; /* Delayed error code. */
222 +
223 /* Directory block. */
224 char data[0] __attribute__ ((aligned (__alignof__ (void*))));
225 };
226 diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c
227 index ddfc3a7..fc05b0f 100644
228 --- a/sysdeps/unix/opendir.c
229 +++ b/sysdeps/unix/opendir.c
230 @@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
231 dirp->size = 0;
232 dirp->offset = 0;
233 dirp->filepos = 0;
234 + dirp->errcode = 0;
235
236 return dirp;
237 }
238 diff --git a/sysdeps/unix/readdir_r.c b/sysdeps/unix/readdir_r.c
239 index b5a8e2e..8ed5c3f 100644
240 --- a/sysdeps/unix/readdir_r.c
241 +++ b/sysdeps/unix/readdir_r.c
242 @@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
243 DIRENT_TYPE *dp;
244 size_t reclen;
245 const int saved_errno = errno;
246 + int ret;
247
248 __libc_lock_lock (dirp->lock);
249
250 @@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
251 bytes = 0;
252 __set_errno (saved_errno);
253 }
254 + if (bytes < 0)
255 + dirp->errcode = errno;
256
257 dp = NULL;
258 - /* Reclen != 0 signals that an error occurred. */
259 - reclen = bytes != 0;
260 break;
261 }
262 dirp->size = (size_t) bytes;
263 @@ -106,28 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
264 dirp->filepos += reclen;
265 #endif
266
267 - /* Skip deleted files. */
268 +#ifdef NAME_MAX
269 + if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
270 + {
271 + /* The record is very long. It could still fit into the
272 + caller-supplied buffer if we can skip padding at the
273 + end. */
274 + size_t namelen = _D_EXACT_NAMLEN (dp);
275 + if (namelen <= NAME_MAX)
276 + reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
277 + else
278 + {
279 + /* The name is too long. Ignore this file. */
280 + dirp->errcode = ENAMETOOLONG;
281 + dp->d_ino = 0;
282 + continue;
283 + }
284 + }
285 +#endif
286 +
287 + /* Skip deleted and ignored files. */
288 }
289 while (dp->d_ino == 0);
290
291 if (dp != NULL)
292 {
293 -#ifdef GETDENTS_64BIT_ALIGNED
294 - /* The d_reclen value might include padding which is not part of
295 - the DIRENT_TYPE data structure. */
296 - reclen = MIN (reclen, sizeof (DIRENT_TYPE));
297 -#endif
298 *result = memcpy (entry, dp, reclen);
299 -#ifdef GETDENTS_64BIT_ALIGNED
300 +#ifdef _DIRENT_HAVE_D_RECLEN
301 entry->d_reclen = reclen;
302 #endif
303 + ret = 0;
304 }
305 else
306 - *result = NULL;
307 + {
308 + *result = NULL;
309 + ret = dirp->errcode;
310 + }
311
312 __libc_lock_unlock (dirp->lock);
313
314 - return dp != NULL ? 0 : reclen ? errno : 0;
315 + return ret;
316 }
317
318 #ifdef __READDIR_R_ALIAS
319 diff --git a/sysdeps/unix/rewinddir.c b/sysdeps/unix/rewinddir.c
320 index 2935a8e..d4991ad 100644
321 --- a/sysdeps/unix/rewinddir.c
322 +++ b/sysdeps/unix/rewinddir.c
323 @@ -33,5 +33,6 @@ rewinddir (dirp)
324 dirp->filepos = 0;
325 dirp->offset = 0;
326 dirp->size = 0;
327 + dirp->errcode = 0;
328 __libc_lock_unlock (dirp->lock);
329 }
330 diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
331 index 8ebbcfd..a7d114e 100644
332 --- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
333 +++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
334 @@ -18,7 +18,6 @@
335 #define __READDIR_R __readdir64_r
336 #define __GETDENTS __getdents64
337 #define DIRENT_TYPE struct dirent64
338 -#define GETDENTS_64BIT_ALIGNED 1
339
340 #include <sysdeps/unix/readdir_r.c>
341