diff options
Diffstat (limited to 'fs/btrfs/acl.c')
-rw-r--r-- | fs/btrfs/acl.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 6df6d6ed74fd..15b5ca2a2606 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/posix_acl_xattr.h> | 22 | #include <linux/posix_acl_xattr.h> |
23 | #include <linux/posix_acl.h> | 23 | #include <linux/posix_acl.h> |
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/slab.h> | ||
25 | 26 | ||
26 | #include "ctree.h" | 27 | #include "ctree.h" |
27 | #include "btrfs_inode.h" | 28 | #include "btrfs_inode.h" |
@@ -59,6 +60,10 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) | |||
59 | size = __btrfs_getxattr(inode, name, value, size); | 60 | size = __btrfs_getxattr(inode, name, value, size); |
60 | if (size > 0) { | 61 | if (size > 0) { |
61 | acl = posix_acl_from_xattr(value, size); | 62 | acl = posix_acl_from_xattr(value, size); |
63 | if (IS_ERR(acl)) { | ||
64 | kfree(value); | ||
65 | return acl; | ||
66 | } | ||
62 | set_cached_acl(inode, type, acl); | 67 | set_cached_acl(inode, type, acl); |
63 | } | 68 | } |
64 | kfree(value); | 69 | kfree(value); |
@@ -159,6 +164,12 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, | |||
159 | int ret; | 164 | int ret; |
160 | struct posix_acl *acl = NULL; | 165 | struct posix_acl *acl = NULL; |
161 | 166 | ||
167 | if (!is_owner_or_cap(dentry->d_inode)) | ||
168 | return -EPERM; | ||
169 | |||
170 | if (!IS_POSIXACL(dentry->d_inode)) | ||
171 | return -EOPNOTSUPP; | ||
172 | |||
162 | if (value) { | 173 | if (value) { |
163 | acl = posix_acl_from_xattr(value, size); | 174 | acl = posix_acl_from_xattr(value, size); |
164 | if (acl == NULL) { | 175 | if (acl == NULL) { |
@@ -176,18 +187,23 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, | |||
176 | return ret; | 187 | return ret; |
177 | } | 188 | } |
178 | 189 | ||
179 | int btrfs_check_acl(struct inode *inode, int mask) | 190 | int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags) |
180 | { | 191 | { |
181 | struct posix_acl *acl; | ||
182 | int error = -EAGAIN; | 192 | int error = -EAGAIN; |
183 | 193 | ||
184 | acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS); | 194 | if (flags & IPERM_FLAG_RCU) { |
195 | if (!negative_cached_acl(inode, ACL_TYPE_ACCESS)) | ||
196 | error = -ECHILD; | ||
185 | 197 | ||
186 | if (IS_ERR(acl)) | 198 | } else { |
187 | return PTR_ERR(acl); | 199 | struct posix_acl *acl; |
188 | if (acl) { | 200 | acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS); |
189 | error = posix_acl_permission(inode, acl, mask); | 201 | if (IS_ERR(acl)) |
190 | posix_acl_release(acl); | 202 | return PTR_ERR(acl); |
203 | if (acl) { | ||
204 | error = posix_acl_permission(inode, acl, mask); | ||
205 | posix_acl_release(acl); | ||
206 | } | ||
191 | } | 207 | } |
192 | 208 | ||
193 | return error; | 209 | return error; |
@@ -281,14 +297,14 @@ int btrfs_acl_chmod(struct inode *inode) | |||
281 | return ret; | 297 | return ret; |
282 | } | 298 | } |
283 | 299 | ||
284 | struct xattr_handler btrfs_xattr_acl_default_handler = { | 300 | const struct xattr_handler btrfs_xattr_acl_default_handler = { |
285 | .prefix = POSIX_ACL_XATTR_DEFAULT, | 301 | .prefix = POSIX_ACL_XATTR_DEFAULT, |
286 | .flags = ACL_TYPE_DEFAULT, | 302 | .flags = ACL_TYPE_DEFAULT, |
287 | .get = btrfs_xattr_acl_get, | 303 | .get = btrfs_xattr_acl_get, |
288 | .set = btrfs_xattr_acl_set, | 304 | .set = btrfs_xattr_acl_set, |
289 | }; | 305 | }; |
290 | 306 | ||
291 | struct xattr_handler btrfs_xattr_acl_access_handler = { | 307 | const struct xattr_handler btrfs_xattr_acl_access_handler = { |
292 | .prefix = POSIX_ACL_XATTR_ACCESS, | 308 | .prefix = POSIX_ACL_XATTR_ACCESS, |
293 | .flags = ACL_TYPE_ACCESS, | 309 | .flags = ACL_TYPE_ACCESS, |
294 | .get = btrfs_xattr_acl_get, | 310 | .get = btrfs_xattr_acl_get, |