aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2009-10-02 06:50:54 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-12-03 06:43:05 -0500
commit2646a1f61a3b5525914757f10fa12b5b94713648 (patch)
tree9f6b7bdad5fb85963cbf05d2215f960b7ac3beaa /fs/gfs2
parentf55073ff1eaf99f6b3bc62134a456638bca043a3 (diff)
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>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/acl.c170
-rw-r--r--fs/gfs2/acl.h24
-rw-r--r--fs/gfs2/xattr.c18
3 files changed, 120 insertions, 92 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 3fc4e3ac7d84..2168da121647 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -12,6 +12,7 @@
12#include <linux/spinlock.h> 12#include <linux/spinlock.h>
13#include <linux/completion.h> 13#include <linux/completion.h>
14#include <linux/buffer_head.h> 14#include <linux/buffer_head.h>
15#include <linux/xattr.h>
15#include <linux/posix_acl.h> 16#include <linux/posix_acl.h>
16#include <linux/posix_acl_xattr.h> 17#include <linux/posix_acl_xattr.h>
17#include <linux/gfs2_ondisk.h> 18#include <linux/gfs2_ondisk.h>
@@ -26,61 +27,6 @@
26#include "trans.h" 27#include "trans.h"
27#include "util.h" 28#include "util.h"
28 29
29#define ACL_ACCESS 1
30#define ACL_DEFAULT 0
31
32int 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
65out:
66 posix_acl_release(acl);
67 return error;
68}
69
70int 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
84static int acl_get(struct gfs2_inode *ip, const char *name, 30static int acl_get(struct gfs2_inode *ip, const char *name,
85 struct posix_acl **acl, struct gfs2_ea_location *el, 31 struct posix_acl **acl, struct gfs2_ea_location *el,
86 char **datap, unsigned int *lenp) 32 char **datap, unsigned int *lenp)
@@ -277,3 +223,117 @@ out_brelse:
277 return error; 223 return error;
278} 224}
279 225
226static 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
235static 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
247static 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
263static 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
326set_acl:
327 error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, 0);
328out_release:
329 posix_acl_release(acl);
330out:
331 return error;
332}
333
334struct xattr_handler gfs2_xattr_system_handler = {
335 .prefix = XATTR_SYSTEM_PREFIX,
336 .get = gfs2_xattr_system_get,
337 .set = gfs2_xattr_system_set,
338};
339
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h
index 6751930bfb64..cc954390b6da 100644
--- a/fs/gfs2/acl.h
+++ b/fs/gfs2/acl.h
@@ -13,26 +13,12 @@
13#include "incore.h" 13#include "incore.h"
14 14
15#define GFS2_POSIX_ACL_ACCESS "posix_acl_access" 15#define GFS2_POSIX_ACL_ACCESS "posix_acl_access"
16#define GFS2_POSIX_ACL_ACCESS_LEN 16
17#define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" 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) \ 19extern int gfs2_check_acl(struct inode *inode, int mask);
21 ((len) == GFS2_POSIX_ACL_ACCESS_LEN && \ 20extern int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
22 !memcmp(GFS2_POSIX_ACL_ACCESS, (name), (len))) 21extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
23 22extern struct xattr_handler gfs2_xattr_system_handler;
24#define GFS2_ACL_IS_DEFAULT(name, len) \
25 ((len) == GFS2_POSIX_ACL_DEFAULT_LEN && \
26 !memcmp(GFS2_POSIX_ACL_DEFAULT, (name), (len)))
27
28struct gfs2_ea_request;
29
30int gfs2_acl_validate_set(struct gfs2_inode *ip, int access,
31 struct gfs2_ea_request *er,
32 int *remove, mode_t *mode);
33int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access);
34int gfs2_check_acl(struct inode *inode, int mask);
35int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip);
36int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr);
37 23
38#endif /* __ACL_DOT_H__ */ 24#endif /* __ACL_DOT_H__ */
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 8a0f8ef6ee27..6b803540951e 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -1507,18 +1507,6 @@ static int gfs2_xattr_user_set(struct inode *inode, const char *name,
1507 return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags); 1507 return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags);
1508} 1508}
1509 1509
1510static 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
1516static 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
1522static int gfs2_xattr_security_get(struct inode *inode, const char *name, 1510static int gfs2_xattr_security_get(struct inode *inode, const char *name,
1523 void *buffer, size_t size) 1511 void *buffer, size_t size)
1524{ 1512{
@@ -1543,12 +1531,6 @@ static struct xattr_handler gfs2_xattr_security_handler = {
1543 .set = gfs2_xattr_security_set, 1531 .set = gfs2_xattr_security_set,
1544}; 1532};
1545 1533
1546static 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};
1551
1552struct xattr_handler *gfs2_xattr_handlers[] = { 1534struct xattr_handler *gfs2_xattr_handlers[] = {
1553 &gfs2_xattr_user_handler, 1535 &gfs2_xattr_user_handler,
1554 &gfs2_xattr_security_handler, 1536 &gfs2_xattr_security_handler,