Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2283 - (hide 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 niro 2283 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