diff options
Diffstat (limited to 'fs')
50 files changed, 215 insertions, 130 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 12d602351dbe..6e58c4ca1e6e 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c | |||
| @@ -91,11 +91,14 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) | |||
| 91 | return acl; | 91 | return acl; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | int v9fs_check_acl(struct inode *inode, int mask) | 94 | int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 95 | { | 95 | { |
| 96 | struct posix_acl *acl; | 96 | struct posix_acl *acl; |
| 97 | struct v9fs_session_info *v9ses; | 97 | struct v9fs_session_info *v9ses; |
| 98 | 98 | ||
| 99 | if (flags & IPERM_FLAG_RCU) | ||
| 100 | return -ECHILD; | ||
| 101 | |||
| 99 | v9ses = v9fs_inode2v9ses(inode); | 102 | v9ses = v9fs_inode2v9ses(inode); |
| 100 | if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) { | 103 | if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) { |
| 101 | /* | 104 | /* |
diff --git a/fs/9p/acl.h b/fs/9p/acl.h index 59e18c2e8c7e..7ef3ac9f6d95 100644 --- a/fs/9p/acl.h +++ b/fs/9p/acl.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #ifdef CONFIG_9P_FS_POSIX_ACL | 17 | #ifdef CONFIG_9P_FS_POSIX_ACL |
| 18 | extern int v9fs_get_acl(struct inode *, struct p9_fid *); | 18 | extern int v9fs_get_acl(struct inode *, struct p9_fid *); |
| 19 | extern int v9fs_check_acl(struct inode *inode, int mask); | 19 | extern int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags); |
| 20 | extern int v9fs_acl_chmod(struct dentry *); | 20 | extern int v9fs_acl_chmod(struct dentry *); |
| 21 | extern int v9fs_set_create_acl(struct dentry *, | 21 | extern int v9fs_set_create_acl(struct dentry *, |
| 22 | struct posix_acl *, struct posix_acl *); | 22 | struct posix_acl *, struct posix_acl *); |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index cca8eef736fc..6d4bc1c8ff60 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -624,7 +624,7 @@ extern void afs_clear_permits(struct afs_vnode *); | |||
| 624 | extern void afs_cache_permit(struct afs_vnode *, struct key *, long); | 624 | extern void afs_cache_permit(struct afs_vnode *, struct key *, long); |
| 625 | extern void afs_zap_permits(struct rcu_head *); | 625 | extern void afs_zap_permits(struct rcu_head *); |
| 626 | extern struct key *afs_request_key(struct afs_cell *); | 626 | extern struct key *afs_request_key(struct afs_cell *); |
| 627 | extern int afs_permission(struct inode *, int); | 627 | extern int afs_permission(struct inode *, int, unsigned int); |
| 628 | 628 | ||
| 629 | /* | 629 | /* |
| 630 | * server.c | 630 | * server.c |
diff --git a/fs/afs/security.c b/fs/afs/security.c index bb4ed144d0e4..f44b9d355377 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c | |||
| @@ -285,13 +285,16 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key, | |||
| 285 | * - AFS ACLs are attached to directories only, and a file is controlled by its | 285 | * - AFS ACLs are attached to directories only, and a file is controlled by its |
| 286 | * parent directory's ACL | 286 | * parent directory's ACL |
| 287 | */ | 287 | */ |
| 288 | int afs_permission(struct inode *inode, int mask) | 288 | int afs_permission(struct inode *inode, int mask, unsigned int flags) |
| 289 | { | 289 | { |
| 290 | struct afs_vnode *vnode = AFS_FS_I(inode); | 290 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 291 | afs_access_t uninitialized_var(access); | 291 | afs_access_t uninitialized_var(access); |
| 292 | struct key *key; | 292 | struct key *key; |
| 293 | int ret; | 293 | int ret; |
| 294 | 294 | ||
| 295 | if (flags & IPERM_FLAG_RCU) | ||
| 296 | return -ECHILD; | ||
| 297 | |||
| 295 | _enter("{{%x:%u},%lx},%x,", | 298 | _enter("{{%x:%u},%lx},%x,", |
| 296 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask); | 299 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask); |
| 297 | 300 | ||
| @@ -347,7 +350,7 @@ int afs_permission(struct inode *inode, int mask) | |||
| 347 | } | 350 | } |
| 348 | 351 | ||
| 349 | key_put(key); | 352 | key_put(key); |
| 350 | ret = generic_permission(inode, mask, NULL); | 353 | ret = generic_permission(inode, mask, flags, NULL); |
| 351 | _leave(" = %d", ret); | 354 | _leave(" = %d", ret); |
| 352 | return ret; | 355 | return ret; |
| 353 | 356 | ||
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index f024d8aaddef..9ad2369d9e35 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
| @@ -229,8 +229,11 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer, | |||
| 229 | return -EIO; | 229 | return -EIO; |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | static int bad_inode_permission(struct inode *inode, int mask) | 232 | static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags) |
| 233 | { | 233 | { |
| 234 | if (flags & IPERM_FLAG_RCU) | ||
| 235 | return -ECHILD; | ||
| 236 | |||
| 234 | return -EIO; | 237 | return -EIO; |
| 235 | } | 238 | } |
| 236 | 239 | ||
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 2222d161c7b6..cb518a4b917c 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
| @@ -185,13 +185,15 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, | |||
| 185 | return ret; | 185 | return ret; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | int btrfs_check_acl(struct inode *inode, int mask) | 188 | int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 189 | { | 189 | { |
| 190 | struct posix_acl *acl; | 190 | struct posix_acl *acl; |
| 191 | int error = -EAGAIN; | 191 | int error = -EAGAIN; |
| 192 | 192 | ||
| 193 | acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS); | 193 | if (flags & IPERM_FLAG_RCU) |
| 194 | return -ECHILD; | ||
| 194 | 195 | ||
| 196 | acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
| 195 | if (IS_ERR(acl)) | 197 | if (IS_ERR(acl)) |
| 196 | return PTR_ERR(acl); | 198 | return PTR_ERR(acl); |
| 197 | if (acl) { | 199 | if (acl) { |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index af52f6d7a4d8..a142d204b526 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -2544,7 +2544,7 @@ int btrfs_sync_fs(struct super_block *sb, int wait); | |||
| 2544 | 2544 | ||
| 2545 | /* acl.c */ | 2545 | /* acl.c */ |
| 2546 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL | 2546 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL |
| 2547 | int btrfs_check_acl(struct inode *inode, int mask); | 2547 | int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags); |
| 2548 | #else | 2548 | #else |
| 2549 | #define btrfs_check_acl NULL | 2549 | #define btrfs_check_acl NULL |
| 2550 | #endif | 2550 | #endif |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 63e4546b478a..5cf0db0081f9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -7211,11 +7211,14 @@ static int btrfs_set_page_dirty(struct page *page) | |||
| 7211 | return __set_page_dirty_nobuffers(page); | 7211 | return __set_page_dirty_nobuffers(page); |
| 7212 | } | 7212 | } |
| 7213 | 7213 | ||
| 7214 | static int btrfs_permission(struct inode *inode, int mask) | 7214 | static int btrfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 7215 | { | 7215 | { |
| 7216 | if (flags & IPERM_FLAG_RCU) | ||
| 7217 | return -ECHILD; | ||
| 7218 | |||
| 7216 | if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE)) | 7219 | if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE)) |
| 7217 | return -EACCES; | 7220 | return -EACCES; |
| 7218 | return generic_permission(inode, mask, btrfs_check_acl); | 7221 | return generic_permission(inode, mask, flags, btrfs_check_acl); |
| 7219 | } | 7222 | } |
| 7220 | 7223 | ||
| 7221 | static const struct inode_operations btrfs_dir_inode_operations = { | 7224 | static const struct inode_operations btrfs_dir_inode_operations = { |
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 47f8c8baf3b5..e61de4f7b99d 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
| @@ -1781,12 +1781,17 @@ int ceph_do_getattr(struct inode *inode, int mask) | |||
| 1781 | * Check inode permissions. We verify we have a valid value for | 1781 | * Check inode permissions. We verify we have a valid value for |
| 1782 | * the AUTH cap, then call the generic handler. | 1782 | * the AUTH cap, then call the generic handler. |
| 1783 | */ | 1783 | */ |
| 1784 | int ceph_permission(struct inode *inode, int mask) | 1784 | int ceph_permission(struct inode *inode, int mask, unsigned int flags) |
| 1785 | { | 1785 | { |
| 1786 | int err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED); | 1786 | int err; |
| 1787 | |||
| 1788 | if (flags & IPERM_FLAG_RCU) | ||
| 1789 | return -ECHILD; | ||
| 1790 | |||
| 1791 | err = ceph_do_getattr(inode, CEPH_CAP_AUTH_SHARED); | ||
| 1787 | 1792 | ||
| 1788 | if (!err) | 1793 | if (!err) |
| 1789 | err = generic_permission(inode, mask, NULL); | 1794 | err = generic_permission(inode, mask, flags, NULL); |
| 1790 | return err; | 1795 | return err; |
| 1791 | } | 1796 | } |
| 1792 | 1797 | ||
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 7f01728a4657..4553d8829edb 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
| @@ -665,7 +665,7 @@ extern void ceph_queue_invalidate(struct inode *inode); | |||
| 665 | extern void ceph_queue_writeback(struct inode *inode); | 665 | extern void ceph_queue_writeback(struct inode *inode); |
| 666 | 666 | ||
| 667 | extern int ceph_do_getattr(struct inode *inode, int mask); | 667 | extern int ceph_do_getattr(struct inode *inode, int mask); |
| 668 | extern int ceph_permission(struct inode *inode, int mask); | 668 | extern int ceph_permission(struct inode *inode, int mask, unsigned int flags); |
| 669 | extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); | 669 | extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); |
| 670 | extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, | 670 | extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, |
| 671 | struct kstat *stat); | 671 | struct kstat *stat); |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 223717dcc401..8e21e0fe65d5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -283,10 +283,13 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 283 | return 0; | 283 | return 0; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | static int cifs_permission(struct inode *inode, int mask) | 286 | static int cifs_permission(struct inode *inode, int mask, unsigned int flags) |
| 287 | { | 287 | { |
| 288 | struct cifs_sb_info *cifs_sb; | 288 | struct cifs_sb_info *cifs_sb; |
| 289 | 289 | ||
| 290 | if (flags & IPERM_FLAG_RCU) | ||
| 291 | return -ECHILD; | ||
| 292 | |||
| 290 | cifs_sb = CIFS_SB(inode->i_sb); | 293 | cifs_sb = CIFS_SB(inode->i_sb); |
| 291 | 294 | ||
| 292 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { | 295 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { |
| @@ -298,7 +301,7 @@ static int cifs_permission(struct inode *inode, int mask) | |||
| 298 | on the client (above and beyond ACL on servers) for | 301 | on the client (above and beyond ACL on servers) for |
| 299 | servers which do not support setting and viewing mode bits, | 302 | servers which do not support setting and viewing mode bits, |
| 300 | so allowing client to check permissions is useful */ | 303 | so allowing client to check permissions is useful */ |
| 301 | return generic_permission(inode, mask, NULL); | 304 | return generic_permission(inode, mask, flags, NULL); |
| 302 | } | 305 | } |
| 303 | 306 | ||
| 304 | static struct kmem_cache *cifs_inode_cachep; | 307 | static struct kmem_cache *cifs_inode_cachep; |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 619a8303766e..29badd91360f 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
| @@ -135,10 +135,13 @@ exit: | |||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | 137 | ||
| 138 | int coda_permission(struct inode *inode, int mask) | 138 | int coda_permission(struct inode *inode, int mask, unsigned int flags) |
| 139 | { | 139 | { |
| 140 | int error; | 140 | int error; |
| 141 | 141 | ||
| 142 | if (flags & IPERM_FLAG_RCU) | ||
| 143 | return -ECHILD; | ||
| 144 | |||
| 142 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; | 145 | mask &= MAY_READ | MAY_WRITE | MAY_EXEC; |
| 143 | 146 | ||
| 144 | if (!mask) | 147 | if (!mask) |
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 2fd89b5c5c7b..741f0bd03918 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include <linux/coda_psdev.h> | 24 | #include <linux/coda_psdev.h> |
| 25 | 25 | ||
| 26 | /* pioctl ops */ | 26 | /* pioctl ops */ |
| 27 | static int coda_ioctl_permission(struct inode *inode, int mask); | 27 | static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags); |
| 28 | static long coda_pioctl(struct file *filp, unsigned int cmd, | 28 | static long coda_pioctl(struct file *filp, unsigned int cmd, |
| 29 | unsigned long user_data); | 29 | unsigned long user_data); |
| 30 | 30 | ||
| @@ -41,8 +41,10 @@ const struct file_operations coda_ioctl_operations = { | |||
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | /* the coda pioctl inode ops */ | 43 | /* the coda pioctl inode ops */ |
| 44 | static int coda_ioctl_permission(struct inode *inode, int mask) | 44 | static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags) |
| 45 | { | 45 | { |
| 46 | if (flags & IPERM_FLAG_RCU) | ||
| 47 | return -ECHILD; | ||
| 46 | return (mask & MAY_EXEC) ? -EACCES : 0; | 48 | return (mask & MAY_EXEC) ? -EACCES : 0; |
| 47 | } | 49 | } |
| 48 | 50 | ||
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index f91b35db4c6e..337352a94751 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -980,8 +980,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) | |||
| 980 | } | 980 | } |
| 981 | 981 | ||
| 982 | static int | 982 | static int |
| 983 | ecryptfs_permission(struct inode *inode, int mask) | 983 | ecryptfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 984 | { | 984 | { |
| 985 | if (flags & IPERM_FLAG_RCU) | ||
| 986 | return -ECHILD; | ||
| 985 | return inode_permission(ecryptfs_inode_to_lower(inode), mask); | 987 | return inode_permission(ecryptfs_inode_to_lower(inode), mask); |
| 986 | } | 988 | } |
| 987 | 989 | ||
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 2bcc0431bada..dd9bb3f0c8d7 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c | |||
| @@ -232,10 +232,14 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | int | 234 | int |
| 235 | ext2_check_acl(struct inode *inode, int mask) | 235 | ext2_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 236 | { | 236 | { |
| 237 | struct posix_acl *acl = ext2_get_acl(inode, ACL_TYPE_ACCESS); | 237 | struct posix_acl *acl; |
| 238 | |||
| 239 | if (flags & IPERM_FLAG_RCU) | ||
| 240 | return -ECHILD; | ||
| 238 | 241 | ||
| 242 | acl = ext2_get_acl(inode, ACL_TYPE_ACCESS); | ||
| 239 | if (IS_ERR(acl)) | 243 | if (IS_ERR(acl)) |
| 240 | return PTR_ERR(acl); | 244 | return PTR_ERR(acl); |
| 241 | if (acl) { | 245 | if (acl) { |
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h index 3ff6cbb9ac44..c939b7b12099 100644 --- a/fs/ext2/acl.h +++ b/fs/ext2/acl.h | |||
| @@ -54,7 +54,7 @@ static inline int ext2_acl_count(size_t size) | |||
| 54 | #ifdef CONFIG_EXT2_FS_POSIX_ACL | 54 | #ifdef CONFIG_EXT2_FS_POSIX_ACL |
| 55 | 55 | ||
| 56 | /* acl.c */ | 56 | /* acl.c */ |
| 57 | extern int ext2_check_acl (struct inode *, int); | 57 | extern int ext2_check_acl (struct inode *, int, unsigned int); |
| 58 | extern int ext2_acl_chmod (struct inode *); | 58 | extern int ext2_acl_chmod (struct inode *); |
| 59 | extern int ext2_init_acl (struct inode *, struct inode *); | 59 | extern int ext2_init_acl (struct inode *, struct inode *); |
| 60 | 60 | ||
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index 8a11fe212183..9e49da8302d3 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c | |||
| @@ -240,10 +240,14 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type, | |||
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | int | 242 | int |
| 243 | ext3_check_acl(struct inode *inode, int mask) | 243 | ext3_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 244 | { | 244 | { |
| 245 | struct posix_acl *acl = ext3_get_acl(inode, ACL_TYPE_ACCESS); | 245 | struct posix_acl *acl; |
| 246 | |||
| 247 | if (flags & IPERM_FLAG_RCU) | ||
| 248 | return -ECHILD; | ||
| 246 | 249 | ||
| 250 | acl = ext3_get_acl(inode, ACL_TYPE_ACCESS); | ||
| 247 | if (IS_ERR(acl)) | 251 | if (IS_ERR(acl)) |
| 248 | return PTR_ERR(acl); | 252 | return PTR_ERR(acl); |
| 249 | if (acl) { | 253 | if (acl) { |
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h index 597334626de9..5faf8048e906 100644 --- a/fs/ext3/acl.h +++ b/fs/ext3/acl.h | |||
| @@ -54,7 +54,7 @@ static inline int ext3_acl_count(size_t size) | |||
| 54 | #ifdef CONFIG_EXT3_FS_POSIX_ACL | 54 | #ifdef CONFIG_EXT3_FS_POSIX_ACL |
| 55 | 55 | ||
| 56 | /* acl.c */ | 56 | /* acl.c */ |
| 57 | extern int ext3_check_acl (struct inode *, int); | 57 | extern int ext3_check_acl (struct inode *, int, unsigned int); |
| 58 | extern int ext3_acl_chmod (struct inode *); | 58 | extern int ext3_acl_chmod (struct inode *); |
| 59 | extern int ext3_init_acl (handle_t *, struct inode *, struct inode *); | 59 | extern int ext3_init_acl (handle_t *, struct inode *, struct inode *); |
| 60 | 60 | ||
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 5e2ed4504ead..373dcaeedba9 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c | |||
| @@ -238,10 +238,14 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, | |||
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | int | 240 | int |
| 241 | ext4_check_acl(struct inode *inode, int mask) | 241 | ext4_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 242 | { | 242 | { |
| 243 | struct posix_acl *acl = ext4_get_acl(inode, ACL_TYPE_ACCESS); | 243 | struct posix_acl *acl; |
| 244 | |||
| 245 | if (flags & IPERM_FLAG_RCU) | ||
| 246 | return -ECHILD; | ||
| 244 | 247 | ||
| 248 | acl = ext4_get_acl(inode, ACL_TYPE_ACCESS); | ||
| 245 | if (IS_ERR(acl)) | 249 | if (IS_ERR(acl)) |
| 246 | return PTR_ERR(acl); | 250 | return PTR_ERR(acl); |
| 247 | if (acl) { | 251 | if (acl) { |
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h index 9d843d5deac4..dec821168fd4 100644 --- a/fs/ext4/acl.h +++ b/fs/ext4/acl.h | |||
| @@ -54,7 +54,7 @@ static inline int ext4_acl_count(size_t size) | |||
| 54 | #ifdef CONFIG_EXT4_FS_POSIX_ACL | 54 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
| 55 | 55 | ||
| 56 | /* acl.c */ | 56 | /* acl.c */ |
| 57 | extern int ext4_check_acl(struct inode *, int); | 57 | extern int ext4_check_acl(struct inode *, int, unsigned int); |
| 58 | extern int ext4_acl_chmod(struct inode *); | 58 | extern int ext4_acl_chmod(struct inode *); |
| 59 | extern int ext4_init_acl(handle_t *, struct inode *, struct inode *); | 59 | extern int ext4_init_acl(handle_t *, struct inode *, struct inode *); |
| 60 | 60 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 07f4b5e675fc..f738599fd8cd 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -985,12 +985,15 @@ static int fuse_access(struct inode *inode, int mask) | |||
| 985 | * access request is sent. Execute permission is still checked | 985 | * access request is sent. Execute permission is still checked |
| 986 | * locally based on file mode. | 986 | * locally based on file mode. |
| 987 | */ | 987 | */ |
| 988 | static int fuse_permission(struct inode *inode, int mask) | 988 | static int fuse_permission(struct inode *inode, int mask, unsigned int flags) |
| 989 | { | 989 | { |
| 990 | struct fuse_conn *fc = get_fuse_conn(inode); | 990 | struct fuse_conn *fc = get_fuse_conn(inode); |
| 991 | bool refreshed = false; | 991 | bool refreshed = false; |
| 992 | int err = 0; | 992 | int err = 0; |
| 993 | 993 | ||
| 994 | if (flags & IPERM_FLAG_RCU) | ||
| 995 | return -ECHILD; | ||
| 996 | |||
| 994 | if (!fuse_allow_task(fc, current)) | 997 | if (!fuse_allow_task(fc, current)) |
| 995 | return -EACCES; | 998 | return -EACCES; |
| 996 | 999 | ||
| @@ -1005,7 +1008,7 @@ static int fuse_permission(struct inode *inode, int mask) | |||
| 1005 | } | 1008 | } |
| 1006 | 1009 | ||
| 1007 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | 1010 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { |
| 1008 | err = generic_permission(inode, mask, NULL); | 1011 | err = generic_permission(inode, mask, flags, NULL); |
| 1009 | 1012 | ||
| 1010 | /* If permission is denied, try to refresh file | 1013 | /* If permission is denied, try to refresh file |
| 1011 | attributes. This is also needed, because the root | 1014 | attributes. This is also needed, because the root |
| @@ -1013,7 +1016,8 @@ static int fuse_permission(struct inode *inode, int mask) | |||
| 1013 | if (err == -EACCES && !refreshed) { | 1016 | if (err == -EACCES && !refreshed) { |
| 1014 | err = fuse_do_getattr(inode, NULL, NULL); | 1017 | err = fuse_do_getattr(inode, NULL, NULL); |
| 1015 | if (!err) | 1018 | if (!err) |
| 1016 | err = generic_permission(inode, mask, NULL); | 1019 | err = generic_permission(inode, mask, |
| 1020 | flags, NULL); | ||
| 1017 | } | 1021 | } |
| 1018 | 1022 | ||
| 1019 | /* Note: the opposite of the above test does not | 1023 | /* Note: the opposite of the above test does not |
diff --git a/fs/generic_acl.c b/fs/generic_acl.c index 6bc9e3a5a693..628004282130 100644 --- a/fs/generic_acl.c +++ b/fs/generic_acl.c | |||
| @@ -190,10 +190,14 @@ generic_acl_chmod(struct inode *inode) | |||
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | int | 192 | int |
| 193 | generic_check_acl(struct inode *inode, int mask) | 193 | generic_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 194 | { | 194 | { |
| 195 | struct posix_acl *acl = get_cached_acl(inode, ACL_TYPE_ACCESS); | 195 | struct posix_acl *acl; |
| 196 | |||
| 197 | if (flags & IPERM_FLAG_RCU) | ||
| 198 | return -ECHILD; | ||
| 196 | 199 | ||
| 200 | acl = get_cached_acl(inode, ACL_TYPE_ACCESS); | ||
| 197 | if (acl) { | 201 | if (acl) { |
| 198 | int error = posix_acl_permission(inode, acl, mask); | 202 | int error = posix_acl_permission(inode, acl, mask); |
| 199 | posix_acl_release(acl); | 203 | posix_acl_release(acl); |
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 48171f4c943d..7118f1a780a9 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c | |||
| @@ -75,11 +75,14 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type) | |||
| 75 | * Returns: errno | 75 | * Returns: errno |
| 76 | */ | 76 | */ |
| 77 | 77 | ||
| 78 | int gfs2_check_acl(struct inode *inode, int mask) | 78 | int gfs2_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 79 | { | 79 | { |
| 80 | struct posix_acl *acl; | 80 | struct posix_acl *acl; |
| 81 | int error; | 81 | int error; |
| 82 | 82 | ||
| 83 | if (flags & IPERM_FLAG_RCU) | ||
| 84 | return -ECHILD; | ||
| 85 | |||
| 83 | acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); | 86 | acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); |
| 84 | if (IS_ERR(acl)) | 87 | if (IS_ERR(acl)) |
| 85 | return PTR_ERR(acl); | 88 | return PTR_ERR(acl); |
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h index b522b0cb39ea..a93907c8159b 100644 --- a/fs/gfs2/acl.h +++ b/fs/gfs2/acl.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" | 16 | #define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" |
| 17 | #define GFS2_ACL_MAX_ENTRIES 25 | 17 | #define GFS2_ACL_MAX_ENTRIES 25 |
| 18 | 18 | ||
| 19 | extern int gfs2_check_acl(struct inode *inode, int mask); | 19 | extern int gfs2_check_acl(struct inode *inode, int mask, unsigned int); |
| 20 | extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode); | 20 | extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode); |
| 21 | extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); | 21 | extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); |
| 22 | extern const struct xattr_handler gfs2_xattr_system_handler; | 22 | extern const struct xattr_handler gfs2_xattr_system_handler; |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index aa996471ec5c..fca6689e12e6 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
| @@ -241,7 +241,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) | |||
| 241 | !capable(CAP_LINUX_IMMUTABLE)) | 241 | !capable(CAP_LINUX_IMMUTABLE)) |
| 242 | goto out; | 242 | goto out; |
| 243 | if (!IS_IMMUTABLE(inode)) { | 243 | if (!IS_IMMUTABLE(inode)) { |
| 244 | error = gfs2_permission(inode, MAY_WRITE); | 244 | error = gfs2_permission(inode, MAY_WRITE, 0); |
| 245 | if (error) | 245 | if (error) |
| 246 | goto out; | 246 | goto out; |
| 247 | } | 247 | } |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index e1213f7f9217..6163be9686be 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
| @@ -509,7 +509,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
| 509 | } | 509 | } |
| 510 | 510 | ||
| 511 | if (!is_root) { | 511 | if (!is_root) { |
| 512 | error = gfs2_permission(dir, MAY_EXEC); | 512 | error = gfs2_permission(dir, MAY_EXEC, 0); |
| 513 | if (error) | 513 | if (error) |
| 514 | goto out; | 514 | goto out; |
| 515 | } | 515 | } |
| @@ -539,7 +539,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
| 539 | { | 539 | { |
| 540 | int error; | 540 | int error; |
| 541 | 541 | ||
| 542 | error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC); | 542 | error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0); |
| 543 | if (error) | 543 | if (error) |
| 544 | return error; | 544 | return error; |
| 545 | 545 | ||
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index d8499fadcc53..732a183efdb3 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h | |||
| @@ -113,7 +113,7 @@ extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, | |||
| 113 | extern struct inode *gfs2_createi(struct gfs2_holder *ghs, | 113 | extern struct inode *gfs2_createi(struct gfs2_holder *ghs, |
| 114 | const struct qstr *name, | 114 | const struct qstr *name, |
| 115 | unsigned int mode, dev_t dev); | 115 | unsigned int mode, dev_t dev); |
| 116 | extern int gfs2_permission(struct inode *inode, int mask); | 116 | extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags); |
| 117 | extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); | 117 | extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); |
| 118 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); | 118 | extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); |
| 119 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); | 119 | extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); |
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index f28f89796f4d..5c63a06fcd7c 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
| @@ -166,7 +166,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, | |||
| 166 | if (error) | 166 | if (error) |
| 167 | goto out_child; | 167 | goto out_child; |
| 168 | 168 | ||
| 169 | error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC); | 169 | error = gfs2_permission(dir, MAY_WRITE | MAY_EXEC, 0); |
| 170 | if (error) | 170 | if (error) |
| 171 | goto out_gunlock; | 171 | goto out_gunlock; |
| 172 | 172 | ||
| @@ -289,7 +289,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
| 289 | if (IS_APPEND(&dip->i_inode)) | 289 | if (IS_APPEND(&dip->i_inode)) |
| 290 | return -EPERM; | 290 | return -EPERM; |
| 291 | 291 | ||
| 292 | error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC); | 292 | error = gfs2_permission(&dip->i_inode, MAY_WRITE | MAY_EXEC, 0); |
| 293 | if (error) | 293 | if (error) |
| 294 | return error; | 294 | return error; |
| 295 | 295 | ||
| @@ -822,7 +822,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 822 | } | 822 | } |
| 823 | } | 823 | } |
| 824 | } else { | 824 | } else { |
| 825 | error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC); | 825 | error = gfs2_permission(ndir, MAY_WRITE | MAY_EXEC, 0); |
| 826 | if (error) | 826 | if (error) |
| 827 | goto out_gunlock; | 827 | goto out_gunlock; |
| 828 | 828 | ||
| @@ -857,7 +857,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
| 857 | /* Check out the dir to be renamed */ | 857 | /* Check out the dir to be renamed */ |
| 858 | 858 | ||
| 859 | if (dir_rename) { | 859 | if (dir_rename) { |
| 860 | error = gfs2_permission(odentry->d_inode, MAY_WRITE); | 860 | error = gfs2_permission(odentry->d_inode, MAY_WRITE, 0); |
| 861 | if (error) | 861 | if (error) |
| 862 | goto out_gunlock; | 862 | goto out_gunlock; |
| 863 | } | 863 | } |
| @@ -1041,13 +1041,17 @@ static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p) | |||
| 1041 | * Returns: errno | 1041 | * Returns: errno |
| 1042 | */ | 1042 | */ |
| 1043 | 1043 | ||
| 1044 | int gfs2_permission(struct inode *inode, int mask) | 1044 | int gfs2_permission(struct inode *inode, int mask, unsigned int flags) |
| 1045 | { | 1045 | { |
| 1046 | struct gfs2_inode *ip = GFS2_I(inode); | 1046 | struct gfs2_inode *ip; |
| 1047 | struct gfs2_holder i_gh; | 1047 | struct gfs2_holder i_gh; |
| 1048 | int error; | 1048 | int error; |
| 1049 | int unlock = 0; | 1049 | int unlock = 0; |
| 1050 | 1050 | ||
| 1051 | if (flags & IPERM_FLAG_RCU) | ||
| 1052 | return -ECHILD; | ||
| 1053 | |||
| 1054 | ip = GFS2_I(inode); | ||
| 1051 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { | 1055 | if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { |
| 1052 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); | 1056 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); |
| 1053 | if (error) | 1057 | if (error) |
| @@ -1058,7 +1062,7 @@ int gfs2_permission(struct inode *inode, int mask) | |||
| 1058 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) | 1062 | if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) |
| 1059 | error = -EACCES; | 1063 | error = -EACCES; |
| 1060 | else | 1064 | else |
| 1061 | error = generic_permission(inode, mask, gfs2_check_acl); | 1065 | error = generic_permission(inode, mask, flags, gfs2_check_acl); |
| 1062 | if (unlock) | 1066 | if (unlock) |
| 1063 | gfs2_glock_dq_uninit(&i_gh); | 1067 | gfs2_glock_dq_uninit(&i_gh); |
| 1064 | 1068 | ||
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 0bc81cf256b8..d3244d949a4e 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
| @@ -749,11 +749,14 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, | |||
| 749 | return err; | 749 | return err; |
| 750 | } | 750 | } |
| 751 | 751 | ||
| 752 | int hostfs_permission(struct inode *ino, int desired) | 752 | int hostfs_permission(struct inode *ino, int desired, unsigned int flags) |
| 753 | { | 753 | { |
| 754 | char *name; | 754 | char *name; |
| 755 | int r = 0, w = 0, x = 0, err; | 755 | int r = 0, w = 0, x = 0, err; |
| 756 | 756 | ||
| 757 | if (flags & IPERM_FLAG_RCU) | ||
| 758 | return -ECHILD; | ||
| 759 | |||
| 757 | if (desired & MAY_READ) r = 1; | 760 | if (desired & MAY_READ) r = 1; |
| 758 | if (desired & MAY_WRITE) w = 1; | 761 | if (desired & MAY_WRITE) w = 1; |
| 759 | if (desired & MAY_EXEC) x = 1; | 762 | if (desired & MAY_EXEC) x = 1; |
| @@ -768,7 +771,7 @@ int hostfs_permission(struct inode *ino, int desired) | |||
| 768 | err = access_file(name, r, w, x); | 771 | err = access_file(name, r, w, x); |
| 769 | __putname(name); | 772 | __putname(name); |
| 770 | if (!err) | 773 | if (!err) |
| 771 | err = generic_permission(ino, desired, NULL); | 774 | err = generic_permission(ino, desired, flags, NULL); |
| 772 | return err; | 775 | return err; |
| 773 | } | 776 | } |
| 774 | 777 | ||
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 11c2b4080f65..f4ad9e31ddc4 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
| @@ -419,7 +419,7 @@ again: | |||
| 419 | unlock_kernel(); | 419 | unlock_kernel(); |
| 420 | return -ENOSPC; | 420 | return -ENOSPC; |
| 421 | } | 421 | } |
| 422 | if (generic_permission(inode, MAY_WRITE, NULL) || | 422 | if (generic_permission(inode, MAY_WRITE, 0, NULL) || |
| 423 | !S_ISREG(inode->i_mode) || | 423 | !S_ISREG(inode->i_mode) || |
| 424 | get_write_access(inode)) { | 424 | get_write_access(inode)) { |
| 425 | d_rehash(dentry); | 425 | d_rehash(dentry); |
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 54a92fd02bbd..95b79672150a 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c | |||
| @@ -259,11 +259,14 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
| 259 | return rc; | 259 | return rc; |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | int jffs2_check_acl(struct inode *inode, int mask) | 262 | int jffs2_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 263 | { | 263 | { |
| 264 | struct posix_acl *acl; | 264 | struct posix_acl *acl; |
| 265 | int rc; | 265 | int rc; |
| 266 | 266 | ||
| 267 | if (flags & IPERM_FLAG_RCU) | ||
| 268 | return -ECHILD; | ||
| 269 | |||
| 267 | acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); | 270 | acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); |
| 268 | if (IS_ERR(acl)) | 271 | if (IS_ERR(acl)) |
| 269 | return PTR_ERR(acl); | 272 | return PTR_ERR(acl); |
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h index 5e42de8d9541..3119f59253d3 100644 --- a/fs/jffs2/acl.h +++ b/fs/jffs2/acl.h | |||
| @@ -26,7 +26,7 @@ struct jffs2_acl_header { | |||
| 26 | 26 | ||
| 27 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | 27 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL |
| 28 | 28 | ||
| 29 | extern int jffs2_check_acl(struct inode *, int); | 29 | extern int jffs2_check_acl(struct inode *, int, unsigned int); |
| 30 | extern int jffs2_acl_chmod(struct inode *); | 30 | extern int jffs2_acl_chmod(struct inode *); |
| 31 | extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *); | 31 | extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *); |
| 32 | extern int jffs2_init_acl_post(struct inode *); | 32 | extern int jffs2_init_acl_post(struct inode *); |
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 1057a4998e4e..e5de9422fa32 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c | |||
| @@ -114,10 +114,14 @@ out: | |||
| 114 | return rc; | 114 | return rc; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | int jfs_check_acl(struct inode *inode, int mask) | 117 | int jfs_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 118 | { | 118 | { |
| 119 | struct posix_acl *acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); | 119 | struct posix_acl *acl; |
| 120 | |||
| 121 | if (flags & IPERM_FLAG_RCU) | ||
| 122 | return -ECHILD; | ||
| 120 | 123 | ||
| 124 | acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
| 121 | if (IS_ERR(acl)) | 125 | if (IS_ERR(acl)) |
| 122 | return PTR_ERR(acl); | 126 | return PTR_ERR(acl); |
| 123 | if (acl) { | 127 | if (acl) { |
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h index 54e07559878d..f9285c4900fa 100644 --- a/fs/jfs/jfs_acl.h +++ b/fs/jfs/jfs_acl.h | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | #ifdef CONFIG_JFS_POSIX_ACL | 21 | #ifdef CONFIG_JFS_POSIX_ACL |
| 22 | 22 | ||
| 23 | int jfs_check_acl(struct inode *, int); | 23 | int jfs_check_acl(struct inode *, int, unsigned int flags); |
| 24 | int jfs_init_acl(tid_t, struct inode *, struct inode *); | 24 | int jfs_init_acl(tid_t, struct inode *, struct inode *); |
| 25 | int jfs_acl_chmod(struct inode *inode); | 25 | int jfs_acl_chmod(struct inode *inode); |
| 26 | 26 | ||
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index 409dfd65e9a1..f9ddf0c388c8 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c | |||
| @@ -555,9 +555,11 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 555 | return __logfs_create(dir, dentry, inode, target, destlen); | 555 | return __logfs_create(dir, dentry, inode, target, destlen); |
| 556 | } | 556 | } |
| 557 | 557 | ||
| 558 | static int logfs_permission(struct inode *inode, int mask) | 558 | static int logfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 559 | { | 559 | { |
| 560 | return generic_permission(inode, mask, NULL); | 560 | if (flags & IPERM_FLAG_RCU) |
| 561 | return -ECHILD; | ||
| 562 | return generic_permission(inode, mask, flags, NULL); | ||
| 561 | } | 563 | } |
| 562 | 564 | ||
| 563 | static int logfs_link(struct dentry *old_dentry, struct inode *dir, | 565 | static int logfs_link(struct dentry *old_dentry, struct inode *dir, |
diff --git a/fs/namei.c b/fs/namei.c index 6e275363e89d..4e957bf744ae 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -169,8 +169,8 @@ EXPORT_SYMBOL(putname); | |||
| 169 | /* | 169 | /* |
| 170 | * This does basic POSIX ACL permission checking | 170 | * This does basic POSIX ACL permission checking |
| 171 | */ | 171 | */ |
| 172 | static inline int __acl_permission_check(struct inode *inode, int mask, | 172 | static int acl_permission_check(struct inode *inode, int mask, unsigned int flags, |
| 173 | int (*check_acl)(struct inode *inode, int mask), int rcu) | 173 | int (*check_acl)(struct inode *inode, int mask, unsigned int flags)) |
| 174 | { | 174 | { |
| 175 | umode_t mode = inode->i_mode; | 175 | umode_t mode = inode->i_mode; |
| 176 | 176 | ||
| @@ -180,13 +180,9 @@ static inline int __acl_permission_check(struct inode *inode, int mask, | |||
| 180 | mode >>= 6; | 180 | mode >>= 6; |
| 181 | else { | 181 | else { |
| 182 | if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) { | 182 | if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) { |
| 183 | if (rcu) { | 183 | int error = check_acl(inode, mask, flags); |
| 184 | return -ECHILD; | 184 | if (error != -EAGAIN) |
| 185 | } else { | 185 | return error; |
| 186 | int error = check_acl(inode, mask); | ||
| 187 | if (error != -EAGAIN) | ||
| 188 | return error; | ||
| 189 | } | ||
| 190 | } | 186 | } |
| 191 | 187 | ||
| 192 | if (in_group_p(inode->i_gid)) | 188 | if (in_group_p(inode->i_gid)) |
| @@ -201,32 +197,31 @@ static inline int __acl_permission_check(struct inode *inode, int mask, | |||
| 201 | return -EACCES; | 197 | return -EACCES; |
| 202 | } | 198 | } |
| 203 | 199 | ||
| 204 | static inline int acl_permission_check(struct inode *inode, int mask, | ||
| 205 | int (*check_acl)(struct inode *inode, int mask)) | ||
| 206 | { | ||
| 207 | return __acl_permission_check(inode, mask, check_acl, 0); | ||
| 208 | } | ||
| 209 | |||
| 210 | /** | 200 | /** |
| 211 | * generic_permission - check for access rights on a Posix-like filesystem | 201 | * generic_permission - check for access rights on a Posix-like filesystem |
| 212 | * @inode: inode to check access rights for | 202 | * @inode: inode to check access rights for |
| 213 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | 203 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) |
| 214 | * @check_acl: optional callback to check for Posix ACLs | 204 | * @check_acl: optional callback to check for Posix ACLs |
| 205 | * @flags IPERM_FLAG_ flags. | ||
| 215 | * | 206 | * |
| 216 | * Used to check for read/write/execute permissions on a file. | 207 | * Used to check for read/write/execute permissions on a file. |
| 217 | * We use "fsuid" for this, letting us set arbitrary permissions | 208 | * We use "fsuid" for this, letting us set arbitrary permissions |
| 218 | * for filesystem access without changing the "normal" uids which | 209 | * for filesystem access without changing the "normal" uids which |
| 219 | * are used for other things.. | 210 | * are used for other things. |
| 211 | * | ||
| 212 | * generic_permission is rcu-walk aware. It returns -ECHILD in case an rcu-walk | ||
| 213 | * request cannot be satisfied (eg. requires blocking or too much complexity). | ||
| 214 | * It would then be called again in ref-walk mode. | ||
| 220 | */ | 215 | */ |
| 221 | int generic_permission(struct inode *inode, int mask, | 216 | int generic_permission(struct inode *inode, int mask, unsigned int flags, |
| 222 | int (*check_acl)(struct inode *inode, int mask)) | 217 | int (*check_acl)(struct inode *inode, int mask, unsigned int flags)) |
| 223 | { | 218 | { |
| 224 | int ret; | 219 | int ret; |
| 225 | 220 | ||
| 226 | /* | 221 | /* |
| 227 | * Do the basic POSIX ACL permission checks. | 222 | * Do the basic POSIX ACL permission checks. |
| 228 | */ | 223 | */ |
| 229 | ret = acl_permission_check(inode, mask, check_acl); | 224 | ret = acl_permission_check(inode, mask, flags, check_acl); |
| 230 | if (ret != -EACCES) | 225 | if (ret != -EACCES) |
| 231 | return ret; | 226 | return ret; |
| 232 | 227 | ||
| @@ -281,9 +276,10 @@ int inode_permission(struct inode *inode, int mask) | |||
| 281 | } | 276 | } |
| 282 | 277 | ||
| 283 | if (inode->i_op->permission) | 278 | if (inode->i_op->permission) |
| 284 | retval = inode->i_op->permission(inode, mask); | 279 | retval = inode->i_op->permission(inode, mask, 0); |
| 285 | else | 280 | else |
| 286 | retval = generic_permission(inode, mask, inode->i_op->check_acl); | 281 | retval = generic_permission(inode, mask, 0, |
| 282 | inode->i_op->check_acl); | ||
| 287 | 283 | ||
| 288 | if (retval) | 284 | if (retval) |
| 289 | return retval; | 285 | return retval; |
| @@ -668,22 +664,19 @@ force_reval_path(struct path *path, struct nameidata *nd) | |||
| 668 | * short-cut DAC fails, then call ->permission() to do more | 664 | * short-cut DAC fails, then call ->permission() to do more |
| 669 | * complete permission check. | 665 | * complete permission check. |
| 670 | */ | 666 | */ |
| 671 | static inline int __exec_permission(struct inode *inode, int rcu) | 667 | static inline int exec_permission(struct inode *inode, unsigned int flags) |
| 672 | { | 668 | { |
| 673 | int ret; | 669 | int ret; |
| 674 | 670 | ||
| 675 | if (inode->i_op->permission) { | 671 | if (inode->i_op->permission) { |
| 676 | if (rcu) | 672 | ret = inode->i_op->permission(inode, MAY_EXEC, flags); |
| 677 | return -ECHILD; | 673 | } else { |
| 678 | ret = inode->i_op->permission(inode, MAY_EXEC); | 674 | ret = acl_permission_check(inode, MAY_EXEC, flags, |
| 679 | if (!ret) | 675 | inode->i_op->check_acl); |
| 680 | goto ok; | ||
| 681 | return ret; | ||
| 682 | } | 676 | } |
| 683 | ret = __acl_permission_check(inode, MAY_EXEC, inode->i_op->check_acl, rcu); | 677 | if (likely(!ret)) |
| 684 | if (!ret) | ||
| 685 | goto ok; | 678 | goto ok; |
| 686 | if (rcu && ret == -ECHILD) | 679 | if (ret == -ECHILD) |
| 687 | return ret; | 680 | return ret; |
| 688 | 681 | ||
| 689 | if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH)) | 682 | if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH)) |
| @@ -691,17 +684,7 @@ static inline int __exec_permission(struct inode *inode, int rcu) | |||
| 691 | 684 | ||
| 692 | return ret; | 685 | return ret; |
| 693 | ok: | 686 | ok: |
| 694 | return security_inode_exec_permission(inode, rcu); | 687 | return security_inode_exec_permission(inode, flags); |
| 695 | } | ||
| 696 | |||
| 697 | static int exec_permission(struct inode *inode) | ||
| 698 | { | ||
| 699 | return __exec_permission(inode, 0); | ||
| 700 | } | ||
| 701 | |||
| 702 | static int exec_permission_rcu(struct inode *inode) | ||
| 703 | { | ||
| 704 | return __exec_permission(inode, 1); | ||
| 705 | } | 688 | } |
| 706 | 689 | ||
| 707 | static __always_inline void set_root(struct nameidata *nd) | 690 | static __always_inline void set_root(struct nameidata *nd) |
| @@ -1165,7 +1148,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
| 1165 | 1148 | ||
| 1166 | nd->flags |= LOOKUP_CONTINUE; | 1149 | nd->flags |= LOOKUP_CONTINUE; |
| 1167 | if (nd->flags & LOOKUP_RCU) { | 1150 | if (nd->flags & LOOKUP_RCU) { |
| 1168 | err = exec_permission_rcu(nd->inode); | 1151 | err = exec_permission(nd->inode, IPERM_FLAG_RCU); |
| 1169 | if (err == -ECHILD) { | 1152 | if (err == -ECHILD) { |
| 1170 | if (nameidata_drop_rcu(nd)) | 1153 | if (nameidata_drop_rcu(nd)) |
| 1171 | return -ECHILD; | 1154 | return -ECHILD; |
| @@ -1173,7 +1156,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
| 1173 | } | 1156 | } |
| 1174 | } else { | 1157 | } else { |
| 1175 | exec_again: | 1158 | exec_again: |
| 1176 | err = exec_permission(nd->inode); | 1159 | err = exec_permission(nd->inode, 0); |
| 1177 | } | 1160 | } |
| 1178 | if (err) | 1161 | if (err) |
| 1179 | break; | 1162 | break; |
| @@ -1620,7 +1603,7 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
| 1620 | struct dentry *dentry; | 1603 | struct dentry *dentry; |
| 1621 | int err; | 1604 | int err; |
| 1622 | 1605 | ||
| 1623 | err = exec_permission(inode); | 1606 | err = exec_permission(inode, 0); |
| 1624 | if (err) | 1607 | if (err) |
| 1625 | return ERR_PTR(err); | 1608 | return ERR_PTR(err); |
| 1626 | 1609 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 58beace14b19..d33da530097a 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -2189,11 +2189,14 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) | |||
| 2189 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); | 2189 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); |
| 2190 | } | 2190 | } |
| 2191 | 2191 | ||
| 2192 | int nfs_permission(struct inode *inode, int mask) | 2192 | int nfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 2193 | { | 2193 | { |
| 2194 | struct rpc_cred *cred; | 2194 | struct rpc_cred *cred; |
| 2195 | int res = 0; | 2195 | int res = 0; |
| 2196 | 2196 | ||
| 2197 | if (flags & IPERM_FLAG_RCU) | ||
| 2198 | return -ECHILD; | ||
| 2199 | |||
| 2197 | nfs_inc_stats(inode, NFSIOS_VFSACCESS); | 2200 | nfs_inc_stats(inode, NFSIOS_VFSACCESS); |
| 2198 | 2201 | ||
| 2199 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) | 2202 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) |
| @@ -2241,7 +2244,7 @@ out: | |||
| 2241 | out_notsup: | 2244 | out_notsup: |
| 2242 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 2245 | res = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 2243 | if (res == 0) | 2246 | if (res == 0) |
| 2244 | res = generic_permission(inode, mask, NULL); | 2247 | res = generic_permission(inode, mask, flags, NULL); |
| 2245 | goto out; | 2248 | goto out; |
| 2246 | } | 2249 | } |
| 2247 | 2250 | ||
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 71d4bc8464e0..77b48c8fab17 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
| @@ -785,15 +785,19 @@ out_err: | |||
| 785 | return err; | 785 | return err; |
| 786 | } | 786 | } |
| 787 | 787 | ||
| 788 | int nilfs_permission(struct inode *inode, int mask) | 788 | int nilfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 789 | { | 789 | { |
| 790 | struct nilfs_root *root = NILFS_I(inode)->i_root; | 790 | struct nilfs_root *root; |
| 791 | |||
| 792 | if (flags & IPERM_FLAG_RCU) | ||
| 793 | return -ECHILD; | ||
| 791 | 794 | ||
| 795 | root = NILFS_I(inode)->i_root; | ||
| 792 | if ((mask & MAY_WRITE) && root && | 796 | if ((mask & MAY_WRITE) && root && |
| 793 | root->cno != NILFS_CPTREE_CURRENT_CNO) | 797 | root->cno != NILFS_CPTREE_CURRENT_CNO) |
| 794 | return -EROFS; /* snapshot is not writable */ | 798 | return -EROFS; /* snapshot is not writable */ |
| 795 | 799 | ||
| 796 | return generic_permission(inode, mask, NULL); | 800 | return generic_permission(inode, mask, flags, NULL); |
| 797 | } | 801 | } |
| 798 | 802 | ||
| 799 | int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, | 803 | int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, |
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index f7560da5a567..0ca98823db59 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
| @@ -256,7 +256,7 @@ extern void nilfs_update_inode(struct inode *, struct buffer_head *); | |||
| 256 | extern void nilfs_truncate(struct inode *); | 256 | extern void nilfs_truncate(struct inode *); |
| 257 | extern void nilfs_evict_inode(struct inode *); | 257 | extern void nilfs_evict_inode(struct inode *); |
| 258 | extern int nilfs_setattr(struct dentry *, struct iattr *); | 258 | extern int nilfs_setattr(struct dentry *, struct iattr *); |
| 259 | int nilfs_permission(struct inode *inode, int mask); | 259 | int nilfs_permission(struct inode *inode, int mask, unsigned int flags); |
| 260 | extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *, | 260 | extern int nilfs_load_inode_block(struct nilfs_sb_info *, struct inode *, |
| 261 | struct buffer_head **); | 261 | struct buffer_head **); |
| 262 | extern int nilfs_inode_dirty(struct inode *); | 262 | extern int nilfs_inode_dirty(struct inode *); |
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 391915093fe1..704f6b1742f3 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c | |||
| @@ -291,13 +291,17 @@ static int ocfs2_set_acl(handle_t *handle, | |||
| 291 | return ret; | 291 | return ret; |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | int ocfs2_check_acl(struct inode *inode, int mask) | 294 | int ocfs2_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 295 | { | 295 | { |
| 296 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 296 | struct ocfs2_super *osb; |
| 297 | struct buffer_head *di_bh = NULL; | 297 | struct buffer_head *di_bh = NULL; |
| 298 | struct posix_acl *acl; | 298 | struct posix_acl *acl; |
| 299 | int ret = -EAGAIN; | 299 | int ret = -EAGAIN; |
| 300 | 300 | ||
| 301 | if (flags & IPERM_FLAG_RCU) | ||
| 302 | return -ECHILD; | ||
| 303 | |||
| 304 | osb = OCFS2_SB(inode->i_sb); | ||
| 301 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) | 305 | if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) |
| 302 | return ret; | 306 | return ret; |
| 303 | 307 | ||
diff --git a/fs/ocfs2/acl.h b/fs/ocfs2/acl.h index 5c5d31f05853..4fe7c9cf4bfb 100644 --- a/fs/ocfs2/acl.h +++ b/fs/ocfs2/acl.h | |||
| @@ -26,7 +26,7 @@ struct ocfs2_acl_entry { | |||
| 26 | __le32 e_id; | 26 | __le32 e_id; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | extern int ocfs2_check_acl(struct inode *, int); | 29 | extern int ocfs2_check_acl(struct inode *, int, unsigned int); |
| 30 | extern int ocfs2_acl_chmod(struct inode *); | 30 | extern int ocfs2_acl_chmod(struct inode *); |
| 31 | extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *, | 31 | extern int ocfs2_init_acl(handle_t *, struct inode *, struct inode *, |
| 32 | struct buffer_head *, struct buffer_head *, | 32 | struct buffer_head *, struct buffer_head *, |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index f6cba566429d..bdadbae09094 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -1307,10 +1307,13 @@ bail: | |||
| 1307 | return err; | 1307 | return err; |
| 1308 | } | 1308 | } |
| 1309 | 1309 | ||
| 1310 | int ocfs2_permission(struct inode *inode, int mask) | 1310 | int ocfs2_permission(struct inode *inode, int mask, unsigned int flags) |
| 1311 | { | 1311 | { |
| 1312 | int ret; | 1312 | int ret; |
| 1313 | 1313 | ||
| 1314 | if (flags & IPERM_FLAG_RCU) | ||
| 1315 | return -ECHILD; | ||
| 1316 | |||
| 1314 | mlog_entry_void(); | 1317 | mlog_entry_void(); |
| 1315 | 1318 | ||
| 1316 | ret = ocfs2_inode_lock(inode, NULL, 0); | 1319 | ret = ocfs2_inode_lock(inode, NULL, 0); |
| @@ -1320,7 +1323,7 @@ int ocfs2_permission(struct inode *inode, int mask) | |||
| 1320 | goto out; | 1323 | goto out; |
| 1321 | } | 1324 | } |
| 1322 | 1325 | ||
| 1323 | ret = generic_permission(inode, mask, ocfs2_check_acl); | 1326 | ret = generic_permission(inode, mask, flags, ocfs2_check_acl); |
| 1324 | 1327 | ||
| 1325 | ocfs2_inode_unlock(inode, 0); | 1328 | ocfs2_inode_unlock(inode, 0); |
| 1326 | out: | 1329 | out: |
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 97bf761c9e7c..f5afbbef6703 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
| @@ -61,7 +61,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, | |||
| 61 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); | 61 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); |
| 62 | int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | 62 | int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, |
| 63 | struct kstat *stat); | 63 | struct kstat *stat); |
| 64 | int ocfs2_permission(struct inode *inode, int mask); | 64 | int ocfs2_permission(struct inode *inode, int mask, unsigned int flags); |
| 65 | 65 | ||
| 66 | int ocfs2_should_update_atime(struct inode *inode, | 66 | int ocfs2_should_update_atime(struct inode *inode, |
| 67 | struct vfsmount *vfsmnt); | 67 | struct vfsmount *vfsmnt); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index dc5b2fcadc3b..b953d41d9abf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -2114,11 +2114,13 @@ static const struct file_operations proc_fd_operations = { | |||
| 2114 | * /proc/pid/fd needs a special permission handler so that a process can still | 2114 | * /proc/pid/fd needs a special permission handler so that a process can still |
| 2115 | * access /proc/self/fd after it has executed a setuid(). | 2115 | * access /proc/self/fd after it has executed a setuid(). |
| 2116 | */ | 2116 | */ |
| 2117 | static int proc_fd_permission(struct inode *inode, int mask) | 2117 | static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags) |
| 2118 | { | 2118 | { |
| 2119 | int rv; | 2119 | int rv; |
| 2120 | 2120 | ||
| 2121 | rv = generic_permission(inode, mask, NULL); | 2121 | if (flags & IPERM_FLAG_RCU) |
| 2122 | return -ECHILD; | ||
| 2123 | rv = generic_permission(inode, mask, flags, NULL); | ||
| 2122 | if (rv == 0) | 2124 | if (rv == 0) |
| 2123 | return 0; | 2125 | return 0; |
| 2124 | if (task_pid(current) == proc_pid(inode)) | 2126 | if (task_pid(current) == proc_pid(inode)) |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index c9097f43b425..09a1f92a34ef 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
| @@ -295,7 +295,7 @@ out: | |||
| 295 | return ret; | 295 | return ret; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static int proc_sys_permission(struct inode *inode, int mask) | 298 | static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags) |
| 299 | { | 299 | { |
| 300 | /* | 300 | /* |
| 301 | * sysctl entries that are not writeable, | 301 | * sysctl entries that are not writeable, |
| @@ -305,6 +305,9 @@ static int proc_sys_permission(struct inode *inode, int mask) | |||
| 305 | struct ctl_table *table; | 305 | struct ctl_table *table; |
| 306 | int error; | 306 | int error; |
| 307 | 307 | ||
| 308 | if (flags & IPERM_FLAG_RCU) | ||
| 309 | return -ECHILD; | ||
| 310 | |||
| 308 | /* Executable files are not allowed under /proc/sys/ */ | 311 | /* Executable files are not allowed under /proc/sys/ */ |
| 309 | if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) | 312 | if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) |
| 310 | return -EACCES; | 313 | return -EACCES; |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 9ea22a56cdf1..3cfb2e933644 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -870,11 +870,14 @@ out: | |||
| 870 | return err; | 870 | return err; |
| 871 | } | 871 | } |
| 872 | 872 | ||
| 873 | static int reiserfs_check_acl(struct inode *inode, int mask) | 873 | static int reiserfs_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 874 | { | 874 | { |
| 875 | struct posix_acl *acl; | 875 | struct posix_acl *acl; |
| 876 | int error = -EAGAIN; /* do regular unix permission checks by default */ | 876 | int error = -EAGAIN; /* do regular unix permission checks by default */ |
| 877 | 877 | ||
| 878 | if (flags & IPERM_FLAG_RCU) | ||
| 879 | return -ECHILD; | ||
| 880 | |||
| 878 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); | 881 | acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); |
| 879 | 882 | ||
| 880 | if (acl) { | 883 | if (acl) { |
| @@ -951,8 +954,10 @@ static int xattr_mount_check(struct super_block *s) | |||
| 951 | return 0; | 954 | return 0; |
| 952 | } | 955 | } |
| 953 | 956 | ||
| 954 | int reiserfs_permission(struct inode *inode, int mask) | 957 | int reiserfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 955 | { | 958 | { |
| 959 | if (flags & IPERM_FLAG_RCU) | ||
| 960 | return -ECHILD; | ||
| 956 | /* | 961 | /* |
| 957 | * We don't do permission checks on the internal objects. | 962 | * We don't do permission checks on the internal objects. |
| 958 | * Permissions are determined by the "owning" object. | 963 | * Permissions are determined by the "owning" object. |
| @@ -965,9 +970,10 @@ int reiserfs_permission(struct inode *inode, int mask) | |||
| 965 | * Stat data v1 doesn't support ACLs. | 970 | * Stat data v1 doesn't support ACLs. |
| 966 | */ | 971 | */ |
| 967 | if (get_inode_sd_version(inode) != STAT_DATA_V1) | 972 | if (get_inode_sd_version(inode) != STAT_DATA_V1) |
| 968 | return generic_permission(inode, mask, reiserfs_check_acl); | 973 | return generic_permission(inode, mask, flags, |
| 974 | reiserfs_check_acl); | ||
| 969 | #endif | 975 | #endif |
| 970 | return generic_permission(inode, mask, NULL); | 976 | return generic_permission(inode, mask, flags, NULL); |
| 971 | } | 977 | } |
| 972 | 978 | ||
| 973 | static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) | 979 | static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index cffb1fd8ba33..30ac27345586 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -348,13 +348,18 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns, const cha | |||
| 348 | return -ENOENT; | 348 | return -ENOENT; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | int sysfs_permission(struct inode *inode, int mask) | 351 | int sysfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 352 | { | 352 | { |
| 353 | struct sysfs_dirent *sd = inode->i_private; | 353 | struct sysfs_dirent *sd; |
| 354 | |||
| 355 | if (flags & IPERM_FLAG_RCU) | ||
| 356 | return -ECHILD; | ||
| 357 | |||
| 358 | sd = inode->i_private; | ||
| 354 | 359 | ||
| 355 | mutex_lock(&sysfs_mutex); | 360 | mutex_lock(&sysfs_mutex); |
| 356 | sysfs_refresh_inode(sd, inode); | 361 | sysfs_refresh_inode(sd, inode); |
| 357 | mutex_unlock(&sysfs_mutex); | 362 | mutex_unlock(&sysfs_mutex); |
| 358 | 363 | ||
| 359 | return generic_permission(inode, mask, NULL); | 364 | return generic_permission(inode, mask, flags, NULL); |
| 360 | } | 365 | } |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index d9be60a2e956..ffaaa816bfba 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -200,7 +200,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd) | |||
| 200 | struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); | 200 | struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); |
| 201 | void sysfs_evict_inode(struct inode *inode); | 201 | void sysfs_evict_inode(struct inode *inode); |
| 202 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); | 202 | int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr); |
| 203 | int sysfs_permission(struct inode *inode, int mask); | 203 | int sysfs_permission(struct inode *inode, int mask, unsigned int flags); |
| 204 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | 204 | int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); |
| 205 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); | 205 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); |
| 206 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 206 | int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c index b2771862fd3d..4b11eaf6a580 100644 --- a/fs/xfs/linux-2.6/xfs_acl.c +++ b/fs/xfs/linux-2.6/xfs_acl.c | |||
| @@ -219,12 +219,16 @@ xfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) | |||
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | int | 221 | int |
| 222 | xfs_check_acl(struct inode *inode, int mask) | 222 | xfs_check_acl(struct inode *inode, int mask, unsigned int flags) |
| 223 | { | 223 | { |
| 224 | struct xfs_inode *ip = XFS_I(inode); | 224 | struct xfs_inode *ip; |
| 225 | struct posix_acl *acl; | 225 | struct posix_acl *acl; |
| 226 | int error = -EAGAIN; | 226 | int error = -EAGAIN; |
| 227 | 227 | ||
| 228 | if (flags & IPERM_FLAG_RCU) | ||
| 229 | return -ECHILD; | ||
| 230 | |||
| 231 | ip = XFS_I(inode); | ||
| 228 | trace_xfs_check_acl(ip); | 232 | trace_xfs_check_acl(ip); |
| 229 | 233 | ||
| 230 | /* | 234 | /* |
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 0135e2a669d7..11dd72070cbb 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h | |||
| @@ -42,7 +42,7 @@ struct xfs_acl { | |||
| 42 | #define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1) | 42 | #define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1) |
| 43 | 43 | ||
| 44 | #ifdef CONFIG_XFS_POSIX_ACL | 44 | #ifdef CONFIG_XFS_POSIX_ACL |
| 45 | extern int xfs_check_acl(struct inode *inode, int mask); | 45 | extern int xfs_check_acl(struct inode *inode, int mask, unsigned int flags); |
| 46 | extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); | 46 | extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); |
| 47 | extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl); | 47 | extern int xfs_inherit_acl(struct inode *inode, struct posix_acl *default_acl); |
| 48 | extern int xfs_acl_chmod(struct inode *inode); | 48 | extern int xfs_acl_chmod(struct inode *inode); |
