OSDN Git Service

NFS: nfs_setattr_update_inode() should clear the suid/sgid bits
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Tue, 13 Apr 2021 00:08:00 +0000 (20:08 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Tue, 13 Apr 2021 00:11:44 +0000 (20:11 -0400)
When we do a 'chown' or 'chgrp', the server will clear the suid/sgid
bits. Ensure that we mirror that in nfs_setattr_update_inode().

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/inode.c

index 8c2d5f3..d34da63 100644 (file)
@@ -636,8 +636,7 @@ nfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
        }
 
        /* Optimization: if the end result is no change, don't RPC */
-       attr->ia_valid &= NFS_VALID_ATTRS;
-       if ((attr->ia_valid & ~(ATTR_FILE|ATTR_OPEN)) == 0)
+       if (((attr->ia_valid & NFS_VALID_ATTRS) & ~(ATTR_FILE|ATTR_OPEN)) == 0)
                return 0;
 
        trace_nfs_setattr_enter(inode);
@@ -719,6 +718,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
        }
        if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
                NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_CTIME;
+               if ((attr->ia_valid & ATTR_KILL_SUID) != 0 &&
+                   inode->i_mode & S_ISUID)
+                       inode->i_mode &= ~S_ISUID;
+               if ((attr->ia_valid & ATTR_KILL_SGID) != 0 &&
+                   (inode->i_mode & (S_ISGID | S_IXGRP)) ==
+                    (S_ISGID | S_IXGRP))
+                       inode->i_mode &= ~S_ISGID;
                if ((attr->ia_valid & ATTR_MODE) != 0) {
                        int mode = attr->ia_mode & S_IALLUGO;
                        mode |= inode->i_mode & ~S_IALLUGO;