Commit 2646a1f61a3b5525914757f10fa12b5b94713648

Authored by Steven Whitehouse
1 parent f55073ff1e

GFS2: Fix up system xattrs

This code has been shamelessly stolen from XFS at the suggestion
of Christoph Hellwig. I've not added support for cached ACLs so
far... watch for that in a later patch, although this is designed
in such a way that they should be easy to add.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>

Showing 3 changed files with 120 additions and 92 deletions Side-by-side Diff

... ... @@ -12,6 +12,7 @@
12 12 #include <linux/spinlock.h>
13 13 #include <linux/completion.h>
14 14 #include <linux/buffer_head.h>
  15 +#include <linux/xattr.h>
15 16 #include <linux/posix_acl.h>
16 17 #include <linux/posix_acl_xattr.h>
17 18 #include <linux/gfs2_ondisk.h>
... ... @@ -26,61 +27,6 @@
26 27 #include "trans.h"
27 28 #include "util.h"
28 29  
29   -#define ACL_ACCESS 1
30   -#define ACL_DEFAULT 0
31   -
32   -int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
33   - struct gfs2_ea_request *er, int *remove, mode_t *mode)
34   -{
35   - struct posix_acl *acl;
36   - int error;
37   -
38   - error = gfs2_acl_validate_remove(ip, access);
39   - if (error)
40   - return error;
41   -
42   - if (!er->er_data)
43   - return -EINVAL;
44   -
45   - acl = posix_acl_from_xattr(er->er_data, er->er_data_len);
46   - if (IS_ERR(acl))
47   - return PTR_ERR(acl);
48   - if (!acl) {
49   - *remove = 1;
50   - return 0;
51   - }
52   -
53   - error = posix_acl_valid(acl);
54   - if (error)
55   - goto out;
56   -
57   - if (access) {
58   - error = posix_acl_equiv_mode(acl, mode);
59   - if (!error)
60   - *remove = 1;
61   - else if (error > 0)
62   - error = 0;
63   - }
64   -
65   -out:
66   - posix_acl_release(acl);
67   - return error;
68   -}
69   -
70   -int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access)
71   -{
72   - if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl)
73   - return -EOPNOTSUPP;
74   - if (!is_owner_or_cap(&ip->i_inode))
75   - return -EPERM;
76   - if (S_ISLNK(ip->i_inode.i_mode))
77   - return -EOPNOTSUPP;
78   - if (!access && !S_ISDIR(ip->i_inode.i_mode))
79   - return -EACCES;
80   -
81   - return 0;
82   -}
83   -
84 30 static int acl_get(struct gfs2_inode *ip, const char *name,
85 31 struct posix_acl **acl, struct gfs2_ea_location *el,
86 32 char **datap, unsigned int *lenp)
... ... @@ -276,4 +222,118 @@
276 222 brelse(el.el_bh);
277 223 return error;
278 224 }
  225 +
  226 +static int gfs2_acl_type(const char *name)
  227 +{
  228 + if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0)
  229 + return ACL_TYPE_ACCESS;
  230 + if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0)
  231 + return ACL_TYPE_DEFAULT;
  232 + return -EINVAL;
  233 +}
  234 +
  235 +static int gfs2_xattr_system_get(struct inode *inode, const char *name,
  236 + void *buffer, size_t size)
  237 +{
  238 + int type;
  239 +
  240 + type = gfs2_acl_type(name);
  241 + if (type < 0)
  242 + return type;
  243 +
  244 + return gfs2_xattr_get(inode, GFS2_EATYPE_SYS, name, buffer, size);
  245 +}
  246 +
  247 +static int gfs2_set_mode(struct inode *inode, mode_t mode)
  248 +{
  249 + int error = 0;
  250 +
  251 + if (mode != inode->i_mode) {
  252 + struct iattr iattr;
  253 +
  254 + iattr.ia_valid = ATTR_MODE;
  255 + iattr.ia_mode = mode;
  256 +
  257 + error = gfs2_setattr_simple(GFS2_I(inode), &iattr);
  258 + }
  259 +
  260 + return error;
  261 +}
  262 +
  263 +static int gfs2_xattr_system_set(struct inode *inode, const char *name,
  264 + const void *value, size_t size, int flags)
  265 +{
  266 + struct gfs2_sbd *sdp = GFS2_SB(inode);
  267 + struct posix_acl *acl = NULL;
  268 + int error = 0, type;
  269 +
  270 + if (!sdp->sd_args.ar_posix_acl)
  271 + return -EOPNOTSUPP;
  272 +
  273 + type = gfs2_acl_type(name);
  274 + if (type < 0)
  275 + return type;
  276 + if (flags & XATTR_CREATE)
  277 + return -EINVAL;
  278 + if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
  279 + return value ? -EACCES : 0;
  280 + if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
  281 + return -EPERM;
  282 + if (S_ISLNK(inode->i_mode))
  283 + return -EOPNOTSUPP;
  284 +
  285 + if (!value)
  286 + goto set_acl;
  287 +
  288 + acl = posix_acl_from_xattr(value, size);
  289 + if (!acl) {
  290 + /*
  291 + * acl_set_file(3) may request that we set default ACLs with
  292 + * zero length -- defend (gracefully) against that here.
  293 + */
  294 + goto out;
  295 + }
  296 + if (IS_ERR(acl)) {
  297 + error = PTR_ERR(acl);
  298 + goto out;
  299 + }
  300 +
  301 + error = posix_acl_valid(acl);
  302 + if (error)
  303 + goto out_release;
  304 +
  305 + error = -EINVAL;
  306 + if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
  307 + goto out_release;
  308 +
  309 + if (type == ACL_TYPE_ACCESS) {
  310 + mode_t mode = inode->i_mode;
  311 + error = posix_acl_equiv_mode(acl, &mode);
  312 +
  313 + if (error <= 0) {
  314 + posix_acl_release(acl);
  315 + acl = NULL;
  316 +
  317 + if (error < 0)
  318 + return error;
  319 + }
  320 +
  321 + error = gfs2_set_mode(inode, mode);
  322 + if (error)
  323 + goto out_release;
  324 + }
  325 +
  326 +set_acl:
  327 + error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, 0);
  328 +out_release:
  329 + posix_acl_release(acl);
  330 +out:
  331 + return error;
  332 +}
  333 +
  334 +struct xattr_handler gfs2_xattr_system_handler = {
  335 + .prefix = XATTR_SYSTEM_PREFIX,
  336 + .get = gfs2_xattr_system_get,
  337 + .set = gfs2_xattr_system_set,
  338 +};
... ... @@ -13,27 +13,13 @@
13 13 #include "incore.h"
14 14  
15 15 #define GFS2_POSIX_ACL_ACCESS "posix_acl_access"
16   -#define GFS2_POSIX_ACL_ACCESS_LEN 16
17 16 #define GFS2_POSIX_ACL_DEFAULT "posix_acl_default"
18   -#define GFS2_POSIX_ACL_DEFAULT_LEN 17
  17 +#define GFS2_ACL_MAX_ENTRIES 25
19 18  
20   -#define GFS2_ACL_IS_ACCESS(name, len) \
21   - ((len) == GFS2_POSIX_ACL_ACCESS_LEN && \
22   - !memcmp(GFS2_POSIX_ACL_ACCESS, (name), (len)))
23   -
24   -#define GFS2_ACL_IS_DEFAULT(name, len) \
25   - ((len) == GFS2_POSIX_ACL_DEFAULT_LEN && \
26   - !memcmp(GFS2_POSIX_ACL_DEFAULT, (name), (len)))
27   -
28   -struct gfs2_ea_request;
29   -
30   -int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
31   - struct gfs2_ea_request *er,
32   - int *remove, mode_t *mode);
33   -int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access);
34   -int gfs2_check_acl(struct inode *inode, int mask);
35   -int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
36   -int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
  19 +extern int gfs2_check_acl(struct inode *inode, int mask);
  20 +extern int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
  21 +extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
  22 +extern struct xattr_handler gfs2_xattr_system_handler;
37 23  
38 24 #endif /* __ACL_DOT_H__ */
... ... @@ -1507,18 +1507,6 @@
1507 1507 return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags);
1508 1508 }
1509 1509  
1510   -static int gfs2_xattr_system_get(struct inode *inode, const char *name,
1511   - void *buffer, size_t size)
1512   -{
1513   - return gfs2_xattr_get(inode, GFS2_EATYPE_SYS, name, buffer, size);
1514   -}
1515   -
1516   -static int gfs2_xattr_system_set(struct inode *inode, const char *name,
1517   - const void *value, size_t size, int flags)
1518   -{
1519   - return gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, flags);
1520   -}
1521   -
1522 1510 static int gfs2_xattr_security_get(struct inode *inode, const char *name,
1523 1511 void *buffer, size_t size)
1524 1512 {
... ... @@ -1541,12 +1529,6 @@
1541 1529 .prefix = XATTR_SECURITY_PREFIX,
1542 1530 .get = gfs2_xattr_security_get,
1543 1531 .set = gfs2_xattr_security_set,
1544   -};
1545   -
1546   -static struct xattr_handler gfs2_xattr_system_handler = {
1547   - .prefix = XATTR_SYSTEM_PREFIX,
1548   - .get = gfs2_xattr_system_get,
1549   - .set = gfs2_xattr_system_set,
1550 1532 };
1551 1533  
1552 1534 struct xattr_handler *gfs2_xattr_handlers[] = {