aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/acl.c')
-rw-r--r--fs/btrfs/acl.c36
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
179int btrfs_check_acl(struct inode *inode, int mask) 190int 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
284struct xattr_handler btrfs_xattr_acl_default_handler = { 300const 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
291struct xattr_handler btrfs_xattr_acl_access_handler = { 307const 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,