Blame SOURCES/glibc-rh996227.patch

147e83
commit 91ce40854d0b7f865cf5024ef95a8026b76096f3
147e83
Author: Florian Weimer <fweimer@redhat.com>
147e83
Date:   Fri Aug 16 09:38:52 2013 +0200
147e83
147e83
    CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
147e83
    
147e83
    	* sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
147e83
    	member.
147e83
    	* sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
147e83
    	member.
147e83
    	* sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
147e83
    	* sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
147e83
    	Return delayed error code.  Remove GETDENTS_64BIT_ALIGNED
147e83
    	conditional.
147e83
    	* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
147e83
    	GETDENTS_64BIT_ALIGNED.
147e83
    	* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
147e83
    	* manual/filesys.texi (Reading/Closing Directory): Document
147e83
    	ENAMETOOLONG return value of readdir_r.  Recommend readdir more
147e83
    	strongly.
147e83
    	* manual/conf.texi (Limits for Files): Add portability note to
147e83
    	NAME_MAX, PATH_MAX.
147e83
    	(Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
147e83
147e83
diff --git glibc-2.17-c758a686/manual/conf.texi glibc-2.17-c758a686/manual/conf.texi
147e83
index 7eb8b36..c720063 100644
147e83
--- glibc-2.17-c758a686/manual/conf.texi
147e83
+++ glibc-2.17-c758a686/manual/conf.texi
147e83
@@ -1149,6 +1149,9 @@ typed ahead as input.  @xref{I/O Queues}.
147e83
 @deftypevr Macro int NAME_MAX
147e83
 The uniform system limit (if any) for the length of a file name component, not
147e83
 including the terminating null character.
147e83
+
147e83
+@strong{Portability Note:} On some systems, @theglibc{} defines
147e83
+@code{NAME_MAX}, but does not actually enforce this limit.
147e83
 @end deftypevr
147e83
 
147e83
 @comment limits.h
147e83
@@ -1157,6 +1160,9 @@ including the terminating null character.
147e83
 The uniform system limit (if any) for the length of an entire file name (that
147e83
 is, the argument given to system calls such as @code{open}), including the
147e83
 terminating null character.
147e83
+
147e83
+@strong{Portability Note:} @Theglibc{} does not enforce this limit
147e83
+even if @code{PATH_MAX} is defined.
147e83
 @end deftypevr
147e83
 
147e83
 @cindex limits, pipe buffer size
147e83
@@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
147e83
 Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
147e83
 @end table
147e83
 
147e83
+@strong{Portability Note:} On some systems, @theglibc{} does not
147e83
+enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
147e83
+
147e83
 @node Utility Limits
147e83
 @section Utility Program Capacity Limits
147e83
 
147e83
diff --git glibc-2.17-c758a686/manual/filesys.texi glibc-2.17-c758a686/manual/filesys.texi
147e83
index 1df9cf2..814c210 100644
147e83
--- glibc-2.17-c758a686/manual/filesys.texi
147e83
+++ glibc-2.17-c758a686/manual/filesys.texi
147e83
@@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
147e83
 @comment POSIX.1
147e83
 @deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
147e83
 This function reads the next entry from the directory.  It normally
147e83
-returns a pointer to a structure containing information about the file.
147e83
-This structure is statically allocated and can be rewritten by a
147e83
-subsequent call.
147e83
+returns a pointer to a structure containing information about the
147e83
+file.  This structure is associated with the @var{dirstream} handle
147e83
+and can be rewritten by a subsequent call.
147e83
 
147e83
 @strong{Portability Note:} On some systems @code{readdir} may not
147e83
 return entries for @file{.} and @file{..}, even though these are always
147e83
@@ -461,19 +461,61 @@ conditions are defined for this function:
147e83
 The @var{dirstream} argument is not valid.
147e83
 @end table
147e83
 
147e83
-@code{readdir} is not thread safe.  Multiple threads using
147e83
-@code{readdir} on the same @var{dirstream} may overwrite the return
147e83
-value.  Use @code{readdir_r} when this is critical.
147e83
+To distinguish between an end-of-directory condition or an error, you
147e83
+must set @code{errno} to zero before calling @code{readdir}.  To avoid
147e83
+entering an infinite loop, you should stop reading from the directory
147e83
+after the first error.
147e83
+
147e83
+In POSIX.1-2008, @code{readdir} is not thread-safe.  In @theglibc{}
147e83
+implementation, it is safe to call @code{readdir} concurrently on
147e83
+different @var{dirstream}s, but multiple threads accessing the same
147e83
+@var{dirstream} result in undefined behavior.  @code{readdir_r} is a
147e83
+fully thread-safe alternative, but suffers from poor portability (see
147e83
+below).  It is recommended that you use @code{readdir}, with external
147e83
+locking if multiple threads access the same @var{dirstream}.
147e83
 @end deftypefun
147e83
 
147e83
 @comment dirent.h
147e83
 @comment GNU
147e83
 @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
147e83
-This function is the reentrant version of @code{readdir}.  Like
147e83
-@code{readdir} it returns the next entry from the directory.  But to
147e83
-prevent conflicts between simultaneously running threads the result is
147e83
-not stored in statically allocated memory.  Instead the argument
147e83
-@var{entry} points to a place to store the result.
147e83
+This function is a version of @code{readdir} which performs internal
147e83
+locking.  Like @code{readdir} it returns the next entry from the
147e83
+directory.  To prevent conflicts between simultaneously running
147e83
+threads the result is stored inside the @var{entry} object.
147e83
+
147e83
+@strong{Portability Note:} It is recommended to use @code{readdir}
147e83
+instead of @code{readdir_r} for the following reasons:
147e83
+
147e83
+@itemize @bullet
147e83
+@item
147e83
+On systems which do not define @code{NAME_MAX}, it may not be possible
147e83
+to use @code{readdir_r} safely because the caller does not specify the
147e83
+length of the buffer for the directory entry.
147e83
+
147e83
+@item
147e83
+On some systems, @code{readdir_r} cannot read directory entries with
147e83
+very long names.  If such a name is encountered, @theglibc{}
147e83
+implementation of @code{readdir_r} returns with an error code of
147e83
+@code{ENAMETOOLONG} after the final directory entry has been read.  On
147e83
+other systems, @code{readdir_r} may return successfully, but the
147e83
+@code{d_name} member may not be NUL-terminated or may be truncated.
147e83
+
147e83
+@item
147e83
+POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
147e83
+even when access to the same @var{dirstream} is serialized.  But in
147e83
+current implementations (including @theglibc{}), it is safe to call
147e83
+@code{readdir} concurrently on different @var{dirstream}s, so there is
147e83
+no need to use @code{readdir_r} in most multi-threaded programs.  In
147e83
+the rare case that multiple threads need to read from the same
147e83
+@var{dirstream}, it is still better to use @code{readdir} and external
147e83
+synchronization.
147e83
+
147e83
+@item
147e83
+It is expected that future versions of POSIX will obsolete
147e83
+@code{readdir_r} and mandate the level of thread safety for
147e83
+@code{readdir} which is provided by @theglibc{} and other
147e83
+implementations today.
147e83
+@end itemize
147e83
 
147e83
 Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
147e83
 to @var{entry}.  If there are no more entries in the directory or an
147e83
@@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
147e83
 null pointer and returns a nonzero error code, also stored in
147e83
 @code{errno}, as described for @code{readdir}.
147e83
 
147e83
-@strong{Portability Note:} On some systems @code{readdir_r} may not
147e83
-return a NUL terminated string for the file name, even when there is no
147e83
-@code{d_reclen} field in @code{struct dirent} and the file
147e83
-name is the maximum allowed size.  Modern systems all have the
147e83
-@code{d_reclen} field, and on old systems multi-threading is not
147e83
-critical.  In any case there is no such problem with the @code{readdir}
147e83
-function, so that even on systems without the @code{d_reclen} member one
147e83
-could use multiple threads by using external locking.
147e83
-
147e83
 It is also important to look at the definition of the @code{struct
147e83
 dirent} type.  Simply passing a pointer to an object of this type for
147e83
 the second parameter of @code{readdir_r} might not be enough.  Some
147e83
diff --git glibc-2.17-c758a686/sysdeps/posix/dirstream.h glibc-2.17-c758a686/sysdeps/posix/dirstream.h
147e83
index a7a074d..8e8570d 100644
147e83
--- glibc-2.17-c758a686/sysdeps/posix/dirstream.h
147e83
+++ glibc-2.17-c758a686/sysdeps/posix/dirstream.h
147e83
@@ -39,6 +39,8 @@ struct __dirstream
147e83
 
147e83
     off_t filepos;		/* Position of next entry to read.  */
147e83
 
147e83
+    int errcode;		/* Delayed error code.  */
147e83
+
147e83
     /* Directory block.  */
147e83
     char data[0] __attribute__ ((aligned (__alignof__ (void*))));
147e83
   };
147e83
diff --git glibc-2.17-c758a686/sysdeps/posix/opendir.c glibc-2.17-c758a686/sysdeps/posix/opendir.c
147e83
index ddfc3a7..fc05b0f 100644
147e83
--- glibc-2.17-c758a686/sysdeps/posix/opendir.c
147e83
+++ glibc-2.17-c758a686/sysdeps/posix/opendir.c
147e83
@@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
147e83
   dirp->size = 0;
147e83
   dirp->offset = 0;
147e83
   dirp->filepos = 0;
147e83
+  dirp->errcode = 0;
147e83
 
147e83
   return dirp;
147e83
 }
147e83
diff --git glibc-2.17-c758a686/sysdeps/posix/readdir_r.c glibc-2.17-c758a686/sysdeps/posix/readdir_r.c
147e83
index b5a8e2e..8ed5c3f 100644
147e83
--- glibc-2.17-c758a686/sysdeps/posix/readdir_r.c
147e83
+++ glibc-2.17-c758a686/sysdeps/posix/readdir_r.c
147e83
@@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
147e83
   DIRENT_TYPE *dp;
147e83
   size_t reclen;
147e83
   const int saved_errno = errno;
147e83
+  int ret;
147e83
 
147e83
   __libc_lock_lock (dirp->lock);
147e83
 
147e83
@@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
147e83
 		  bytes = 0;
147e83
 		  __set_errno (saved_errno);
147e83
 		}
147e83
+	      if (bytes < 0)
147e83
+		dirp->errcode = errno;
147e83
 
147e83
 	      dp = NULL;
147e83
-	      /* Reclen != 0 signals that an error occurred.  */
147e83
-	      reclen = bytes != 0;
147e83
 	      break;
147e83
 	    }
147e83
 	  dirp->size = (size_t) bytes;
147e83
@@ -106,29 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
147e83
       dirp->filepos += reclen;
147e83
 #endif
147e83
 
147e83
-      /* Skip deleted files.  */
147e83
+#ifdef NAME_MAX
147e83
+      if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
147e83
+	{
147e83
+	  /* The record is very long.  It could still fit into the
147e83
+	     caller-supplied buffer if we can skip padding at the
147e83
+	     end.  */
147e83
+	  size_t namelen = _D_EXACT_NAMLEN (dp);
147e83
+	  if (namelen <= NAME_MAX)
147e83
+	    reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
147e83
+	  else
147e83
+	    {
147e83
+	      /* The name is too long.  Ignore this file.  */
147e83
+	      dirp->errcode = ENAMETOOLONG;
147e83
+	      dp->d_ino = 0;
147e83
+	      continue;
147e83
+	    }
147e83
+	}
147e83
+#endif
147e83
+
147e83
+      /* Skip deleted and ignored files.  */
147e83
     }
147e83
   while (dp->d_ino == 0);
147e83
 
147e83
   if (dp != NULL)
147e83
     {
147e83
-#ifdef GETDENTS_64BIT_ALIGNED
147e83
-      /* The d_reclen value might include padding which is not part of
147e83
-	 the DIRENT_TYPE data structure.  */
147e83
-      reclen = MIN (reclen,
147e83
-		    offsetof (DIRENT_TYPE, d_name) + sizeof (dp->d_name));
147e83
-#endif
147e83
       *result = memcpy (entry, dp, reclen);
147e83
-#ifdef GETDENTS_64BIT_ALIGNED
147e83
+#ifdef _DIRENT_HAVE_D_RECLEN
147e83
       entry->d_reclen = reclen;
147e83
 #endif
147e83
+      ret = 0;
147e83
     }
147e83
   else
147e83
-    *result = NULL;
147e83
+    {
147e83
+      *result = NULL;
147e83
+      ret = dirp->errcode;
147e83
+    }
147e83
 
147e83
   __libc_lock_unlock (dirp->lock);
147e83
 
147e83
-  return dp != NULL ? 0 : reclen ? errno : 0;
147e83
+  return ret;
147e83
 }
147e83
 
147e83
 #ifdef __READDIR_R_ALIAS
147e83
diff --git glibc-2.17-c758a686/sysdeps/posix/rewinddir.c glibc-2.17-c758a686/sysdeps/posix/rewinddir.c
147e83
index 2935a8e..d4991ad 100644
147e83
--- glibc-2.17-c758a686/sysdeps/posix/rewinddir.c
147e83
+++ glibc-2.17-c758a686/sysdeps/posix/rewinddir.c
147e83
@@ -33,6 +33,7 @@ rewinddir (dirp)
147e83
   dirp->filepos = 0;
147e83
   dirp->offset = 0;
147e83
   dirp->size = 0;
147e83
+  dirp->errcode = 0;
147e83
 #ifndef NOT_IN_libc
147e83
   __libc_lock_unlock (dirp->lock);
147e83
 #endif
147e83
diff --git glibc-2.17-c758a686/sysdeps/unix/sysv/linux/i386/readdir64_r.c glibc-2.17-c758a686/sysdeps/unix/sysv/linux/i386/readdir64_r.c
147e83
index 8ebbcfd..a7d114e 100644
147e83
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/i386/readdir64_r.c
147e83
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/i386/readdir64_r.c
147e83
@@ -18,7 +18,6 @@
147e83
 #define __READDIR_R __readdir64_r
147e83
 #define __GETDENTS __getdents64
147e83
 #define DIRENT_TYPE struct dirent64
147e83
-#define GETDENTS_64BIT_ALIGNED 1
147e83
 
147e83
 #include <sysdeps/posix/readdir_r.c>
147e83
 
147e83
diff --git glibc-2.17-c758a686/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c glibc-2.17-c758a686/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
147e83
index 5ed8e95..290f2c8 100644
147e83
--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
147e83
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
147e83
@@ -1,5 +1,4 @@
147e83
 #define readdir64_r __no_readdir64_r_decl
147e83
-#define GETDENTS_64BIT_ALIGNED 1
147e83
 #include <sysdeps/posix/readdir_r.c>
147e83
 #undef readdir64_r
147e83
 weak_alias (__readdir_r, readdir64_r)