path: root/src/stat
diff options
authorRich Felker <>2015-02-05 23:34:27 -0500
committerRich Felker <>2015-03-30 01:43:48 -0400
commitd670873b7ed315001f5a9dcc5208b54c383c9176 (patch)
tree1030baa3ba354dc4a707b725fb4c825eb4869a82 /src/stat
parentc534aad07df48a130e342fb78304b80778d53c64 (diff)
fix failure of fchmodat to report EOPNOTSUPP in the race path
in the case where a non-symlink file was replaced by a symlink during the fchmodat operation with AT_SYMLINK_NOFOLLOW, mode change on the new symlink target was successfully suppressed, but the error was not reported. instead, fchmodat simply returned 0. (cherry picked from commit 61b1d102129990f6e903c6ddcf46c7d79d1a1e99) (conflicts from commit dd5f50da6f6c3df5647e922e47f8568a8896a752)
Diffstat (limited to 'src/stat')
1 files changed, 5 insertions, 2 deletions
diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c
index 94d0335c..d94667ae 100644
--- a/src/stat/fchmodat.c
+++ b/src/stat/fchmodat.c
@@ -28,8 +28,11 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
__procfdname(proc, fd2);
- if (!(ret = __syscall(SYS_stat, proc, &st)) && !S_ISLNK(st.st_mode))
- ret = __syscall(SYS_chmod, proc, mode);
+ ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0);
+ if (!ret) {
+ if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP;
+ else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
+ }
__syscall(SYS_close, fd2);
return __syscall_ret(ret);