diff options
author | Christoph Hellwig <hch@lst.de> | 2010-06-04 05:30:03 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:47:38 -0400 |
commit | db78b877f7744bec4a9d9f9e7d10da3931d7cd39 (patch) | |
tree | fd9ee2fbe0998218b6d90322f85b285887e6fe9d | |
parent | 1025774ce411f2bd4b059ad7b53f0003569b74fa (diff) |
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>
-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 | ||||
-rw-r--r-- | mm/shmem.c | 10 |
6 files changed, 48 insertions, 48 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) | |||
1796 | 1796 | ||
1797 | xid = GetXid(); | 1797 | xid = GetXid(); |
1798 | 1798 | ||
1799 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | 1799 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
1800 | /* check if we have permission to change attrs */ | 1800 | attrs->ia_valid |= ATTR_FORCE; |
1801 | rc = inode_change_ok(inode, attrs); | 1801 | |
1802 | if (rc < 0) | 1802 | rc = inode_change_ok(inode, attrs); |
1803 | goto out; | 1803 | if (rc < 0) |
1804 | else | 1804 | goto out; |
1805 | rc = 0; | ||
1806 | } | ||
1807 | 1805 | ||
1808 | full_path = build_path_from_dentry(direntry); | 1806 | full_path = build_path_from_dentry(direntry); |
1809 | if (full_path == NULL) { | 1807 | if (full_path == NULL) { |
@@ -1934,14 +1932,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1934 | cFYI(1, "setattr on file %s attrs->iavalid 0x%x", | 1932 | cFYI(1, "setattr on file %s attrs->iavalid 0x%x", |
1935 | direntry->d_name.name, attrs->ia_valid); | 1933 | direntry->d_name.name, attrs->ia_valid); |
1936 | 1934 | ||
1937 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | 1935 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
1938 | /* check if we have permission to change attrs */ | 1936 | attrs->ia_valid |= ATTR_FORCE; |
1939 | rc = inode_change_ok(inode, attrs); | 1937 | |
1940 | if (rc < 0) { | 1938 | rc = inode_change_ok(inode, attrs); |
1941 | FreeXid(xid); | 1939 | if (rc < 0) { |
1942 | return rc; | 1940 | FreeXid(xid); |
1943 | } else | 1941 | return rc; |
1944 | rc = 0; | ||
1945 | } | 1942 | } |
1946 | 1943 | ||
1947 | full_path = build_path_from_dentry(direntry); | 1944 | 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) | |||
387 | unsigned int ia_valid; | 387 | unsigned int ia_valid; |
388 | int error; | 388 | int error; |
389 | 389 | ||
390 | /* | ||
391 | * Expand the file. Since inode_setattr() updates ->i_size | ||
392 | * before calling the ->truncate(), but FAT needs to fill the | ||
393 | * hole before it. XXX: this is no longer true with new truncate | ||
394 | * sequence. | ||
395 | */ | ||
396 | if (attr->ia_valid & ATTR_SIZE) { | ||
397 | if (attr->ia_size > inode->i_size) { | ||
398 | error = fat_cont_expand(inode, attr->ia_size); | ||
399 | if (error || attr->ia_valid == ATTR_SIZE) | ||
400 | goto out; | ||
401 | attr->ia_valid &= ~ATTR_SIZE; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | /* Check for setting the inode time. */ | 390 | /* Check for setting the inode time. */ |
406 | ia_valid = attr->ia_valid; | 391 | ia_valid = attr->ia_valid; |
407 | if (ia_valid & TIMES_SET_FLAGS) { | 392 | if (ia_valid & TIMES_SET_FLAGS) { |
@@ -417,6 +402,21 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
417 | goto out; | 402 | goto out; |
418 | } | 403 | } |
419 | 404 | ||
405 | /* | ||
406 | * Expand the file. Since inode_setattr() updates ->i_size | ||
407 | * before calling the ->truncate(), but FAT needs to fill the | ||
408 | * hole before it. XXX: this is no longer true with new truncate | ||
409 | * sequence. | ||
410 | */ | ||
411 | if (attr->ia_valid & ATTR_SIZE) { | ||
412 | if (attr->ia_size > inode->i_size) { | ||
413 | error = fat_cont_expand(inode, attr->ia_size); | ||
414 | if (error || attr->ia_valid == ATTR_SIZE) | ||
415 | goto out; | ||
416 | attr->ia_valid &= ~ATTR_SIZE; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | if (((attr->ia_valid & ATTR_UID) && | 420 | if (((attr->ia_valid & ATTR_UID) && |
421 | (attr->ia_uid != sbi->options.fs_uid)) || | 421 | (attr->ia_uid != sbi->options.fs_uid)) || |
422 | ((attr->ia_valid & ATTR_GID) && | 422 | ((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, | |||
1270 | if (!fuse_allow_task(fc, current)) | 1270 | if (!fuse_allow_task(fc, current)) |
1271 | return -EACCES; | 1271 | return -EACCES; |
1272 | 1272 | ||
1273 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | 1273 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
1274 | err = inode_change_ok(inode, attr); | 1274 | attr->ia_valid |= ATTR_FORCE; |
1275 | if (err) | 1275 | |
1276 | return err; | 1276 | err = inode_change_ok(inode, attr); |
1277 | } | 1277 | if (err) |
1278 | return err; | ||
1278 | 1279 | ||
1279 | if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc) | 1280 | if ((attr->ia_valid & ATTR_OPEN) && fc->atomic_o_trunc) |
1280 | return 0; | 1281 | 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) | |||
232 | struct inode *inode = dentry->d_inode; | 232 | struct inode *inode = dentry->d_inode; |
233 | int err = 0; | 233 | int err = 0; |
234 | 234 | ||
235 | err = inode_change_ok(inode, attr); | ||
236 | if (err) | ||
237 | return err; | ||
238 | |||
235 | if (attr->ia_valid & ATTR_SIZE) { | 239 | if (attr->ia_valid & ATTR_SIZE) { |
236 | err = logfs_truncate(inode, attr->ia_size); | 240 | err = logfs_truncate(inode, attr->ia_size); |
237 | if (err) | 241 | if (err) |
238 | return err; | 242 | return err; |
239 | } | 243 | } |
240 | 244 | ||
241 | err = inode_change_ok(inode, attr); | ||
242 | if (err) | ||
243 | return err; | ||
244 | |||
245 | setattr_copy(inode, attr); | 245 | setattr_copy(inode, attr); |
246 | mark_inode_dirty(inode); | 246 | mark_inode_dirty(inode); |
247 | return 0; | 247 | 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) | |||
3084 | int depth; | 3084 | int depth; |
3085 | int error; | 3085 | int error; |
3086 | 3086 | ||
3087 | error = inode_change_ok(inode, attr); | ||
3088 | if (error) | ||
3089 | return error; | ||
3090 | |||
3087 | /* must be turned off for recursive notify_change calls */ | 3091 | /* must be turned off for recursive notify_change calls */ |
3088 | ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); | 3092 | ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); |
3089 | 3093 | ||
@@ -3133,10 +3137,6 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
3133 | goto out; | 3137 | goto out; |
3134 | } | 3138 | } |
3135 | 3139 | ||
3136 | error = inode_change_ok(inode, attr); | ||
3137 | if (error) | ||
3138 | goto out; | ||
3139 | |||
3140 | if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | 3140 | if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || |
3141 | (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | 3141 | (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { |
3142 | struct reiserfs_transaction_handle th; | 3142 | struct reiserfs_transaction_handle th; |
diff --git a/mm/shmem.c b/mm/shmem.c index 3b58ad65d26c..0a43505eeaec 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -767,6 +767,10 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) | |||
767 | loff_t newsize = attr->ia_size; | 767 | loff_t newsize = attr->ia_size; |
768 | int error; | 768 | int error; |
769 | 769 | ||
770 | error = inode_change_ok(inode, attr); | ||
771 | if (error) | ||
772 | return error; | ||
773 | |||
770 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE) | 774 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE) |
771 | && newsize != inode->i_size) { | 775 | && newsize != inode->i_size) { |
772 | struct page *page = NULL; | 776 | struct page *page = NULL; |
@@ -809,11 +813,9 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) | |||
809 | shmem_truncate_range(inode, newsize, (loff_t)-1); | 813 | shmem_truncate_range(inode, newsize, (loff_t)-1); |
810 | } | 814 | } |
811 | 815 | ||
812 | error = inode_change_ok(inode, attr); | 816 | setattr_copy(inode, attr); |
813 | if (!error) | ||
814 | setattr_copy(inode, attr); | ||
815 | #ifdef CONFIG_TMPFS_POSIX_ACL | 817 | #ifdef CONFIG_TMPFS_POSIX_ACL |
816 | if (!error && (attr->ia_valid & ATTR_MODE)) | 818 | if (attr->ia_valid & ATTR_MODE) |
817 | error = generic_acl_chmod(inode); | 819 | error = generic_acl_chmod(inode); |
818 | #endif | 820 | #endif |
819 | return error; | 821 | return error; |