From bf4374c54589a5e01f37a14c1064beab51743434 Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 4 Apr 2015 20:22:12 +0000 Subject: [PATCH] fts: Don't return FTS_SLNONE if it's not a symlink (if race). When following symlinks, fts returned FTS_SLNONE when fstatat(flag=0) failed, but a subsequent fstatat(flag=AT_SYMLINK_NOFOLLOW) succeeded. This incorrectly triggered if a filename existed to be read from the directory, was deleted before the fstatat(flag=0) and created again after the fstatat(flag=0). Fix this by only returning FTS_SLNONE if the result from fstatat(flag=AT_SYMLINK_NOFOLLOW) is actually a symlink. If it is not a symlink, treat it as if fstatat(flag=0) succeeded. PR: 196724 Reported and tested by: pho MFC after: 1 week --- lib/libc/gen/fts.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c index 7635fbc3526..1ca8334acc6 100644 --- a/lib/libc/gen/fts.c +++ b/lib/libc/gen/fts.c @@ -905,12 +905,13 @@ fts_stat(FTS *sp, FTSENT *p, int follow, int dfd) if (ISSET(FTS_LOGICAL) || follow) { if (fstatat(dfd, path, sbp, 0)) { saved_errno = errno; - if (!fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { - errno = 0; - return (FTS_SLNONE); + if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { + p->fts_errno = saved_errno; + goto err; } - p->fts_errno = saved_errno; - goto err; + errno = 0; + if (S_ISLNK(sbp->st_mode)) + return (FTS_SLNONE); } } else if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { p->fts_errno = errno; -- 2.45.0