diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2010-09-27 14:57:39 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2010-10-28 10:08:46 -0400 |
commit | 85ff872d3f4a62d076d698bd1fa15ca2a4d7c100 (patch) | |
tree | 16d74f328ccb0b81470b1fbc4cad1b37e4df7ab8 /fs | |
parent | 8e44a0805fc9d77475060280136aa491aa7d7060 (diff) |
fs/9p: Implement POSIX ACL permission checking function
The ACL value is fetched as a part of inode initialization
from the server and the permission checking function use the
cached value of the ACL
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/9p/Kconfig | 13 | ||||
-rw-r--r-- | fs/9p/Makefile | 1 | ||||
-rw-r--r-- | fs/9p/acl.c | 96 | ||||
-rw-r--r-- | fs/9p/acl.h | 27 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 10 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 9 | ||||
-rw-r--r-- | fs/9p/xattr.c | 48 | ||||
-rw-r--r-- | fs/9p/xattr.h | 4 |
8 files changed, 186 insertions, 22 deletions
diff --git a/fs/9p/Kconfig b/fs/9p/Kconfig index 795233702a4e..7e0511476797 100644 --- a/fs/9p/Kconfig +++ b/fs/9p/Kconfig | |||
@@ -17,3 +17,16 @@ config 9P_FSCACHE | |||
17 | Choose Y here to enable persistent, read-only local | 17 | Choose Y here to enable persistent, read-only local |
18 | caching support for 9p clients using FS-Cache | 18 | caching support for 9p clients using FS-Cache |
19 | 19 | ||
20 | |||
21 | config 9P_FS_POSIX_ACL | ||
22 | bool "9P POSIX Access Control Lists" | ||
23 | depends on 9P_FS | ||
24 | select FS_POSIX_ACL | ||
25 | help | ||
26 | POSIX Access Control Lists (ACLs) support permissions for users and | ||
27 | groups beyond the owner/group/world scheme. | ||
28 | |||
29 | To learn more about Access Control Lists, visit the POSIX ACLs for | ||
30 | Linux website <http://acl.bestbits.at/>. | ||
31 | |||
32 | If you don't know what Access Control Lists are, say N | ||
diff --git a/fs/9p/Makefile b/fs/9p/Makefile index 91fba025fcbe..f8ba37effd1b 100644 --- a/fs/9p/Makefile +++ b/fs/9p/Makefile | |||
@@ -13,3 +13,4 @@ obj-$(CONFIG_9P_FS) := 9p.o | |||
13 | xattr_user.o | 13 | xattr_user.o |
14 | 14 | ||
15 | 9p-$(CONFIG_9P_FSCACHE) += cache.o | 15 | 9p-$(CONFIG_9P_FSCACHE) += cache.o |
16 | 9p-$(CONFIG_9P_FS_POSIX_ACL) += acl.o | ||
diff --git a/fs/9p/acl.c b/fs/9p/acl.c new file mode 100644 index 000000000000..a8c013615a22 --- /dev/null +++ b/fs/9p/acl.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2010 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <net/9p/9p.h> | ||
18 | #include <net/9p/client.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/posix_acl_xattr.h> | ||
21 | #include "xattr.h" | ||
22 | #include "acl.h" | ||
23 | |||
24 | static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) | ||
25 | { | ||
26 | ssize_t size; | ||
27 | void *value = NULL; | ||
28 | struct posix_acl *acl = NULL;; | ||
29 | |||
30 | size = v9fs_fid_xattr_get(fid, name, NULL, 0); | ||
31 | if (size > 0) { | ||
32 | value = kzalloc(size, GFP_NOFS); | ||
33 | if (!value) | ||
34 | return ERR_PTR(-ENOMEM); | ||
35 | size = v9fs_fid_xattr_get(fid, name, value, size); | ||
36 | if (size > 0) { | ||
37 | acl = posix_acl_from_xattr(value, size); | ||
38 | if (IS_ERR(acl)) | ||
39 | goto err_out; | ||
40 | } | ||
41 | } else if (size == -ENODATA || size == 0 || | ||
42 | size == -ENOSYS || size == -EOPNOTSUPP) { | ||
43 | acl = NULL; | ||
44 | } else | ||
45 | acl = ERR_PTR(-EIO); | ||
46 | |||
47 | err_out: | ||
48 | kfree(value); | ||
49 | return acl; | ||
50 | } | ||
51 | |||
52 | int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) | ||
53 | { | ||
54 | int retval = 0; | ||
55 | struct posix_acl *pacl, *dacl; | ||
56 | |||
57 | /* get the default/access acl values and cache them */ | ||
58 | dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT); | ||
59 | pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS); | ||
60 | |||
61 | if (!IS_ERR(dacl) && !IS_ERR(pacl)) { | ||
62 | set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); | ||
63 | set_cached_acl(inode, ACL_TYPE_ACCESS, pacl); | ||
64 | posix_acl_release(dacl); | ||
65 | posix_acl_release(pacl); | ||
66 | } else | ||
67 | retval = -EIO; | ||
68 | |||
69 | return retval; | ||
70 | } | ||
71 | |||
72 | static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) | ||
73 | { | ||
74 | struct posix_acl *acl; | ||
75 | /* | ||
76 | * 9p Always cache the acl value when | ||
77 | * instantiating the inode (v9fs_inode_from_fid) | ||
78 | */ | ||
79 | acl = get_cached_acl(inode, type); | ||
80 | BUG_ON(acl == ACL_NOT_CACHED); | ||
81 | return acl; | ||
82 | } | ||
83 | |||
84 | int v9fs_check_acl(struct inode *inode, int mask) | ||
85 | { | ||
86 | struct posix_acl *acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); | ||
87 | |||
88 | if (IS_ERR(acl)) | ||
89 | return PTR_ERR(acl); | ||
90 | if (acl) { | ||
91 | int error = posix_acl_permission(inode, acl, mask); | ||
92 | posix_acl_release(acl); | ||
93 | return error; | ||
94 | } | ||
95 | return -EAGAIN; | ||
96 | } | ||
diff --git a/fs/9p/acl.h b/fs/9p/acl.h new file mode 100644 index 000000000000..b1414f7c82e0 --- /dev/null +++ b/fs/9p/acl.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2010 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | * | ||
13 | */ | ||
14 | #ifndef FS_9P_ACL_H | ||
15 | #define FS_9P_ACL_H | ||
16 | |||
17 | #ifdef CONFIG_9P_FS_POSIX_ACL | ||
18 | extern int v9fs_get_acl(struct inode *, struct p9_fid *); | ||
19 | extern int v9fs_check_acl(struct inode *inode, int mask); | ||
20 | #else | ||
21 | #define v9fs_check_acl NULL | ||
22 | static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) | ||
23 | { | ||
24 | return 0; | ||
25 | } | ||
26 | #endif | ||
27 | #endif /* FS_9P_XATTR_H */ | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c3d200d41dca..1249b8323961 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/xattr.h> | 38 | #include <linux/xattr.h> |
39 | #include <linux/posix_acl.h> | ||
39 | #include <net/9p/9p.h> | 40 | #include <net/9p/9p.h> |
40 | #include <net/9p/client.h> | 41 | #include <net/9p/client.h> |
41 | 42 | ||
@@ -44,6 +45,7 @@ | |||
44 | #include "fid.h" | 45 | #include "fid.h" |
45 | #include "cache.h" | 46 | #include "cache.h" |
46 | #include "xattr.h" | 47 | #include "xattr.h" |
48 | #include "acl.h" | ||
47 | 49 | ||
48 | static const struct inode_operations v9fs_dir_inode_operations; | 50 | static const struct inode_operations v9fs_dir_inode_operations; |
49 | static const struct inode_operations v9fs_dir_inode_operations_dotu; | 51 | static const struct inode_operations v9fs_dir_inode_operations_dotu; |
@@ -500,6 +502,11 @@ v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, | |||
500 | v9fs_vcookie_set_qid(ret, &st->qid); | 502 | v9fs_vcookie_set_qid(ret, &st->qid); |
501 | v9fs_cache_inode_get_cookie(ret); | 503 | v9fs_cache_inode_get_cookie(ret); |
502 | #endif | 504 | #endif |
505 | err = v9fs_get_acl(ret, fid); | ||
506 | if (err) { | ||
507 | iput(ret); | ||
508 | goto error; | ||
509 | } | ||
503 | kfree(st); | 510 | kfree(st); |
504 | return ret; | 511 | return ret; |
505 | error: | 512 | error: |
@@ -1959,7 +1966,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotl = { | |||
1959 | .getxattr = generic_getxattr, | 1966 | .getxattr = generic_getxattr, |
1960 | .removexattr = generic_removexattr, | 1967 | .removexattr = generic_removexattr, |
1961 | .listxattr = v9fs_listxattr, | 1968 | .listxattr = v9fs_listxattr, |
1962 | 1969 | .check_acl = v9fs_check_acl, | |
1963 | }; | 1970 | }; |
1964 | 1971 | ||
1965 | static const struct inode_operations v9fs_dir_inode_operations = { | 1972 | static const struct inode_operations v9fs_dir_inode_operations = { |
@@ -1986,6 +1993,7 @@ static const struct inode_operations v9fs_file_inode_operations_dotl = { | |||
1986 | .getxattr = generic_getxattr, | 1993 | .getxattr = generic_getxattr, |
1987 | .removexattr = generic_removexattr, | 1994 | .removexattr = generic_removexattr, |
1988 | .listxattr = v9fs_listxattr, | 1995 | .listxattr = v9fs_listxattr, |
1996 | .check_acl = v9fs_check_acl, | ||
1989 | }; | 1997 | }; |
1990 | 1998 | ||
1991 | static const struct inode_operations v9fs_symlink_inode_operations = { | 1999 | static const struct inode_operations v9fs_symlink_inode_operations = { |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 1d12ba0ed3db..14da5778d44e 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "v9fs_vfs.h" | 46 | #include "v9fs_vfs.h" |
47 | #include "fid.h" | 47 | #include "fid.h" |
48 | #include "xattr.h" | 48 | #include "xattr.h" |
49 | #include "acl.h" | ||
49 | 50 | ||
50 | static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; | 51 | static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; |
51 | 52 | ||
@@ -88,6 +89,10 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, | |||
88 | sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | | 89 | sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | |
89 | MS_NOATIME; | 90 | MS_NOATIME; |
90 | 91 | ||
92 | #ifdef CONFIG_9P_FS_POSIX_ACL | ||
93 | sb->s_flags |= MS_POSIXACL; | ||
94 | #endif | ||
95 | |||
91 | save_mount_options(sb, data); | 96 | save_mount_options(sb, data); |
92 | } | 97 | } |
93 | 98 | ||
@@ -149,7 +154,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
149 | goto release_sb; | 154 | goto release_sb; |
150 | } | 155 | } |
151 | sb->s_root = root; | 156 | sb->s_root = root; |
152 | |||
153 | if (v9fs_proto_dotl(v9ses)) { | 157 | if (v9fs_proto_dotl(v9ses)) { |
154 | struct p9_stat_dotl *st = NULL; | 158 | struct p9_stat_dotl *st = NULL; |
155 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | 159 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); |
@@ -174,6 +178,9 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
174 | p9stat_free(st); | 178 | p9stat_free(st); |
175 | kfree(st); | 179 | kfree(st); |
176 | } | 180 | } |
181 | retval = v9fs_get_acl(inode, fid); | ||
182 | if (retval) | ||
183 | goto release_sb; | ||
177 | 184 | ||
178 | v9fs_fid_add(root, fid); | 185 | v9fs_fid_add(root, fid); |
179 | 186 | ||
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index f88e5c2dc873..67ac6cfc1a07 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c | |||
@@ -21,30 +21,13 @@ | |||
21 | #include "fid.h" | 21 | #include "fid.h" |
22 | #include "xattr.h" | 22 | #include "xattr.h" |
23 | 23 | ||
24 | /* | 24 | ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, |
25 | * v9fs_xattr_get() | 25 | void *buffer, size_t buffer_size) |
26 | * | ||
27 | * Copy an extended attribute into the buffer | ||
28 | * provided, or compute the buffer size required. | ||
29 | * Buffer is NULL to compute the size of the buffer required. | ||
30 | * | ||
31 | * Returns a negative error number on failure, or the number of bytes | ||
32 | * used / required on success. | ||
33 | */ | ||
34 | ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, | ||
35 | void *buffer, size_t buffer_size) | ||
36 | { | 26 | { |
37 | ssize_t retval; | 27 | ssize_t retval; |
38 | int msize, read_count; | 28 | int msize, read_count; |
39 | u64 offset = 0, attr_size; | 29 | u64 offset = 0, attr_size; |
40 | struct p9_fid *fid, *attr_fid; | 30 | struct p9_fid *attr_fid; |
41 | |||
42 | P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu\n", | ||
43 | __func__, name, buffer_size); | ||
44 | |||
45 | fid = v9fs_fid_lookup(dentry); | ||
46 | if (IS_ERR(fid)) | ||
47 | return PTR_ERR(fid); | ||
48 | 31 | ||
49 | attr_fid = p9_client_xattrwalk(fid, name, &attr_size); | 32 | attr_fid = p9_client_xattrwalk(fid, name, &attr_size); |
50 | if (IS_ERR(attr_fid)) { | 33 | if (IS_ERR(attr_fid)) { |
@@ -88,6 +71,31 @@ error: | |||
88 | 71 | ||
89 | } | 72 | } |
90 | 73 | ||
74 | |||
75 | /* | ||
76 | * v9fs_xattr_get() | ||
77 | * | ||
78 | * Copy an extended attribute into the buffer | ||
79 | * provided, or compute the buffer size required. | ||
80 | * Buffer is NULL to compute the size of the buffer required. | ||
81 | * | ||
82 | * Returns a negative error number on failure, or the number of bytes | ||
83 | * used / required on success. | ||
84 | */ | ||
85 | ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, | ||
86 | void *buffer, size_t buffer_size) | ||
87 | { | ||
88 | struct p9_fid *fid; | ||
89 | |||
90 | P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu\n", | ||
91 | __func__, name, buffer_size); | ||
92 | fid = v9fs_fid_lookup(dentry); | ||
93 | if (IS_ERR(fid)) | ||
94 | return PTR_ERR(fid); | ||
95 | |||
96 | return v9fs_fid_xattr_get(fid, name, buffer, buffer_size); | ||
97 | } | ||
98 | |||
91 | /* | 99 | /* |
92 | * v9fs_xattr_set() | 100 | * v9fs_xattr_set() |
93 | * | 101 | * |
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h index 9ddf672ae5c4..ec908c693342 100644 --- a/fs/9p/xattr.h +++ b/fs/9p/xattr.h | |||
@@ -15,10 +15,14 @@ | |||
15 | #define FS_9P_XATTR_H | 15 | #define FS_9P_XATTR_H |
16 | 16 | ||
17 | #include <linux/xattr.h> | 17 | #include <linux/xattr.h> |
18 | #include <net/9p/9p.h> | ||
19 | #include <net/9p/client.h> | ||
18 | 20 | ||
19 | extern const struct xattr_handler *v9fs_xattr_handlers[]; | 21 | extern const struct xattr_handler *v9fs_xattr_handlers[]; |
20 | extern struct xattr_handler v9fs_xattr_user_handler; | 22 | extern struct xattr_handler v9fs_xattr_user_handler; |
21 | 23 | ||
24 | extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *, | ||
25 | void *, size_t); | ||
22 | extern ssize_t v9fs_xattr_get(struct dentry *, const char *, | 26 | extern ssize_t v9fs_xattr_get(struct dentry *, const char *, |
23 | void *, size_t); | 27 | void *, size_t); |
24 | extern int v9fs_xattr_set(struct dentry *, const char *, | 28 | extern int v9fs_xattr_set(struct dentry *, const char *, |