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@xxxxxx> Index: linux-2.6/fs/cifs/inode.c =================================================================== --- linux-2.6.orig/fs/cifs/inode.c 2010-06-01 12:19:48.004255568 +0200 +++ linux-2.6/fs/cifs/inode.c 2010-06-01 12:20:04.402023064 +0200 @@ -1776,14 +1776,12 @@ cifs_setattr_unix(struct dentry *direntr 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) { @@ -1914,14 +1912,13 @@ cifs_setattr_nounix(struct dentry *diren 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); Index: linux-2.6/fs/fat/file.c =================================================================== --- linux-2.6.orig/fs/fat/file.c 2010-06-01 12:19:23.681011749 +0200 +++ linux-2.6/fs/fat/file.c 2010-06-01 12:21:01.134027230 +0200 @@ -387,21 +387,6 @@ int fat_setattr(struct dentry *dentry, s 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, s 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) && Index: linux-2.6/fs/fuse/dir.c =================================================================== --- linux-2.6.orig/fs/fuse/dir.c 2010-06-01 12:19:23.688003647 +0200 +++ linux-2.6/fs/fuse/dir.c 2010-06-01 12:20:04.409254311 +0200 @@ -1270,11 +1270,12 @@ static int fuse_do_setattr(struct dentry 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; Index: linux-2.6/fs/logfs/file.c =================================================================== --- linux-2.6.orig/fs/logfs/file.c 2010-06-01 12:19:48.056005672 +0200 +++ linux-2.6/fs/logfs/file.c 2010-06-01 12:20:04.412282458 +0200 @@ -232,16 +232,16 @@ static int logfs_setattr(struct dentry * 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; Index: linux-2.6/fs/reiserfs/inode.c =================================================================== --- linux-2.6.orig/fs/reiserfs/inode.c 2010-06-01 12:19:48.162005532 +0200 +++ linux-2.6/fs/reiserfs/inode.c 2010-06-01 12:20:28.959005660 +0200 @@ -3086,6 +3086,10 @@ int reiserfs_setattr(struct dentry *dent 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); @@ -3135,10 +3139,6 @@ int reiserfs_setattr(struct dentry *dent 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; Index: linux-2.6/mm/shmem.c =================================================================== --- linux-2.6.orig/mm/shmem.c 2010-06-01 12:19:23.712004415 +0200 +++ linux-2.6/mm/shmem.c 2010-06-01 12:20:04.424255568 +0200 @@ -766,6 +766,10 @@ static int shmem_notify_change(struct de struct inode *inode = dentry->d_inode; int error; + error = inode_change_ok(inode, attr); + if (error) + return error; + if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { loff_t newsize = attr->ia_size; struct page *page = NULL; @@ -808,11 +812,9 @@ static int shmem_notify_change(struct de 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; -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html