Magellan Linux

Contents of /trunk/glibc/patches/glibc-2.18-readdir_r-CVE-2013-4237.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2283 - (show annotations) (download)
Mon Sep 16 11:57:11 2013 UTC (10 years, 7 months ago) by niro
File size: 10608 byte(s)
-glibc-2.18 CVEs and fixes
1 diff --git a/manual/conf.texi b/manual/conf.texi
2 index 7eb8b36..c720063 100644
3 --- a/manual/conf.texi
4 +++ b/manual/conf.texi
5 @@ -1149,6 +1149,9 @@ typed ahead as input. @xref{I/O Queues}.
6 @deftypevr Macro int NAME_MAX
7 The uniform system limit (if any) for the length of a file name component, not
8 including the terminating null character.
9 +
10 +@strong{Portability Note:} On some systems, @theglibc{} defines
11 +@code{NAME_MAX}, but does not actually enforce this limit.
12 @end deftypevr
13
14 @comment limits.h
15 @@ -1157,6 +1160,9 @@ including the terminating null character.
16 The uniform system limit (if any) for the length of an entire file name (that
17 is, the argument given to system calls such as @code{open}), including the
18 terminating null character.
19 +
20 +@strong{Portability Note:} @Theglibc{} does not enforce this limit
21 +even if @code{PATH_MAX} is defined.
22 @end deftypevr
23
24 @cindex limits, pipe buffer size
25 @@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
26 Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
27 @end table
28
29 +@strong{Portability Note:} On some systems, @theglibc{} does not
30 +enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
31 +
32 @node Utility Limits
33 @section Utility Program Capacity Limits
34
35 diff --git a/manual/filesys.texi b/manual/filesys.texi
36 index 1df9cf2..814c210 100644
37 --- a/manual/filesys.texi
38 +++ b/manual/filesys.texi
39 @@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
40 @comment POSIX.1
41 @deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
42 This function reads the next entry from the directory. It normally
43 -returns a pointer to a structure containing information about the file.
44 -This structure is statically allocated and can be rewritten by a
45 -subsequent call.
46 +returns a pointer to a structure containing information about the
47 +file. This structure is associated with the @var{dirstream} handle
48 +and can be rewritten by a subsequent call.
49
50 @strong{Portability Note:} On some systems @code{readdir} may not
51 return entries for @file{.} and @file{..}, even though these are always
52 @@ -461,19 +461,61 @@ conditions are defined for this function:
53 The @var{dirstream} argument is not valid.
54 @end table
55
56 -@code{readdir} is not thread safe. Multiple threads using
57 -@code{readdir} on the same @var{dirstream} may overwrite the return
58 -value. Use @code{readdir_r} when this is critical.
59 +To distinguish between an end-of-directory condition or an error, you
60 +must set @code{errno} to zero before calling @code{readdir}. To avoid
61 +entering an infinite loop, you should stop reading from the directory
62 +after the first error.
63 +
64 +In POSIX.1-2008, @code{readdir} is not thread-safe. In @theglibc{}
65 +implementation, it is safe to call @code{readdir} concurrently on
66 +different @var{dirstream}s, but multiple threads accessing the same
67 +@var{dirstream} result in undefined behavior. @code{readdir_r} is a
68 +fully thread-safe alternative, but suffers from poor portability (see
69 +below). It is recommended that you use @code{readdir}, with external
70 +locking if multiple threads access the same @var{dirstream}.
71 @end deftypefun
72
73 @comment dirent.h
74 @comment GNU
75 @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
76 -This function is the reentrant version of @code{readdir}. Like
77 -@code{readdir} it returns the next entry from the directory. But to
78 -prevent conflicts between simultaneously running threads the result is
79 -not stored in statically allocated memory. Instead the argument
80 -@var{entry} points to a place to store the result.
81 +This function is a version of @code{readdir} which performs internal
82 +locking. Like @code{readdir} it returns the next entry from the
83 +directory. To prevent conflicts between simultaneously running
84 +threads the result is stored inside the @var{entry} object.
85 +
86 +@strong{Portability Note:} It is recommended to use @code{readdir}
87 +instead of @code{readdir_r} for the following reasons:
88 +
89 +@itemize @bullet
90 +@item
91 +On systems which do not define @code{NAME_MAX}, it may not be possible
92 +to use @code{readdir_r} safely because the caller does not specify the
93 +length of the buffer for the directory entry.
94 +
95 +@item
96 +On some systems, @code{readdir_r} cannot read directory entries with
97 +very long names. If such a name is encountered, @theglibc{}
98 +implementation of @code{readdir_r} returns with an error code of
99 +@code{ENAMETOOLONG} after the final directory entry has been read. On
100 +other systems, @code{readdir_r} may return successfully, but the
101 +@code{d_name} member may not be NUL-terminated or may be truncated.
102 +
103 +@item
104 +POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
105 +even when access to the same @var{dirstream} is serialized. But in
106 +current implementations (including @theglibc{}), it is safe to call
107 +@code{readdir} concurrently on different @var{dirstream}s, so there is
108 +no need to use @code{readdir_r} in most multi-threaded programs. In
109 +the rare case that multiple threads need to read from the same
110 +@var{dirstream}, it is still better to use @code{readdir} and external
111 +synchronization.
112 +
113 +@item
114 +It is expected that future versions of POSIX will obsolete
115 +@code{readdir_r} and mandate the level of thread safety for
116 +@code{readdir} which is provided by @theglibc{} and other
117 +implementations today.
118 +@end itemize
119
120 Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
121 to @var{entry}. If there are no more entries in the directory or an
122 @@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
123 null pointer and returns a nonzero error code, also stored in
124 @code{errno}, as described for @code{readdir}.
125
126 -@strong{Portability Note:} On some systems @code{readdir_r} may not
127 -return a NUL terminated string for the file name, even when there is no
128 -@code{d_reclen} field in @code{struct dirent} and the file
129 -name is the maximum allowed size. Modern systems all have the
130 -@code{d_reclen} field, and on old systems multi-threading is not
131 -critical. In any case there is no such problem with the @code{readdir}
132 -function, so that even on systems without the @code{d_reclen} member one
133 -could use multiple threads by using external locking.
134 -
135 It is also important to look at the definition of the @code{struct
136 dirent} type. Simply passing a pointer to an object of this type for
137 the second parameter of @code{readdir_r} might not be enough. Some
138 diff --git a/sysdeps/posix/dirstream.h b/sysdeps/posix/dirstream.h
139 index a7a074d..8e8570d 100644
140 --- a/sysdeps/posix/dirstream.h
141 +++ b/sysdeps/posix/dirstream.h
142 @@ -39,6 +39,8 @@ struct __dirstream
143
144 off_t filepos; /* Position of next entry to read. */
145
146 + int errcode; /* Delayed error code. */
147 +
148 /* Directory block. */
149 char data[0] __attribute__ ((aligned (__alignof__ (void*))));
150 };
151 diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
152 index ddfc3a7..fc05b0f 100644
153 --- a/sysdeps/posix/opendir.c
154 +++ b/sysdeps/posix/opendir.c
155 @@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
156 dirp->size = 0;
157 dirp->offset = 0;
158 dirp->filepos = 0;
159 + dirp->errcode = 0;
160
161 return dirp;
162 }
163 diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c
164 index b5a8e2e..8ed5c3f 100644
165 --- a/sysdeps/posix/readdir_r.c
166 +++ b/sysdeps/posix/readdir_r.c
167 @@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
168 DIRENT_TYPE *dp;
169 size_t reclen;
170 const int saved_errno = errno;
171 + int ret;
172
173 __libc_lock_lock (dirp->lock);
174
175 @@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
176 bytes = 0;
177 __set_errno (saved_errno);
178 }
179 + if (bytes < 0)
180 + dirp->errcode = errno;
181
182 dp = NULL;
183 - /* Reclen != 0 signals that an error occurred. */
184 - reclen = bytes != 0;
185 break;
186 }
187 dirp->size = (size_t) bytes;
188 @@ -106,29 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
189 dirp->filepos += reclen;
190 #endif
191
192 - /* Skip deleted files. */
193 +#ifdef NAME_MAX
194 + if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
195 + {
196 + /* The record is very long. It could still fit into the
197 + caller-supplied buffer if we can skip padding at the
198 + end. */
199 + size_t namelen = _D_EXACT_NAMLEN (dp);
200 + if (namelen <= NAME_MAX)
201 + reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
202 + else
203 + {
204 + /* The name is too long. Ignore this file. */
205 + dirp->errcode = ENAMETOOLONG;
206 + dp->d_ino = 0;
207 + continue;
208 + }
209 + }
210 +#endif
211 +
212 + /* Skip deleted and ignored files. */
213 }
214 while (dp->d_ino == 0);
215
216 if (dp != NULL)
217 {
218 -#ifdef GETDENTS_64BIT_ALIGNED
219 - /* The d_reclen value might include padding which is not part of
220 - the DIRENT_TYPE data structure. */
221 - reclen = MIN (reclen,
222 - offsetof (DIRENT_TYPE, d_name) + sizeof (dp->d_name));
223 -#endif
224 *result = memcpy (entry, dp, reclen);
225 -#ifdef GETDENTS_64BIT_ALIGNED
226 +#ifdef _DIRENT_HAVE_D_RECLEN
227 entry->d_reclen = reclen;
228 #endif
229 + ret = 0;
230 }
231 else
232 - *result = NULL;
233 + {
234 + *result = NULL;
235 + ret = dirp->errcode;
236 + }
237
238 __libc_lock_unlock (dirp->lock);
239
240 - return dp != NULL ? 0 : reclen ? errno : 0;
241 + return ret;
242 }
243
244 #ifdef __READDIR_R_ALIAS
245 diff --git a/sysdeps/posix/rewinddir.c b/sysdeps/posix/rewinddir.c
246 index 2935a8e..d4991ad 100644
247 --- a/sysdeps/posix/rewinddir.c
248 +++ b/sysdeps/posix/rewinddir.c
249 @@ -33,6 +33,7 @@ rewinddir (dirp)
250 dirp->filepos = 0;
251 dirp->offset = 0;
252 dirp->size = 0;
253 + dirp->errcode = 0;
254 #ifndef NOT_IN_libc
255 __libc_lock_unlock (dirp->lock);
256 #endif
257 diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
258 index 8ebbcfd..a7d114e 100644
259 --- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
260 +++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
261 @@ -18,7 +18,6 @@
262 #define __READDIR_R __readdir64_r
263 #define __GETDENTS __getdents64
264 #define DIRENT_TYPE struct dirent64
265 -#define GETDENTS_64BIT_ALIGNED 1
266
267 #include <sysdeps/posix/readdir_r.c>
268
269 diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
270 index 5ed8e95..290f2c8 100644
271 --- a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
272 +++ b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
273 @@ -1,5 +1,4 @@
274 #define readdir64_r __no_readdir64_r_decl
275 -#define GETDENTS_64BIT_ALIGNED 1
276 #include <sysdeps/posix/readdir_r.c>
277 #undef readdir64_r
278 weak_alias (__readdir_r, readdir64_r)
279 --
280 1.8.3.4
281