1 commit 7cbcdb3699584db8913ca90f705d6337633ee10f
2 Author: Siddhesh Poyarekar <siddhesh@redhat.com>
3 Date: Fri Oct 25 10:22:12 2013 +0530
5 Fix stack overflow due to large AF_INET6 requests
7 Resolves #16072 (CVE-2013-4458).
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.
13 commit 91ce40854d0b7f865cf5024ef95a8026b76096f3
14 Author: Florian Weimer <fweimer@redhat.com>
15 Date: Fri Aug 16 09:38:52 2013 +0200
17 CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
19 * sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
21 * sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
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
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
33 * manual/conf.texi (Limits for Files): Add portability note to
35 (Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
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) \
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, \
51 + char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \
55 + result = -EAI_MEMORY; \
56 + goto free_and_return; \
59 + malloc_tmpbuf = true; \
60 + tmpbuflen = 2 * tmpbuflen; \
63 if (status == NSS_STATUS_SUCCESS && rc == 0) \
65 @@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
67 __set_h_errno (herrno); \
68 _res.options = old_res_options; \
69 - return -EAI_SYSTEM; \
70 + result = -EAI_SYSTEM; \
71 + goto free_and_return; \
73 if (herrno == TRY_AGAIN) \
74 no_data = EAI_AGAIN; \
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}.
82 @deftypevr Macro int NAME_MAX
83 The uniform system limit (if any) for the length of a file name component.
85 +@strong{Portability Note:} On some systems, the GNU C Library defines
86 +@code{NAME_MAX}, but does not actually enforce this limit.
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}).
95 +@strong{Portability Note:} The GNU C Library does not enforce this limit
96 +even if @code{PATH_MAX} is defined.
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}.
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.
108 @section Utility Program Capacity Limits
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}.
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
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.
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.
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.
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}.
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.
161 +@strong{Portability Note:} It is recommended to use @code{readdir}
162 +instead of @code{readdir_r} for the following reasons:
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.
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.
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
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.
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}.
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.
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
219 off_t filepos; /* Position of next entry to read. */
221 + int errcode; /* Delayed error code. */
223 /* Directory block. */
224 char data[0] __attribute__ ((aligned (__alignof__ (void*))));
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)
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)
245 const int saved_errno = errno;
248 __libc_lock_lock (dirp->lock);
250 @@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
252 __set_errno (saved_errno);
255 + dirp->errcode = errno;
258 - /* Reclen != 0 signals that an error occurred. */
259 - reclen = bytes != 0;
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;
267 - /* Skip deleted files. */
269 + if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
271 + /* The record is very long. It could still fit into the
272 + caller-supplied buffer if we can skip padding at the
274 + size_t namelen = _D_EXACT_NAMLEN (dp);
275 + if (namelen <= NAME_MAX)
276 + reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
279 + /* The name is too long. Ignore this file. */
280 + dirp->errcode = ENAMETOOLONG;
287 + /* Skip deleted and ignored files. */
289 while (dp->d_ino == 0);
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));
298 *result = memcpy (entry, dp, reclen);
299 -#ifdef GETDENTS_64BIT_ALIGNED
300 +#ifdef _DIRENT_HAVE_D_RECLEN
301 entry->d_reclen = reclen;
309 + ret = dirp->errcode;
312 __libc_lock_unlock (dirp->lock);
314 - return dp != NULL ? 0 : reclen ? errno : 0;
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)
328 __libc_lock_unlock (dirp->lock);
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
335 #define __READDIR_R __readdir64_r
336 #define __GETDENTS __getdents64
337 #define DIRENT_TYPE struct dirent64
338 -#define GETDENTS_64BIT_ALIGNED 1
340 #include <sysdeps/unix/readdir_r.c>