diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/acl.c | 170 | ||||
-rw-r--r-- | fs/gfs2/acl.h | 24 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 18 |
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 | |||
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 | static int acl_get(struct gfs2_inode *ip, const char *name, | 30 | static 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 | ||
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 | }; | ||
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) \ | 19 | extern int gfs2_check_acl(struct inode *inode, int mask); |
21 | ((len) == GFS2_POSIX_ACL_ACCESS_LEN && \ | 20 | extern int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip); |
22 | !memcmp(GFS2_POSIX_ACL_ACCESS, (name), (len))) | 21 | extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); |
23 | 22 | extern 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 | |||
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); | ||
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 | ||
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 | static int gfs2_xattr_security_get(struct inode *inode, const char *name, | 1510 | static 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 | ||
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 | }; | ||
1551 | |||
1552 | struct xattr_handler *gfs2_xattr_handlers[] = { | 1534 | struct 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, |