aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2010-09-27 14:57:41 -0400
committerEric Van Hensbergen <ericvh@gmail.com>2010-10-28 10:08:46 -0400
commit76381a42e4a5606774fd48413e6282cd7130ff2c (patch)
treeb7d6f73804b1bb7bca4198991c42122fa6ff159e /fs/9p
parentad77dbce567128d59b37a14c9562c8af6f63aeca (diff)
fs/9p: Add access = client option to opt in acl evaluation.
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/9p')
-rw-r--r--fs/9p/acl.c78
-rw-r--r--fs/9p/fid.c1
-rw-r--r--fs/9p/v9fs.c22
-rw-r--r--fs/9p/v9fs.h8
-rw-r--r--fs/9p/vfs_super.c4
5 files changed, 107 insertions, 6 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 8b3c54a4958c..12d602351dbe 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -22,6 +22,7 @@
22#include "xattr.h" 22#include "xattr.h"
23#include "acl.h" 23#include "acl.h"
24#include "v9fs_vfs.h" 24#include "v9fs_vfs.h"
25#include "v9fs.h"
25 26
26static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) 27static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
27{ 28{
@@ -55,7 +56,14 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
55{ 56{
56 int retval = 0; 57 int retval = 0;
57 struct posix_acl *pacl, *dacl; 58 struct posix_acl *pacl, *dacl;
59 struct v9fs_session_info *v9ses;
58 60
61 v9ses = v9fs_inode2v9ses(inode);
62 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) {
63 set_cached_acl(inode, ACL_TYPE_DEFAULT, NULL);
64 set_cached_acl(inode, ACL_TYPE_ACCESS, NULL);
65 return 0;
66 }
59 /* get the default/access acl values and cache them */ 67 /* get the default/access acl values and cache them */
60 dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT); 68 dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
61 pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS); 69 pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS);
@@ -85,7 +93,18 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)
85 93
86int v9fs_check_acl(struct inode *inode, int mask) 94int v9fs_check_acl(struct inode *inode, int mask)
87{ 95{
88 struct posix_acl *acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); 96 struct posix_acl *acl;
97 struct v9fs_session_info *v9ses;
98
99 v9ses = v9fs_inode2v9ses(inode);
100 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) {
101 /*
102 * On access = client mode get the acl
103 * values from the server
104 */
105 return 0;
106 }
107 acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);
89 108
90 if (IS_ERR(acl)) 109 if (IS_ERR(acl))
91 return PTR_ERR(acl); 110 return PTR_ERR(acl);
@@ -204,15 +223,41 @@ cleanup:
204 223
205} 224}
206 225
226static int v9fs_remote_get_acl(struct dentry *dentry, const char *name,
227 void *buffer, size_t size, int type)
228{
229 char *full_name;
230
231 switch (type) {
232 case ACL_TYPE_ACCESS:
233 full_name = POSIX_ACL_XATTR_ACCESS;
234 break;
235 case ACL_TYPE_DEFAULT:
236 full_name = POSIX_ACL_XATTR_DEFAULT;
237 break;
238 default:
239 BUG();
240 }
241 return v9fs_xattr_get(dentry, full_name, buffer, size);
242}
243
207static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, 244static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
208 void *buffer, size_t size, int type) 245 void *buffer, size_t size, int type)
209{ 246{
247 struct v9fs_session_info *v9ses;
210 struct posix_acl *acl; 248 struct posix_acl *acl;
211 int error; 249 int error;
212 250
213 if (strcmp(name, "") != 0) 251 if (strcmp(name, "") != 0)
214 return -EINVAL; 252 return -EINVAL;
215 253
254 v9ses = v9fs_inode2v9ses(dentry->d_inode);
255 /*
256 * We allow set/get/list of acl when access=client is not specified
257 */
258 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
259 return v9fs_remote_get_acl(dentry, name, buffer, size, type);
260
216 acl = v9fs_get_cached_acl(dentry->d_inode, type); 261 acl = v9fs_get_cached_acl(dentry->d_inode, type);
217 if (IS_ERR(acl)) 262 if (IS_ERR(acl))
218 return PTR_ERR(acl); 263 return PTR_ERR(acl);
@@ -224,16 +269,47 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
224 return error; 269 return error;
225} 270}
226 271
272static int v9fs_remote_set_acl(struct dentry *dentry, const char *name,
273 const void *value, size_t size,
274 int flags, int type)
275{
276 char *full_name;
277
278 switch (type) {
279 case ACL_TYPE_ACCESS:
280 full_name = POSIX_ACL_XATTR_ACCESS;
281 break;
282 case ACL_TYPE_DEFAULT:
283 full_name = POSIX_ACL_XATTR_DEFAULT;
284 break;
285 default:
286 BUG();
287 }
288 return v9fs_xattr_set(dentry, full_name, value, size, flags);
289}
290
291
227static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, 292static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
228 const void *value, size_t size, 293 const void *value, size_t size,
229 int flags, int type) 294 int flags, int type)
230{ 295{
231 int retval; 296 int retval;
232 struct posix_acl *acl; 297 struct posix_acl *acl;
298 struct v9fs_session_info *v9ses;
233 struct inode *inode = dentry->d_inode; 299 struct inode *inode = dentry->d_inode;
234 300
235 if (strcmp(name, "") != 0) 301 if (strcmp(name, "") != 0)
236 return -EINVAL; 302 return -EINVAL;
303
304 v9ses = v9fs_inode2v9ses(dentry->d_inode);
305 /*
306 * set the attribute on the remote. Without even looking at the
307 * xattr value. We leave it to the server to validate
308 */
309 if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
310 return v9fs_remote_set_acl(dentry, name,
311 value, size, flags, type);
312
237 if (S_ISLNK(inode->i_mode)) 313 if (S_ISLNK(inode->i_mode))
238 return -EOPNOTSUPP; 314 return -EOPNOTSUPP;
239 if (!is_owner_or_cap(inode)) 315 if (!is_owner_or_cap(inode))
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 6406f896bf95..b00223c99d70 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -149,6 +149,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
149 switch (access) { 149 switch (access) {
150 case V9FS_ACCESS_SINGLE: 150 case V9FS_ACCESS_SINGLE:
151 case V9FS_ACCESS_USER: 151 case V9FS_ACCESS_USER:
152 case V9FS_ACCESS_CLIENT:
152 uid = current_fsuid(); 153 uid = current_fsuid();
153 any = 0; 154 any = 0;
154 break; 155 break;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 38dc0e067599..2f77cd33ba83 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -193,7 +193,17 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
193 v9ses->flags |= V9FS_ACCESS_USER; 193 v9ses->flags |= V9FS_ACCESS_USER;
194 else if (strcmp(s, "any") == 0) 194 else if (strcmp(s, "any") == 0)
195 v9ses->flags |= V9FS_ACCESS_ANY; 195 v9ses->flags |= V9FS_ACCESS_ANY;
196 else { 196 else if (strcmp(s, "client") == 0) {
197#ifdef CONFIG_9P_FS_POSIX_ACL
198 v9ses->flags |= V9FS_ACCESS_CLIENT;
199#else
200 P9_DPRINTK(P9_DEBUG_ERROR,
201 "access=client option not supported\n");
202 kfree(s);
203 ret = -EINVAL;
204 goto free_and_return;
205#endif
206 } else {
197 v9ses->flags |= V9FS_ACCESS_SINGLE; 207 v9ses->flags |= V9FS_ACCESS_SINGLE;
198 v9ses->uid = simple_strtoul(s, &e, 10); 208 v9ses->uid = simple_strtoul(s, &e, 10);
199 if (*e != '\0') 209 if (*e != '\0')
@@ -278,6 +288,16 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
278 288
279 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; 289 v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
280 290
291 if (!v9fs_proto_dotl(v9ses) &&
292 ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
293 /*
294 * We support ACCESS_CLIENT only for dotl.
295 * Fall back to ACCESS_USER
296 */
297 v9ses->flags &= ~V9FS_ACCESS_MASK;
298 v9ses->flags |= V9FS_ACCESS_USER;
299 }
300 /*FIXME !! */
281 /* for legacy mode, fall back to V9FS_ACCESS_ANY */ 301 /* for legacy mode, fall back to V9FS_ACCESS_ANY */
282 if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) && 302 if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
283 ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { 303 ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 4c963c9fc41f..8bb7792afe2e 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -33,13 +33,17 @@
33 * 33 *
34 * Session flags reflect options selected by users at mount time 34 * Session flags reflect options selected by users at mount time
35 */ 35 */
36#define V9FS_ACCESS_ANY (V9FS_ACCESS_SINGLE | \
37 V9FS_ACCESS_USER | \
38 V9FS_ACCESS_CLIENT)
39#define V9FS_ACCESS_MASK V9FS_ACCESS_ANY
40
36enum p9_session_flags { 41enum p9_session_flags {
37 V9FS_PROTO_2000U = 0x01, 42 V9FS_PROTO_2000U = 0x01,
38 V9FS_PROTO_2000L = 0x02, 43 V9FS_PROTO_2000L = 0x02,
39 V9FS_ACCESS_SINGLE = 0x04, 44 V9FS_ACCESS_SINGLE = 0x04,
40 V9FS_ACCESS_USER = 0x08, 45 V9FS_ACCESS_USER = 0x08,
41 V9FS_ACCESS_ANY = 0x0C, 46 V9FS_ACCESS_CLIENT = 0x10
42 V9FS_ACCESS_MASK = 0x0C,
43}; 47};
44 48
45/* possible values of ->cache */ 49/* possible values of ->cache */
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 14da5778d44e..174643f4f901 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -90,7 +90,8 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
90 MS_NOATIME; 90 MS_NOATIME;
91 91
92#ifdef CONFIG_9P_FS_POSIX_ACL 92#ifdef CONFIG_9P_FS_POSIX_ACL
93 sb->s_flags |= MS_POSIXACL; 93 if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)
94 sb->s_flags |= MS_POSIXACL;
94#endif 95#endif
95 96
96 save_mount_options(sb, data); 97 save_mount_options(sb, data);
@@ -181,7 +182,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
181 retval = v9fs_get_acl(inode, fid); 182 retval = v9fs_get_acl(inode, fid);
182 if (retval) 183 if (retval)
183 goto release_sb; 184 goto release_sb;
184
185 v9fs_fid_add(root, fid); 185 v9fs_fid_add(root, fid);
186 186
187 P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); 187 P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");