diff options
| author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2010-09-27 14:57:41 -0400 |
|---|---|---|
| committer | Eric Van Hensbergen <ericvh@gmail.com> | 2010-10-28 10:08:46 -0400 |
| commit | 76381a42e4a5606774fd48413e6282cd7130ff2c (patch) | |
| tree | b7d6f73804b1bb7bca4198991c42122fa6ff159e | |
| parent | ad77dbce567128d59b37a14c9562c8af6f63aeca (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>
| -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"); |
