diff options
author | Rich Felker <dalias@aerifal.cx> | 2020-06-15 18:59:59 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2020-06-15 19:09:46 -0400 |
commit | 4bd22b8f3e6ffa8f43ea73e7bb6276aafb5a7743 (patch) | |
tree | 03503c03d8951ffcaa3e00b11c11d1ba34bab980 /src/misc/nftw.c | |
parent | ca36573ecfbbef7a1563aaa1a8486081f8c9fdda (diff) | |
download | musl-4bd22b8f3e6ffa8f43ea73e7bb6276aafb5a7743.tar.gz musl-4bd22b8f3e6ffa8f43ea73e7bb6276aafb5a7743.tar.bz2 musl-4bd22b8f3e6ffa8f43ea73e7bb6276aafb5a7743.tar.xz musl-4bd22b8f3e6ffa8f43ea73e7bb6276aafb5a7743.zip |
fix invalid use of access function in nftw
access always computes result with real ids not effective ones, so it
is not a valid means of determining whether the directory is readable.
instead, attempt to open it before reporting whether it's readable,
and then use fdopendir rather than opendir to open and read the
entries.
effort is made here to keep fd_limit behavior the same as before even
if it was not correct.
Diffstat (limited to 'src/misc/nftw.c')
-rw-r--r-- | src/misc/nftw.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/misc/nftw.c b/src/misc/nftw.c index 0a464100..8dcff7fe 100644 --- a/src/misc/nftw.c +++ b/src/misc/nftw.c @@ -1,5 +1,6 @@ #include <ftw.h> #include <dirent.h> +#include <fcntl.h> #include <sys/stat.h> #include <errno.h> #include <unistd.h> @@ -26,6 +27,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct history new; int type; int r; + int dfd; + int err; struct FTW lev; if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) { @@ -34,8 +37,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, else if (errno != EACCES) return -1; else type = FTW_NS; } else if (S_ISDIR(st.st_mode)) { - if (access(path, R_OK) < 0) type = FTW_DNR; - else if (flags & FTW_DEPTH) type = FTW_DP; + if (flags & FTW_DEPTH) type = FTW_DP; else type = FTW_D; } else if (S_ISLNK(st.st_mode)) { if (flags & FTW_PHYS) type = FTW_SL; @@ -63,6 +65,13 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, lev.base = k; } + if (type == FTW_D || type == FTW_DP) { + dfd = open(path, O_RDONLY); + err = errno; + if (dfd < 0 && err == EACCES) type = FTW_DNR; + if (!fd_limit) close(dfd); + } + if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev))) return r; @@ -71,7 +80,11 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, return 0; if ((type == FTW_D || type == FTW_DP) && fd_limit) { - DIR *d = opendir(path); + if (dfd < 0) { + errno = err; + return -1; + } + DIR *d = fdopendir(dfd); if (d) { struct dirent *de; while ((de = readdir(d))) { @@ -92,7 +105,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, } } closedir(d); - } else if (errno != EACCES) { + } else { + close(dfd); return -1; } } |