Commit db78b877 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 1025774c
...@@ -1796,14 +1796,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) ...@@ -1796,14 +1796,12 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
xid = GetXid(); xid = GetXid();
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
/* check if we have permission to change attrs */ attrs->ia_valid |= ATTR_FORCE;
rc = inode_change_ok(inode, attrs);
if (rc < 0) rc = inode_change_ok(inode, attrs);
goto out; if (rc < 0)
else goto out;
rc = 0;
}
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
...@@ -1934,14 +1932,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -1934,14 +1932,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
cFYI(1, "setattr on file %s attrs->iavalid 0x%x", cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
direntry->d_name.name, attrs->ia_valid); direntry->d_name.name, attrs->ia_valid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
/* check if we have permission to change attrs */ attrs->ia_valid |= ATTR_FORCE;
rc = inode_change_ok(inode, attrs);
if (rc < 0) { rc = inode_change_ok(inode, attrs);
FreeXid(xid); if (rc < 0) {
return rc; FreeXid(xid);
} else return rc;
rc = 0;
} }
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
......
...@@ -387,21 +387,6 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -387,21 +387,6 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
unsigned int ia_valid; unsigned int ia_valid;
int error; 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. */ /* Check for setting the inode time. */
ia_valid = attr->ia_valid; ia_valid = attr->ia_valid;
if (ia_valid & TIMES_SET_FLAGS) { if (ia_valid & TIMES_SET_FLAGS) {
...@@ -417,6 +402,21 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -417,6 +402,21 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
goto out; 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) && if (((attr->ia_valid & ATTR_UID) &&
(attr->ia_uid != sbi->options.fs_uid)) || (attr->ia_uid != sbi->options.fs_uid)) ||
((attr->ia_valid & ATTR_GID) && ((attr->ia_valid & ATTR_GID) &&
......
...@@ -1270,11 +1270,12 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, ...@@ -1270,11 +1270,12 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
if (!fuse_allow_task(fc, current)) if (!fuse_allow_task(fc, current))
return -EACCES; return -EACCES;
if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
err = inode_change_ok(inode, attr); attr->ia_valid |= ATTR_FORCE;
if (err)
return err; err = inode_change_ok(inode, attr);
} if (err)
return err;
if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc) if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc)
return 0; return 0;
......
...@@ -232,16 +232,16 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -232,16 +232,16 @@ static int logfs_setattr(struct dentry *dentry, struct iattr *attr)
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int err = 0; int err = 0;
err = inode_change_ok(inode, attr);
if (err)
return err;
if (attr->ia_valid & ATTR_SIZE) { if (attr->ia_valid & ATTR_SIZE) {
err = logfs_truncate(inode, attr->ia_size); err = logfs_truncate(inode, attr->ia_size);
if (err) if (err)
return err; return err;
} }
err = inode_change_ok(inode, attr);
if (err)
return err;
setattr_copy(inode, attr); setattr_copy(inode, attr);
mark_inode_dirty(inode); mark_inode_dirty(inode);
return 0; return 0;
......
...@@ -3084,6 +3084,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3084,6 +3084,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
int depth; int depth;
int error; int error;
error = inode_change_ok(inode, attr);
if (error)
return error;
/* must be turned off for recursive notify_change calls */ /* must be turned off for recursive notify_change calls */
ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
...@@ -3133,10 +3137,6 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3133,10 +3137,6 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
goto out; goto out;
} }
error = inode_change_ok(inode, attr);
if (error)
goto out;
if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
......
...@@ -767,6 +767,10 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) ...@@ -767,6 +767,10 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
loff_t newsize = attr->ia_size; loff_t newsize = attr->ia_size;
int error; int error;
error = inode_change_ok(inode, attr);
if (error)
return error;
if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE) if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)
&& newsize != inode->i_size) { && newsize != inode->i_size) {
struct page *page = NULL; struct page *page = NULL;
...@@ -809,11 +813,9 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) ...@@ -809,11 +813,9 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
shmem_truncate_range(inode, newsize, (loff_t)-1); shmem_truncate_range(inode, newsize, (loff_t)-1);
} }
error = inode_change_ok(inode, attr); setattr_copy(inode, attr);
if (!error)
setattr_copy(inode, attr);
#ifdef CONFIG_TMPFS_POSIX_ACL #ifdef CONFIG_TMPFS_POSIX_ACL
if (!error && (attr->ia_valid & ATTR_MODE)) if (attr->ia_valid & ATTR_MODE)
error = generic_acl_chmod(inode); error = generic_acl_chmod(inode);
#endif #endif
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment