diff options
author | Christoph Hellwig <hch@lst.de> | 2010-06-04 11:30:03 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:47:38 -0400 |
commit | db78b877f7744bec4a9d9f9e7d10da3931d7cd39 (patch) | |
tree | fd9ee2fbe0998218b6d90322f85b285887e6fe9d /fs | |
parent | 1025774ce411f2bd4b059ad7b53f0003569b74fa (diff) | |
download | linux-db78b877f7744bec4a9d9f9e7d10da3931d7cd39.tar.bz2 |
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 <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/inode.c | 29 | ||||
-rw-r--r-- | fs/fat/file.c | 30 | ||||
-rw-r--r-- | fs/fuse/dir.c | 11 | ||||
-rw-r--r-- | fs/logfs/file.c | 8 | ||||
-rw-r--r-- | fs/reiserfs/inode.c | 8 |
5 files changed, 42 insertions, 44 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 9c6a40f5cc57..b95f4a5af013 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 20813d2c7d61..b2eedcee7516 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 3cdc5f78a406..43a9b3730a98 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 23b4d03bbd26..4dd0f7c06e39 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 2b8dc5c22867..46ba1cfc2df3 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; |