changeset 13674:5c447be5815d

fts: use O_NOFOLLOW to avoid race condition when opening a directory * lib/fts.c (opendirat): New arg extra_flags. (__opendir2): Use it to avoid following symlinks when opening a directory, if symlinks are not supposed to be followed. See <http://lists.gnu.org/archive/html/bug-gnulib/2010-09/msg00213.html>.
author Paul Eggert <eggert@cs.ucla.edu>
date Mon, 13 Sep 2010 12:38:41 -0700
parents 8a0919c1c14c
children a973123e4b73
files ChangeLog lib/fts.c
diffstat 2 files changed, 14 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2010-09-13  Paul Eggert  <eggert@cs.ucla.edu>
 
+	fts: use O_NOFOLLOW to avoid race condition when opening a directory
+	* lib/fts.c (opendirat): New arg extra_flags.
+	(__opendir2): Use it to avoid following symlinks when opening
+	a directory, if symlinks are not supposed to be followed.  See
+	<http://lists.gnu.org/archive/html/bug-gnulib/2010-09/msg00213.html>.
+
 	fdopendir: preserve argument fd before returning
 	* lib/fdopendir.c: Adjust comments to say POSIX, not Solaris.
 	(fdopendir_with_dup, fd_clone_opendir): New static functions.
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -290,10 +290,11 @@
 /* FIXME: if others need this function, move it into lib/openat.c */
 static inline DIR *
 internal_function
-opendirat (int fd, char const *dir)
+opendirat (int fd, char const *dir, int extra_flags)
 {
   int new_fd = openat (fd, dir,
-                       O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
+                       (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+                        | extra_flags));
   DIR *dirp;
 
   if (new_fd < 0)
@@ -1237,7 +1238,11 @@
 #else
 # define __opendir2(file, flag) \
         ( ! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
-          ? opendirat(sp->fts_cwd_fd, file)        \
+          ? opendirat(sp->fts_cwd_fd, file,        \
+                      ((ISSET(FTS_PHYSICAL)                   \
+                        && ! (cur->fts_level == FTS_ROOTLEVEL \
+                              && ISSET(FTS_COMFOLLOW)))       \
+                       ? O_NOFOLLOW : 0))                     \
           : opendir(file))
 #endif
        if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {