From b1f55699e4ca1e66987385edeff6859672e5a070 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 12 Aug 2017 11:20:41 -0700 Subject: [PATCH] fts: fix cloexec races MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * lib/fts.c [!_LIBC]: Do not include dirent--.h, unistd--.h, cloexec.h. (opendirat, diropen): Use O_CLOEXEC instead of set_cloexec_flag. (fts_build): Use F_DUPD_CLOEXEC rinstad of set_cloexec_flag. (fd_ring_check): Set cloexec flag on new file descriptors. (fts_build, fd_ring_check): While we’re at it, make sure the resulting file descriptor is not 0, 1, or 2, since that is easy. * modules/fts (Depends-on): Remove cloexec, dirent-safer, dup, fcntl-safer, unistd-safer. Add fcntl. --- ChangeLog | 10 ++++++++++ lib/fts.c | 27 ++++++++------------------- modules/fts | 6 +----- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b475437d7..c725f5d91f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2017-08-12 Paul Eggert + + fts: fix cloexec races + * lib/fts.c [!_LIBC]: Do not include dirent--.h, unistd--.h, cloexec.h. + (opendirat, diropen): Use O_CLOEXEC instead of set_cloexec_flag. + (fts_build): Use F_DUPD_CLOEXEC rinstad of set_cloexec_flag. + (fd_ring_check): Set cloexec flag on new file descriptors. + (fts_build, fd_ring_check): While we’re at it, make sure the + resulting file descriptor is not 0, 1, or 2, since that is easy. + 2017-08-11 Bruno Haible fts tests: Fix link error. diff --git a/lib/fts.c b/lib/fts.c index bf8edf8211..ffa41130a2 100644 --- a/lib/fts.c +++ b/lib/fts.c @@ -71,11 +71,6 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; #if ! _LIBC # include "fcntl--.h" -# include "dirent--.h" -# include "unistd--.h" -/* FIXME - use fcntl(F_DUPFD_CLOEXEC)/openat(O_CLOEXEC) once they are - supported. */ -# include "cloexec.h" # include "flexmember.h" # include "openat.h" # include "same-inode.h" @@ -305,14 +300,13 @@ static DIR * internal_function opendirat (int fd, char const *dir, int extra_flags, int *pdir_fd) { - int new_fd = openat (fd, dir, - (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK - | extra_flags)); + int open_flags = (O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOCTTY + | O_NONBLOCK | extra_flags); + int new_fd = openat (fd, dir, open_flags); DIR *dirp; if (new_fd < 0) return NULL; - set_cloexec_flag (new_fd, true); dirp = fdopendir (new_fd); if (dirp) *pdir_fd = new_fd; @@ -375,15 +369,13 @@ static int internal_function diropen (FTS const *sp, char const *dir) { - int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK + int open_flags = (O_SEARCH | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0) | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)); int fd = (ISSET (FTS_CWDFD) ? openat (sp->fts_cwd_fd, dir, open_flags) : open (dir, open_flags)); - if (0 <= fd) - set_cloexec_flag (fd, true); return fd; } @@ -1435,11 +1427,7 @@ fts_build (register FTS *sp, int type) if (descend || type == BREAD) { if (ISSET(FTS_CWDFD)) - { - dir_fd = dup (dir_fd); - if (0 <= dir_fd) - set_cloexec_flag (dir_fd, true); - } + dir_fd = fcntl (dir_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1); if (dir_fd < 0 || fts_safe_changedir(sp, cur, dir_fd, NULL)) { if (descend && type == BREAD) cur->fts_errno = errno; @@ -1781,7 +1769,7 @@ fd_ring_check (FTS const *sp) I_ring fd_w = sp->fts_fd_ring; int cwd_fd = sp->fts_cwd_fd; - cwd_fd = dup (cwd_fd); + cwd_fd = fcntl (cwd_fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1); char *dot = getcwdat (cwd_fd, NULL, 0); error (0, 0, "===== check ===== cwd: %s", dot); free (dot); @@ -1790,7 +1778,8 @@ fd_ring_check (FTS const *sp) int fd = i_ring_pop (&fd_w); if (0 <= fd) { - int parent_fd = openat (cwd_fd, "..", O_SEARCH | O_NOATIME); + int open_flags = O_SEARCH | O_CLOEXEC | O_NOATIME; + int parent_fd = openat (cwd_fd, "..", open_flags); if (parent_fd < 0) { // Warn? diff --git a/modules/fts b/modules/fts index 55c09e7c95..ecbca70b54 100644 --- a/modules/fts +++ b/modules/fts @@ -8,16 +8,13 @@ lib/fts-cycle.c m4/fts.m4 Depends-on: -cloexec closedir cycle-check d-ino d-type -dirent-safer -dup fchdir +fcntl fcntl-h -fcntl-safer fdopendir flexmember fstat @@ -32,7 +29,6 @@ readdir stdalign stdbool stddef -unistd-safer configure.ac: gl_FUNC_FTS -- 2.39.5