aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/afs/internal.h4
-rw-r--r--fs/afs/security.c2
-rw-r--r--fs/bad_inode.c3
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/coda/dir.c4
-rw-r--r--fs/coda/pioctl.c6
-rw-r--r--fs/ecryptfs/inode.c17
-rw-r--r--fs/ext2/acl.c2
-rw-r--r--fs/ext2/acl.h2
-rw-r--r--fs/ext3/acl.c2
-rw-r--r--fs/ext3/acl.h2
-rw-r--r--fs/ext4/acl.c2
-rw-r--r--fs/ext4/acl.h2
-rw-r--r--fs/fuse/dir.c6
-rw-r--r--fs/gfs2/ops_inode.c12
-rw-r--r--fs/hfs/inode.c3
-rw-r--r--fs/hfsplus/inode.c2
-rw-r--r--fs/hostfs/hostfs_kern.c2
-rw-r--r--fs/jffs2/acl.c2
-rw-r--r--fs/jffs2/acl.h2
-rw-r--r--fs/jfs/acl.c2
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/namei.c23
-rw-r--r--fs/nfs/dir.c11
-rw-r--r--fs/ocfs2/file.c2
-rw-r--r--fs/ocfs2/file.h3
-rw-r--r--fs/proc/base.c3
-rw-r--r--fs/proc/proc_sysctl.c2
-rw-r--r--fs/reiserfs/xattr.c2
-rw-r--r--fs/smbfs/file.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c3
-rw-r--r--include/linux/coda_linux.h2
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/reiserfs_xattr.h2
-rw-r--r--include/linux/shmem_fs.h2
-rw-r--r--kernel/sysctl.c10
-rw-r--r--mm/shmem_acl.c2
38 files changed, 74 insertions, 87 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 7102824ba847..3cb6920ff30b 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -469,8 +469,6 @@ extern bool afs_cm_incoming_call(struct afs_call *);
469extern const struct inode_operations afs_dir_inode_operations; 469extern const struct inode_operations afs_dir_inode_operations;
470extern const struct file_operations afs_dir_file_operations; 470extern const struct file_operations afs_dir_file_operations;
471 471
472extern int afs_permission(struct inode *, int, struct nameidata *);
473
474/* 472/*
475 * file.c 473 * file.c
476 */ 474 */
@@ -605,7 +603,7 @@ extern void afs_clear_permits(struct afs_vnode *);
605extern void afs_cache_permit(struct afs_vnode *, struct key *, long); 603extern void afs_cache_permit(struct afs_vnode *, struct key *, long);
606extern void afs_zap_permits(struct rcu_head *); 604extern void afs_zap_permits(struct rcu_head *);
607extern struct key *afs_request_key(struct afs_cell *); 605extern struct key *afs_request_key(struct afs_cell *);
608extern int afs_permission(struct inode *, int, struct nameidata *); 606extern int afs_permission(struct inode *, int);
609 607
610/* 608/*
611 * server.c 609 * server.c
diff --git a/fs/afs/security.c b/fs/afs/security.c
index 3bcbeceba1bb..3ef504370034 100644
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -284,7 +284,7 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key,
284 * - AFS ACLs are attached to directories only, and a file is controlled by its 284 * - AFS ACLs are attached to directories only, and a file is controlled by its
285 * parent directory's ACL 285 * parent directory's ACL
286 */ 286 */
287int afs_permission(struct inode *inode, int mask, struct nameidata *nd) 287int afs_permission(struct inode *inode, int mask)
288{ 288{
289 struct afs_vnode *vnode = AFS_FS_I(inode); 289 struct afs_vnode *vnode = AFS_FS_I(inode);
290 afs_access_t uninitialized_var(access); 290 afs_access_t uninitialized_var(access);
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index f1c2ea8342f5..5f1538c03b1b 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -243,8 +243,7 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
243 return -EIO; 243 return -EIO;
244} 244}
245 245
246static int bad_inode_permission(struct inode *inode, int mask, 246static int bad_inode_permission(struct inode *inode, int mask)
247 struct nameidata *nd)
248{ 247{
249 return -EIO; 248 return -EIO;
250} 249}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index fe5f6809cba6..1ec7076f7b24 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -267,7 +267,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
267 return 0; 267 return 0;
268} 268}
269 269
270static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd) 270static int cifs_permission(struct inode *inode, int mask)
271{ 271{
272 struct cifs_sb_info *cifs_sb; 272 struct cifs_sb_info *cifs_sb;
273 273
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 3d2580e00a3e..c5916228243c 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -137,9 +137,11 @@ exit:
137} 137}
138 138
139 139
140int coda_permission(struct inode *inode, int mask, struct nameidata *nd) 140int coda_permission(struct inode *inode, int mask)
141{ 141{
142 int error = 0; 142 int error = 0;
143
144 mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
143 145
144 if (!mask) 146 if (!mask)
145 return 0; 147 return 0;
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index c21a1f552a63..c38a98974fb0 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -24,8 +24,7 @@
24#include <linux/coda_psdev.h> 24#include <linux/coda_psdev.h>
25 25
26/* pioctl ops */ 26/* pioctl ops */
27static int coda_ioctl_permission(struct inode *inode, int mask, 27static int coda_ioctl_permission(struct inode *inode, int mask);
28 struct nameidata *nd);
29static int coda_pioctl(struct inode * inode, struct file * filp, 28static int coda_pioctl(struct inode * inode, struct file * filp,
30 unsigned int cmd, unsigned long user_data); 29 unsigned int cmd, unsigned long user_data);
31 30
@@ -42,8 +41,7 @@ const struct file_operations coda_ioctl_operations = {
42}; 41};
43 42
44/* the coda pioctl inode ops */ 43/* the coda pioctl inode ops */
45static int coda_ioctl_permission(struct inode *inode, int mask, 44static int coda_ioctl_permission(struct inode *inode, int mask)
46 struct nameidata *nd)
47{ 45{
48 return 0; 46 return 0;
49} 47}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index d755455e3bff..32f4228efcd5 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -830,22 +830,9 @@ out:
830} 830}
831 831
832static int 832static int
833ecryptfs_permission(struct inode *inode, int mask, struct nameidata *nd) 833ecryptfs_permission(struct inode *inode, int mask)
834{ 834{
835 int rc; 835 return permission(ecryptfs_inode_to_lower(inode), mask, NULL);
836
837 if (nd) {
838 struct vfsmount *vfsmnt_save = nd->path.mnt;
839 struct dentry *dentry_save = nd->path.dentry;
840
841 nd->path.mnt = ecryptfs_dentry_to_lower_mnt(nd->path.dentry);
842 nd->path.dentry = ecryptfs_dentry_to_lower(nd->path.dentry);
843 rc = permission(ecryptfs_inode_to_lower(inode), mask, nd);
844 nd->path.mnt = vfsmnt_save;
845 nd->path.dentry = dentry_save;
846 } else
847 rc = permission(ecryptfs_inode_to_lower(inode), mask, NULL);
848 return rc;
849} 836}
850 837
851/** 838/**
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index e58669e1b87c..ae8c4f850b27 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -294,7 +294,7 @@ ext2_check_acl(struct inode *inode, int mask)
294} 294}
295 295
296int 296int
297ext2_permission(struct inode *inode, int mask, struct nameidata *nd) 297ext2_permission(struct inode *inode, int mask)
298{ 298{
299 return generic_permission(inode, mask, ext2_check_acl); 299 return generic_permission(inode, mask, ext2_check_acl);
300} 300}
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index 0bde85bafe38..b42cf578554b 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -58,7 +58,7 @@ static inline int ext2_acl_count(size_t size)
58#define EXT2_ACL_NOT_CACHED ((void *)-1) 58#define EXT2_ACL_NOT_CACHED ((void *)-1)
59 59
60/* acl.c */ 60/* acl.c */
61extern int ext2_permission (struct inode *, int, struct nameidata *); 61extern int ext2_permission (struct inode *, int);
62extern int ext2_acl_chmod (struct inode *); 62extern int ext2_acl_chmod (struct inode *);
63extern int ext2_init_acl (struct inode *, struct inode *); 63extern int ext2_init_acl (struct inode *, struct inode *);
64 64
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index a754d1848173..b60bb241880c 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -299,7 +299,7 @@ ext3_check_acl(struct inode *inode, int mask)
299} 299}
300 300
301int 301int
302ext3_permission(struct inode *inode, int mask, struct nameidata *nd) 302ext3_permission(struct inode *inode, int mask)
303{ 303{
304 return generic_permission(inode, mask, ext3_check_acl); 304 return generic_permission(inode, mask, ext3_check_acl);
305} 305}
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 0d1e6279cbfd..42da16b8cac0 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -58,7 +58,7 @@ static inline int ext3_acl_count(size_t size)
58#define EXT3_ACL_NOT_CACHED ((void *)-1) 58#define EXT3_ACL_NOT_CACHED ((void *)-1)
59 59
60/* acl.c */ 60/* acl.c */
61extern int ext3_permission (struct inode *, int, struct nameidata *); 61extern int ext3_permission (struct inode *, int);
62extern int ext3_acl_chmod (struct inode *); 62extern int ext3_acl_chmod (struct inode *);
63extern int ext3_init_acl (handle_t *, struct inode *, struct inode *); 63extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
64 64
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 3c8dab880d91..c7d04e165446 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -299,7 +299,7 @@ ext4_check_acl(struct inode *inode, int mask)
299} 299}
300 300
301int 301int
302ext4_permission(struct inode *inode, int mask, struct nameidata *nd) 302ext4_permission(struct inode *inode, int mask)
303{ 303{
304 return generic_permission(inode, mask, ext4_check_acl); 304 return generic_permission(inode, mask, ext4_check_acl);
305} 305}
diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
index 26a5c1abf147..cd2b855a07d6 100644
--- a/fs/ext4/acl.h
+++ b/fs/ext4/acl.h
@@ -58,7 +58,7 @@ static inline int ext4_acl_count(size_t size)
58#define EXT4_ACL_NOT_CACHED ((void *)-1) 58#define EXT4_ACL_NOT_CACHED ((void *)-1)
59 59
60/* acl.c */ 60/* acl.c */
61extern int ext4_permission (struct inode *, int, struct nameidata *); 61extern int ext4_permission (struct inode *, int);
62extern int ext4_acl_chmod (struct inode *); 62extern int ext4_acl_chmod (struct inode *);
63extern int ext4_init_acl (handle_t *, struct inode *, struct inode *); 63extern int ext4_init_acl (handle_t *, struct inode *, struct inode *);
64 64
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 51d0035ff07e..48a7934cb950 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -898,7 +898,7 @@ static int fuse_access(struct inode *inode, int mask)
898 return PTR_ERR(req); 898 return PTR_ERR(req);
899 899
900 memset(&inarg, 0, sizeof(inarg)); 900 memset(&inarg, 0, sizeof(inarg));
901 inarg.mask = mask; 901 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
902 req->in.h.opcode = FUSE_ACCESS; 902 req->in.h.opcode = FUSE_ACCESS;
903 req->in.h.nodeid = get_node_id(inode); 903 req->in.h.nodeid = get_node_id(inode);
904 req->in.numargs = 1; 904 req->in.numargs = 1;
@@ -927,7 +927,7 @@ static int fuse_access(struct inode *inode, int mask)
927 * access request is sent. Execute permission is still checked 927 * access request is sent. Execute permission is still checked
928 * locally based on file mode. 928 * locally based on file mode.
929 */ 929 */
930static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) 930static int fuse_permission(struct inode *inode, int mask)
931{ 931{
932 struct fuse_conn *fc = get_fuse_conn(inode); 932 struct fuse_conn *fc = get_fuse_conn(inode);
933 bool refreshed = false; 933 bool refreshed = false;
@@ -962,7 +962,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
962 exist. So if permissions are revoked this won't be 962 exist. So if permissions are revoked this won't be
963 noticed immediately, only after the attribute 963 noticed immediately, only after the attribute
964 timeout has expired */ 964 timeout has expired */
965 } else if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) { 965 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
966 err = fuse_access(inode, mask); 966 err = fuse_access(inode, mask);
967 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 967 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
968 if (!(inode->i_mode & S_IXUGO)) { 968 if (!(inode->i_mode & S_IXUGO)) {
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 1e252dfc5294..4e982532f085 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -915,12 +915,6 @@ int gfs2_permission(struct inode *inode, int mask)
915 return error; 915 return error;
916} 916}
917 917
918static int gfs2_iop_permission(struct inode *inode, int mask,
919 struct nameidata *nd)
920{
921 return gfs2_permission(inode, mask);
922}
923
924static int setattr_size(struct inode *inode, struct iattr *attr) 918static int setattr_size(struct inode *inode, struct iattr *attr)
925{ 919{
926 struct gfs2_inode *ip = GFS2_I(inode); 920 struct gfs2_inode *ip = GFS2_I(inode);
@@ -1150,7 +1144,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
1150} 1144}
1151 1145
1152const struct inode_operations gfs2_file_iops = { 1146const struct inode_operations gfs2_file_iops = {
1153 .permission = gfs2_iop_permission, 1147 .permission = gfs2_permission,
1154 .setattr = gfs2_setattr, 1148 .setattr = gfs2_setattr,
1155 .getattr = gfs2_getattr, 1149 .getattr = gfs2_getattr,
1156 .setxattr = gfs2_setxattr, 1150 .setxattr = gfs2_setxattr,
@@ -1169,7 +1163,7 @@ const struct inode_operations gfs2_dir_iops = {
1169 .rmdir = gfs2_rmdir, 1163 .rmdir = gfs2_rmdir,
1170 .mknod = gfs2_mknod, 1164 .mknod = gfs2_mknod,
1171 .rename = gfs2_rename, 1165 .rename = gfs2_rename,
1172 .permission = gfs2_iop_permission, 1166 .permission = gfs2_permission,
1173 .setattr = gfs2_setattr, 1167 .setattr = gfs2_setattr,
1174 .getattr = gfs2_getattr, 1168 .getattr = gfs2_getattr,
1175 .setxattr = gfs2_setxattr, 1169 .setxattr = gfs2_setxattr,
@@ -1181,7 +1175,7 @@ const struct inode_operations gfs2_dir_iops = {
1181const struct inode_operations gfs2_symlink_iops = { 1175const struct inode_operations gfs2_symlink_iops = {
1182 .readlink = gfs2_readlink, 1176 .readlink = gfs2_readlink,
1183 .follow_link = gfs2_follow_link, 1177 .follow_link = gfs2_follow_link,
1184 .permission = gfs2_iop_permission, 1178 .permission = gfs2_permission,
1185 .setattr = gfs2_setattr, 1179 .setattr = gfs2_setattr,
1186 .getattr = gfs2_getattr, 1180 .getattr = gfs2_getattr,
1187 .setxattr = gfs2_setxattr, 1181 .setxattr = gfs2_setxattr,
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index dc4ec640e875..aa73f3fd5dd9 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -511,8 +511,7 @@ void hfs_clear_inode(struct inode *inode)
511 } 511 }
512} 512}
513 513
514static int hfs_permission(struct inode *inode, int mask, 514static int hfs_permission(struct inode *inode, int mask)
515 struct nameidata *nd)
516{ 515{
517 if (S_ISREG(inode->i_mode) && mask & MAY_EXEC) 516 if (S_ISREG(inode->i_mode) && mask & MAY_EXEC)
518 return 0; 517 return 0;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index cc3b5e24339b..d4014e3044d2 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -238,7 +238,7 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
238 perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev); 238 perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev);
239} 239}
240 240
241static int hfsplus_permission(struct inode *inode, int mask, struct nameidata *nd) 241static int hfsplus_permission(struct inode *inode, int mask)
242{ 242{
243 /* MAY_EXEC is also used for lookup, if no x bit is set allow lookup, 243 /* MAY_EXEC is also used for lookup, if no x bit is set allow lookup,
244 * open_exec has the same test, so it's still not executable, if a x bit 244 * open_exec has the same test, so it's still not executable, if a x bit
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 5222345ddccf..d6ecabf4d231 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -822,7 +822,7 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
822 return err; 822 return err;
823} 823}
824 824
825int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) 825int hostfs_permission(struct inode *ino, int desired)
826{ 826{
827 char *name; 827 char *name;
828 int r = 0, w = 0, x = 0, err; 828 int r = 0, w = 0, x = 0, err;
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 4c80404a9aba..d98713777a1b 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -314,7 +314,7 @@ static int jffs2_check_acl(struct inode *inode, int mask)
314 return -EAGAIN; 314 return -EAGAIN;
315} 315}
316 316
317int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd) 317int jffs2_permission(struct inode *inode, int mask)
318{ 318{
319 return generic_permission(inode, mask, jffs2_check_acl); 319 return generic_permission(inode, mask, jffs2_check_acl);
320} 320}
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 0bb7f003fd80..8ca058aed384 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -28,7 +28,7 @@ struct jffs2_acl_header {
28 28
29#define JFFS2_ACL_NOT_CACHED ((void *)-1) 29#define JFFS2_ACL_NOT_CACHED ((void *)-1)
30 30
31extern int jffs2_permission(struct inode *, int, struct nameidata *); 31extern int jffs2_permission(struct inode *, int);
32extern int jffs2_acl_chmod(struct inode *); 32extern int jffs2_acl_chmod(struct inode *);
33extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *); 33extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
34extern int jffs2_init_acl_post(struct inode *); 34extern int jffs2_init_acl_post(struct inode *);
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 4d84bdc88299..d3e5c33665de 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -140,7 +140,7 @@ static int jfs_check_acl(struct inode *inode, int mask)
140 return -EAGAIN; 140 return -EAGAIN;
141} 141}
142 142
143int jfs_permission(struct inode *inode, int mask, struct nameidata *nd) 143int jfs_permission(struct inode *inode, int mask)
144{ 144{
145 return generic_permission(inode, mask, jfs_check_acl); 145 return generic_permission(inode, mask, jfs_check_acl);
146} 146}
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index 455fa4292045..88475f10a389 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
23int jfs_permission(struct inode *, int, struct nameidata *); 23int jfs_permission(struct inode *, int);
24int jfs_init_acl(tid_t, struct inode *, struct inode *); 24int jfs_init_acl(tid_t, struct inode *, struct inode *);
25int jfs_setattr(struct dentry *, struct iattr *); 25int jfs_setattr(struct dentry *, struct iattr *);
26 26
diff --git a/fs/namei.c b/fs/namei.c
index 3b26a240ade9..46af98ed136b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -185,6 +185,8 @@ int generic_permission(struct inode *inode, int mask,
185{ 185{
186 umode_t mode = inode->i_mode; 186 umode_t mode = inode->i_mode;
187 187
188 mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
189
188 if (current->fsuid == inode->i_uid) 190 if (current->fsuid == inode->i_uid)
189 mode >>= 6; 191 mode >>= 6;
190 else { 192 else {
@@ -203,7 +205,7 @@ int generic_permission(struct inode *inode, int mask,
203 /* 205 /*
204 * If the DACs are ok we don't need any capability check. 206 * If the DACs are ok we don't need any capability check.
205 */ 207 */
206 if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) 208 if ((mask & ~mode) == 0)
207 return 0; 209 return 0;
208 210
209 check_capabilities: 211 check_capabilities:
@@ -228,7 +230,7 @@ int generic_permission(struct inode *inode, int mask,
228 230
229int permission(struct inode *inode, int mask, struct nameidata *nd) 231int permission(struct inode *inode, int mask, struct nameidata *nd)
230{ 232{
231 int retval, submask; 233 int retval;
232 struct vfsmount *mnt = NULL; 234 struct vfsmount *mnt = NULL;
233 235
234 if (nd) 236 if (nd)
@@ -261,9 +263,17 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
261 } 263 }
262 264
263 /* Ordinary permission routines do not understand MAY_APPEND. */ 265 /* Ordinary permission routines do not understand MAY_APPEND. */
264 submask = mask & ~MAY_APPEND;
265 if (inode->i_op && inode->i_op->permission) { 266 if (inode->i_op && inode->i_op->permission) {
266 retval = inode->i_op->permission(inode, submask, nd); 267 int extra = 0;
268 if (nd) {
269 if (nd->flags & LOOKUP_ACCESS)
270 extra |= MAY_ACCESS;
271 if (nd->flags & LOOKUP_CHDIR)
272 extra |= MAY_CHDIR;
273 if (nd->flags & LOOKUP_OPEN)
274 extra |= MAY_OPEN;
275 }
276 retval = inode->i_op->permission(inode, mask | extra);
267 if (!retval) { 277 if (!retval) {
268 /* 278 /*
269 * Exec permission on a regular file is denied if none 279 * Exec permission on a regular file is denied if none
@@ -277,7 +287,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
277 return -EACCES; 287 return -EACCES;
278 } 288 }
279 } else { 289 } else {
280 retval = generic_permission(inode, submask, NULL); 290 retval = generic_permission(inode, mask, NULL);
281 } 291 }
282 if (retval) 292 if (retval)
283 return retval; 293 return retval;
@@ -286,7 +296,8 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
286 if (retval) 296 if (retval)
287 return retval; 297 return retval;
288 298
289 return security_inode_permission(inode, mask, nd); 299 return security_inode_permission(inode,
300 mask & (MAY_READ|MAY_WRITE|MAY_EXEC), nd);
290} 301}
291 302
292/** 303/**
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 28a238dab23a..74f92b717f78 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1884,7 +1884,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
1884 return status; 1884 return status;
1885 nfs_access_add_cache(inode, &cache); 1885 nfs_access_add_cache(inode, &cache);
1886out: 1886out:
1887 if ((cache.mask & mask) == mask) 1887 if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
1888 return 0; 1888 return 0;
1889 return -EACCES; 1889 return -EACCES;
1890} 1890}
@@ -1907,17 +1907,17 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
1907 return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); 1907 return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
1908} 1908}
1909 1909
1910int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) 1910int nfs_permission(struct inode *inode, int mask)
1911{ 1911{
1912 struct rpc_cred *cred; 1912 struct rpc_cred *cred;
1913 int res = 0; 1913 int res = 0;
1914 1914
1915 nfs_inc_stats(inode, NFSIOS_VFSACCESS); 1915 nfs_inc_stats(inode, NFSIOS_VFSACCESS);
1916 1916
1917 if (mask == 0) 1917 if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
1918 goto out; 1918 goto out;
1919 /* Is this sys_access() ? */ 1919 /* Is this sys_access() ? */
1920 if (nd != NULL && (nd->flags & LOOKUP_ACCESS)) 1920 if (mask & MAY_ACCESS)
1921 goto force_lookup; 1921 goto force_lookup;
1922 1922
1923 switch (inode->i_mode & S_IFMT) { 1923 switch (inode->i_mode & S_IFMT) {
@@ -1926,8 +1926,7 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
1926 case S_IFREG: 1926 case S_IFREG:
1927 /* NFSv4 has atomic_open... */ 1927 /* NFSv4 has atomic_open... */
1928 if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN) 1928 if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)
1929 && nd != NULL 1929 && (mask & MAY_OPEN))
1930 && (nd->flags & LOOKUP_OPEN))
1931 goto out; 1930 goto out;
1932 break; 1931 break;
1933 case S_IFDIR: 1932 case S_IFDIR:
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index e8514e8b6ce8..be2dd95d3a1d 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1176,7 +1176,7 @@ bail:
1176 return err; 1176 return err;
1177} 1177}
1178 1178
1179int ocfs2_permission(struct inode *inode, int mask, struct nameidata *nd) 1179int ocfs2_permission(struct inode *inode, int mask)
1180{ 1180{
1181 int ret; 1181 int ret;
1182 1182
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 048ddcaf5c80..1e27b4d017ea 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -62,8 +62,7 @@ int ocfs2_lock_allocators(struct inode *inode, struct ocfs2_dinode *di,
62int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); 62int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
63int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, 63int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
64 struct kstat *stat); 64 struct kstat *stat);
65int ocfs2_permission(struct inode *inode, int mask, 65int ocfs2_permission(struct inode *inode, int mask);
66 struct nameidata *nd);
67 66
68int ocfs2_should_update_atime(struct inode *inode, 67int ocfs2_should_update_atime(struct inode *inode,
69 struct vfsmount *vfsmnt); 68 struct vfsmount *vfsmnt);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 81bce6791bfc..d82d800389f6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1859,8 +1859,7 @@ static const struct file_operations proc_fd_operations = {
1859 * /proc/pid/fd needs a special permission handler so that a process can still 1859 * /proc/pid/fd needs a special permission handler so that a process can still
1860 * access /proc/self/fd after it has executed a setuid(). 1860 * access /proc/self/fd after it has executed a setuid().
1861 */ 1861 */
1862static int proc_fd_permission(struct inode *inode, int mask, 1862static int proc_fd_permission(struct inode *inode, int mask)
1863 struct nameidata *nd)
1864{ 1863{
1865 int rv; 1864 int rv;
1866 1865
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index fa1ec2433e44..f9a8b892718f 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -292,7 +292,7 @@ out:
292 return ret; 292 return ret;
293} 293}
294 294
295static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *nd) 295static int proc_sys_permission(struct inode *inode, int mask)
296{ 296{
297 /* 297 /*
298 * sysctl entries that are not writeable, 298 * sysctl entries that are not writeable,
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index d7c4935c1034..bb3cb5b7cdb2 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -1250,7 +1250,7 @@ static int reiserfs_check_acl(struct inode *inode, int mask)
1250 return error; 1250 return error;
1251} 1251}
1252 1252
1253int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd) 1253int reiserfs_permission(struct inode *inode, int mask)
1254{ 1254{
1255 /* 1255 /*
1256 * We don't do permission checks on the internal objects. 1256 * We don't do permission checks on the internal objects.
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 2294783320cb..e4f8d51a5553 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -408,7 +408,7 @@ smb_file_release(struct inode *inode, struct file * file)
408 * privileges, so we need our own check for this. 408 * privileges, so we need our own check for this.
409 */ 409 */
410static int 410static int
411smb_file_permission(struct inode *inode, int mask, struct nameidata *nd) 411smb_file_permission(struct inode *inode, int mask)
412{ 412{
413 int mode = inode->i_mode; 413 int mode = inode->i_mode;
414 int error = 0; 414 int error = 0;
@@ -417,7 +417,7 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
417 417
418 /* Look at user permissions */ 418 /* Look at user permissions */
419 mode >>= 6; 419 mode >>= 6;
420 if ((mode & 7 & mask) != mask) 420 if (mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC))
421 error = -EACCES; 421 error = -EACCES;
422 return error; 422 return error;
423} 423}
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 2bf287ef5489..5fc61c824bb9 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -589,8 +589,7 @@ xfs_check_acl(
589STATIC int 589STATIC int
590xfs_vn_permission( 590xfs_vn_permission(
591 struct inode *inode, 591 struct inode *inode,
592 int mask, 592 int mask)
593 struct nameidata *nd)
594{ 593{
595 return generic_permission(inode, mask, xfs_check_acl); 594 return generic_permission(inode, mask, xfs_check_acl);
596} 595}
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index 31b75311e2ca..dcc228aa335a 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -37,7 +37,7 @@ extern const struct file_operations coda_ioctl_operations;
37/* operations shared over more than one file */ 37/* operations shared over more than one file */
38int coda_open(struct inode *i, struct file *f); 38int coda_open(struct inode *i, struct file *f);
39int coda_release(struct inode *i, struct file *f); 39int coda_release(struct inode *i, struct file *f);
40int coda_permission(struct inode *inode, int mask, struct nameidata *nd); 40int coda_permission(struct inode *inode, int mask);
41int coda_revalidate_inode(struct dentry *); 41int coda_revalidate_inode(struct dentry *);
42int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *); 42int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
43int coda_setattr(struct dentry *, struct iattr *); 43int coda_setattr(struct dentry *, struct iattr *);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7721a2ac9c0e..6c923c9b79bc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -60,6 +60,9 @@ extern int dir_notify_enable;
60#define MAY_WRITE 2 60#define MAY_WRITE 2
61#define MAY_READ 4 61#define MAY_READ 4
62#define MAY_APPEND 8 62#define MAY_APPEND 8
63#define MAY_ACCESS 16
64#define MAY_CHDIR 32
65#define MAY_OPEN 64
63 66
64#define FMODE_READ 1 67#define FMODE_READ 1
65#define FMODE_WRITE 2 68#define FMODE_WRITE 2
@@ -1272,7 +1275,7 @@ struct inode_operations {
1272 void * (*follow_link) (struct dentry *, struct nameidata *); 1275 void * (*follow_link) (struct dentry *, struct nameidata *);
1273 void (*put_link) (struct dentry *, struct nameidata *, void *); 1276 void (*put_link) (struct dentry *, struct nameidata *, void *);
1274 void (*truncate) (struct inode *); 1277 void (*truncate) (struct inode *);
1275 int (*permission) (struct inode *, int, struct nameidata *); 1278 int (*permission) (struct inode *, int);
1276 int (*setattr) (struct dentry *, struct iattr *); 1279 int (*setattr) (struct dentry *, struct iattr *);
1277 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); 1280 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
1278 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); 1281 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 29d261918734..f08f9ca602af 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -332,7 +332,7 @@ extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
332extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr); 332extern int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr);
333extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr); 333extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr);
334extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); 334extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
335extern int nfs_permission(struct inode *, int, struct nameidata *); 335extern int nfs_permission(struct inode *, int);
336extern int nfs_open(struct inode *, struct file *); 336extern int nfs_open(struct inode *, struct file *);
337extern int nfs_release(struct inode *, struct file *); 337extern int nfs_release(struct inode *, struct file *);
338extern int nfs_attribute_timeout(struct inode *inode); 338extern int nfs_attribute_timeout(struct inode *inode);
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 66a96814d614..af135ae895db 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -55,7 +55,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name);
55int reiserfs_delete_xattrs(struct inode *inode); 55int reiserfs_delete_xattrs(struct inode *inode);
56int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); 56int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
57int reiserfs_xattr_init(struct super_block *sb, int mount_flags); 57int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
58int reiserfs_permission(struct inode *inode, int mask, struct nameidata *nd); 58int reiserfs_permission(struct inode *inode, int mask);
59 59
60int reiserfs_xattr_del(struct inode *, const char *); 60int reiserfs_xattr_del(struct inode *, const char *);
61int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t); 61int reiserfs_xattr_get(const struct inode *, const char *, void *, size_t);
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index f2d12d5a21b8..fd83f2584b15 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -43,7 +43,7 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
43} 43}
44 44
45#ifdef CONFIG_TMPFS_POSIX_ACL 45#ifdef CONFIG_TMPFS_POSIX_ACL
46int shmem_permission(struct inode *, int, struct nameidata *); 46int shmem_permission(struct inode *, int);
47int shmem_acl_init(struct inode *, struct inode *); 47int shmem_acl_init(struct inode *, struct inode *);
48void shmem_acl_destroy_inode(struct inode *); 48void shmem_acl_destroy_inode(struct inode *);
49 49
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index ff5abcca5ddf..911d846f0503 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1516,9 +1516,9 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
1516 int op = 0, rc; 1516 int op = 0, rc;
1517 1517
1518 if (oldval) 1518 if (oldval)
1519 op |= 004; 1519 op |= MAY_READ;
1520 if (newval) 1520 if (newval)
1521 op |= 002; 1521 op |= MAY_WRITE;
1522 if (sysctl_perm(root, table, op)) 1522 if (sysctl_perm(root, table, op))
1523 return -EPERM; 1523 return -EPERM;
1524 1524
@@ -1560,7 +1560,7 @@ repeat:
1560 if (n == table->ctl_name) { 1560 if (n == table->ctl_name) {
1561 int error; 1561 int error;
1562 if (table->child) { 1562 if (table->child) {
1563 if (sysctl_perm(root, table, 001)) 1563 if (sysctl_perm(root, table, MAY_EXEC))
1564 return -EPERM; 1564 return -EPERM;
1565 name++; 1565 name++;
1566 nlen--; 1566 nlen--;
@@ -1635,7 +1635,7 @@ static int test_perm(int mode, int op)
1635 mode >>= 6; 1635 mode >>= 6;
1636 else if (in_egroup_p(0)) 1636 else if (in_egroup_p(0))
1637 mode >>= 3; 1637 mode >>= 3;
1638 if ((mode & op & 0007) == op) 1638 if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0)
1639 return 0; 1639 return 0;
1640 return -EACCES; 1640 return -EACCES;
1641} 1641}
@@ -1645,7 +1645,7 @@ int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
1645 int error; 1645 int error;
1646 int mode; 1646 int mode;
1647 1647
1648 error = security_sysctl(table, op); 1648 error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
1649 if (error) 1649 if (error)
1650 return error; 1650 return error;
1651 1651
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
index f5664c5b9eb1..8e5aadd7dcd6 100644
--- a/mm/shmem_acl.c
+++ b/mm/shmem_acl.c
@@ -191,7 +191,7 @@ shmem_check_acl(struct inode *inode, int mask)
191 * shmem_permission - permission() inode operation 191 * shmem_permission - permission() inode operation
192 */ 192 */
193int 193int
194shmem_permission(struct inode *inode, int mask, struct nameidata *nd) 194shmem_permission(struct inode *inode, int mask)
195{ 195{
196 return generic_permission(inode, mask, shmem_check_acl); 196 return generic_permission(inode, mask, shmem_check_acl);
197} 197}