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>
This commit is contained in:
parent
1025774ce4
commit
db78b877f7
|
@ -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);
|
rc = inode_change_ok(inode, attrs);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
else
|
|
||||||
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)
|
||||||
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);
|
rc = inode_change_ok(inode, attrs);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
} else
|
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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))
|
||||||
|
attr->ia_valid |= ATTR_FORCE;
|
||||||
|
|
||||||
err = inode_change_ok(inode, attr);
|
err = inode_change_ok(inode, attr);
|
||||||
if (err)
|
if (err)
|
||||||
return 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
shmem_truncate_range(inode, newsize, (loff_t)-1);
|
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
|
#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;
|
||||||
|
|
Loading…
Reference in New Issue