diff options
-rw-r--r-- | Documentation/filesystems/9p.txt | 4 | ||||
-rw-r--r-- | fs/9p/acl.c | 78 | ||||
-rw-r--r-- | fs/9p/fid.c | 1 | ||||
-rw-r--r-- | fs/9p/v9fs.c | 22 | ||||
-rw-r--r-- | fs/9p/v9fs.h | 8 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 4 |
6 files changed, 110 insertions, 7 deletions
diff --git a/Documentation/filesystems/9p.txt b/Documentation/filesystems/9p.txt index f9765e8cf086..b22abba78fed 100644 --- a/Documentation/filesystems/9p.txt +++ b/Documentation/filesystems/9p.txt | |||
@@ -111,7 +111,7 @@ OPTIONS | |||
111 | This can be used to share devices/named pipes/sockets between | 111 | This can be used to share devices/named pipes/sockets between |
112 | hosts. This functionality will be expanded in later versions. | 112 | hosts. This functionality will be expanded in later versions. |
113 | 113 | ||
114 | access there are three access modes. | 114 | access there are four access modes. |
115 | user = if a user tries to access a file on v9fs | 115 | user = if a user tries to access a file on v9fs |
116 | filesystem for the first time, v9fs sends an | 116 | filesystem for the first time, v9fs sends an |
117 | attach command (Tattach) for that user. | 117 | attach command (Tattach) for that user. |
@@ -120,6 +120,8 @@ OPTIONS | |||
120 | the files on the mounted filesystem | 120 | the files on the mounted filesystem |
121 | any = v9fs does single attach and performs all | 121 | any = v9fs does single attach and performs all |
122 | operations as one user | 122 | operations as one user |
123 | client = ACL based access check on the 9p client | ||
124 | side for access validation | ||
123 | 125 | ||
124 | cachetag cache tag to use the specified persistent cache. | 126 | cachetag cache tag to use the specified persistent cache. |
125 | cache tags for existing cache sessions can be listed at | 127 | cache tags for existing cache sessions can be listed at |
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 | ||
26 | static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) | 27 | static 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 | ||
86 | int v9fs_check_acl(struct inode *inode, int mask) | 94 | int 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 | ||
226 | static 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 | |||
207 | static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, | 244 | static 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 | ||
272 | static 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 | |||
227 | static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, | 292 | static 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 | |||
36 | enum p9_session_flags { | 41 | enum 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"); |