From: Shaun A. Johnson Date: Mon, 13 Aug 2018 23:43:04 +0000 (-0700) Subject: lib: Changed chown to chmod for Linux NFS Flush X-Git-Tag: 2.3.9~414 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7d4375dd8f7c67f630d7be272dc0873ba4857612;p=thirdparty%2Fdovecot%2Fcore.git lib: Changed chown to chmod for Linux NFS Flush This change switches the chown call to a chmod call in the function nfs_flush_chown_uid because the chown call was resulting in certain permission bits being dropped when the nfs attributes were flushed. Functionality for FreeBSD/Solaris was left unchanged. --- diff --git a/src/lib/nfs-workarounds.c b/src/lib/nfs-workarounds.c index bcbfcd7579..4bbea8aa6e 100644 --- a/src/lib/nfs-workarounds.c +++ b/src/lib/nfs-workarounds.c @@ -146,10 +146,9 @@ int nfs_safe_link(const char *oldpath, const char *newpath, bool links1) static void nfs_flush_chown_uid(const char *path) { - uid_t uid; #ifdef ATTRCACHE_FLUSH_CHOWN_UID_1 - uid = (uid_t)-1; + uid_t uid = (uid_t)-1; if (chown(path, uid, (gid_t)-1) < 0) { if (errno == ESTALE || errno == EPERM || errno == ENOENT) { /* attr cache is flushed */ @@ -164,9 +163,9 @@ static void nfs_flush_chown_uid(const char *path) #else struct stat st; - if (stat(path, &st) == 0) - uid = st.st_uid; - else { + if (stat(path, &st) == 0) { + /* do nothing */ + } else { if (errno == ESTALE) { /* ESTALE causes the OS to flush the attr cache */ return; @@ -178,8 +177,10 @@ static void nfs_flush_chown_uid(const char *path) i_error("nfs_flush_chown_uid: stat(%s) failed: %m", path); return; } - if (chown(path, uid, (gid_t)-1) < 0) { - if (errno == ESTALE || errno == EPERM || errno == ENOENT) { + /* we use chmod for this operation since chown has been seen to drop S_UID + and S_GID bits from directory inodes in certain conditions */ + if (chmod(path, st.st_mode & 07777) < 0) { + if (errno == EPERM) { /* attr cache is flushed */ return; } @@ -187,7 +188,8 @@ static void nfs_flush_chown_uid(const char *path) nfs_flush_file_handle_cache_parent_dir(path); return; } - i_error("nfs_flush_chown_uid: chown(%s) failed: %m", path); + i_error("nfs_flush_chown_uid: chmod(%s, %04o) failed: %m", + path, st.st_mode & 07777); } #endif }