From db78b877f7744bec4a9d9f9e7d10da3931d7cd39 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Jun 2010 11:30:03 +0200 Subject: [PATCH] always call inode_change_ok early in ->setattr Make sure we call inode_change_ok before doing any changes in ->setattr, and make sure to call it even if our fs wants to ignore normal UNIX permissions, but use the ATTR_FORCE to skip those. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/cifs/inode.c | 29 +++++++++++++---------------- fs/fat/file.c | 30 +++++++++++++++--------------- fs/fuse/dir.c | 11 ++++++----- fs/logfs/file.c | 8 ++++---- fs/reiserfs/inode.c | 8 ++++---- mm/shmem.c | 10 ++++++---- 6 files changed, 48 insertions(+), 48 deletions(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9c6a40f5cc5..b95f4a5af01 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1796,14 +1796,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) xid = GetXid(); - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { - /* check if we have permission to change attrs */ - rc = inode_change_ok(inode, attrs); - if (rc < 0) - goto out; - else - rc = 0; - } + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) + attrs->ia_valid |= ATTR_FORCE; + + rc = inode_change_ok(inode, attrs); + if (rc < 0) + goto out; full_path = build_path_from_dentry(direntry); if (full_path == NULL) { @@ -1934,14 +1932,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) cFYI(1, "setattr on file %s attrs->iavalid 0x%x", direntry->d_name.name, attrs->ia_valid); - if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { - /* check if we have permission to change attrs */ - rc = inode_change_ok(inode, attrs); - if (rc < 0) { - FreeXid(xid); - return rc; - } else - rc = 0; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) + attrs->ia_valid |= ATTR_FORCE; + + rc = inode_change_ok(inode, attrs); + if (rc < 0) { + FreeXid(xid); + return rc; } full_path = build_path_from_dentry(direntry); diff --git a/fs/fat/file.c b/fs/fat/file.c index 20813d2c7d6..b2eedcee751 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -387,21 +387,6 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) unsigned int ia_valid; int error; - /* - * Expand the file. Since inode_setattr() updates ->i_size - * before calling the ->truncate(), but FAT needs to fill the - * hole before it. XXX: this is no longer true with new truncate - * sequence. - */ - if (attr->ia_valid & ATTR_SIZE) { - if (attr->ia_size > inode->i_size) { - error = fat_cont_expand(inode, attr->ia_size); - if (error || attr->ia_valid == ATTR_SIZE) - goto out; - attr->ia_valid &= ~ATTR_SIZE; - } - } - /* Check for setting the inode time. */ ia_valid = attr->ia_valid; if (ia_valid & TIMES_SET_FLAGS) { @@ -417,6 +402,21 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) goto out; } + /* + * Expand the file. Since inode_setattr() updates ->i_size + * before calling the ->truncate(), but FAT needs to fill the + * hole before it. XXX: this is no longer true with new truncate + * sequence. + */ + if (attr->ia_valid & ATTR_SIZE) { + if (attr->ia_size > inode->i_size) { + error = fat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + goto out; + attr->ia_valid &= ~ATTR_SIZE; + } + } + if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != sbi->options.fs_uid)) || ((attr->ia_valid & ATTR_GID) && diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 3cdc5f78a40..43a9b3730a9 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1270,11 +1270,12 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, if (!fuse_allow_task(fc, current)) return -EACCES; - if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { - err = inode_change_ok(inode, attr); - if (err) - return err; - } + if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) + attr->ia_valid |= ATTR_FORCE; + + err = inode_change_ok(inode, attr); + if (err) + return err; if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc) return 0; diff --git a/fs/logfs/file.c b/fs/logfs/file.c index 23b4d03bbd2..4dd0f7c06e3 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -232,16 +232,16 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int err = 0; + err = inode_change_ok(inode, attr); + if (err) + return err; + if (attr->ia_valid & ATTR_SIZE) { err = logfs_truncate(inode, attr->ia_size); if (err) return err; } - err = inode_change_ok(inode, attr); - if (err) - return err; - setattr_copy(inode, attr); mark_inode_dirty(inode); return 0; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 2b8dc5c2286..46ba1cfc2df 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -3084,6 +3084,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) int depth; int error; + error = inode_change_ok(inode, attr); + if (error) + return error; + /* must be turned off for recursive notify_change calls */ ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); @@ -3133,10 +3137,6 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) goto out; } - error = inode_change_ok(inode, attr); - if (error) - goto out; - if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { struct reiserfs_transaction_handle th; diff --git a/mm/shmem.c b/mm/shmem.c index 3b58ad65d26..0a43505eeae 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -767,6 +767,10 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) loff_t newsize = attr->ia_size; int error; + error = inode_change_ok(inode, attr); + if (error) + return error; + if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE) && newsize != inode->i_size) { struct page *page = NULL; @@ -809,11 +813,9 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) shmem_truncate_range(inode, newsize, (loff_t)-1); } - error = inode_change_ok(inode, attr); - if (!error) - setattr_copy(inode, attr); + setattr_copy(inode, attr); #ifdef CONFIG_TMPFS_POSIX_ACL - if (!error && (attr->ia_valid & ATTR_MODE)) + if (attr->ia_valid & ATTR_MODE) error = generic_acl_chmod(inode); #endif return error;