]> bbs.cooldavid.org Git - net-next-2.6.git/blob - fs/9p/acl.c
fs/9p: Implement POSIX ACL permission checking function
[net-next-2.6.git] / fs / 9p / acl.c
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 }