]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Changed chown to chmod for Linux NFS Flush
authorShaun A. Johnson <shaun@linuxmagic.com>
Mon, 13 Aug 2018 23:43:04 +0000 (16:43 -0700)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 10 Sep 2019 07:01:51 +0000 (10:01 +0300)
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.

src/lib/nfs-workarounds.c

index bcbfcd757962d9760b878420b5e295fff852ffd6..4bbea8aa6e4cfa6bb6b53ab36a9d4fa2534eae14 100644 (file)
@@ -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
 }