aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/inode.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2005-08-16 11:49:44 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-08-16 12:30:58 -0400
commit65e4308d2500e7daf60c3dccc202c61ffb066c63 (patch)
tree76a2e00004f645d09b2e59b485fb2aea0af45234 /fs/nfs/inode.c
parent367ae3cd74bdc2ad32d71293427fec570b14ddcd (diff)
[PATCH] NFS: Ensure we always update inode->i_mode when doing O_EXCL creates
When the client performs an exclusive create and opens the file for writing, a Netapp filer will first create the file using the mode 01777. It does this since an NFSv3/v4 exclusive create cannot immediately set the mode bits. The 01777 mode then gets put into the inode->i_mode. After the file creation is successful, we then do a setattr to change the mode to the correct value (as per the NFS spec). The problem is that nfs_refresh_inode() no longer updates inode->i_mode, so the latter retains the 01777 mode. A bit later, the VFS notices this, and calls remove_suid(). This of course now resets the file mode to inode->i_mode & 0777. Hey presto, the file mode on the server is now magically changed to 0777. Duh... Fixes http://bugzilla.linux-nfs.org/show_bug.cgi?id=32 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r--fs/nfs/inode.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 4845911f1c63..bb7ca022bcb2 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -814,28 +814,39 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
814 nfs_wb_all(inode); 814 nfs_wb_all(inode);
815 } 815 }
816 error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); 816 error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
817 if (error == 0) { 817 if (error == 0)
818 nfs_refresh_inode(inode, &fattr); 818 nfs_refresh_inode(inode, &fattr);
819 nfs_end_data_update(inode);
820 unlock_kernel();
821 return error;
822}
823
824/**
825 * nfs_setattr_update_inode - Update inode metadata after a setattr call.
826 * @inode: pointer to struct inode
827 * @attr: pointer to struct iattr
828 *
829 * Note: we do this in the *proc.c in order to ensure that
830 * it works for things like exclusive creates too.
831 */
832void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
833{
834 if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
819 if ((attr->ia_valid & ATTR_MODE) != 0) { 835 if ((attr->ia_valid & ATTR_MODE) != 0) {
820 int mode; 836 int mode = attr->ia_mode & S_IALLUGO;
821 mode = inode->i_mode & ~S_IALLUGO; 837 mode |= inode->i_mode & ~S_IALLUGO;
822 mode |= attr->ia_mode & S_IALLUGO;
823 inode->i_mode = mode; 838 inode->i_mode = mode;
824 } 839 }
825 if ((attr->ia_valid & ATTR_UID) != 0) 840 if ((attr->ia_valid & ATTR_UID) != 0)
826 inode->i_uid = attr->ia_uid; 841 inode->i_uid = attr->ia_uid;
827 if ((attr->ia_valid & ATTR_GID) != 0) 842 if ((attr->ia_valid & ATTR_GID) != 0)
828 inode->i_gid = attr->ia_gid; 843 inode->i_gid = attr->ia_gid;
829 if ((attr->ia_valid & ATTR_SIZE) != 0) {
830 inode->i_size = attr->ia_size;
831 vmtruncate(inode, attr->ia_size);
832 }
833 }
834 if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
835 NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; 844 NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
836 nfs_end_data_update(inode); 845 }
837 unlock_kernel(); 846 if ((attr->ia_valid & ATTR_SIZE) != 0) {
838 return error; 847 inode->i_size = attr->ia_size;
848 vmtruncate(inode, attr->ia_size);
849 }
839} 850}
840 851
841/* 852/*