diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 16:32:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 16:32:10 -0500 |
commit | ddf1d6238dd13a3bd948e8fcb1109798ef0af49b (patch) | |
tree | daa25447e4b791b2868a0338f872975ec480862b /fs | |
parent | 32fb378437a1d716e72a442237d7ead1f435ecf0 (diff) | |
parent | 764a5c6b1fa4306dd7573c1d80914254909cd036 (diff) |
Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs xattr updates from Al Viro:
"Andreas' xattr cleanup series.
It's a followup to his xattr work that went in last cycle; -0.5KLoC"
* 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
xattr handlers: Simplify list operation
ocfs2: Replace list xattr handler operations
nfs: Move call to security_inode_listsecurity into nfs_listxattr
xfs: Change how listxattr generates synthetic attributes
tmpfs: listxattr should include POSIX ACL xattrs
tmpfs: Use xattr handler infrastructure
btrfs: Use xattr handler infrastructure
vfs: Distinguish between full xattr names and proper prefixes
posix acls: Remove duplicate xattr name definitions
gfs2: Remove gfs2_xattr_acl_chmod
vfs: Remove vfs_xattr_cmp
Diffstat (limited to 'fs')
44 files changed, 457 insertions, 948 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index a7e28890f5ef..9da967f38387 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c | |||
@@ -67,8 +67,8 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | /* get the default/access acl values and cache them */ | 69 | /* get the default/access acl values and cache them */ |
70 | dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT); | 70 | dacl = __v9fs_get_acl(fid, XATTR_NAME_POSIX_ACL_DEFAULT); |
71 | pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS); | 71 | pacl = __v9fs_get_acl(fid, XATTR_NAME_POSIX_ACL_ACCESS); |
72 | 72 | ||
73 | if (!IS_ERR(dacl) && !IS_ERR(pacl)) { | 73 | if (!IS_ERR(dacl) && !IS_ERR(pacl)) { |
74 | set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); | 74 | set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); |
@@ -133,10 +133,10 @@ static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl) | |||
133 | goto err_free_out; | 133 | goto err_free_out; |
134 | switch (type) { | 134 | switch (type) { |
135 | case ACL_TYPE_ACCESS: | 135 | case ACL_TYPE_ACCESS: |
136 | name = POSIX_ACL_XATTR_ACCESS; | 136 | name = XATTR_NAME_POSIX_ACL_ACCESS; |
137 | break; | 137 | break; |
138 | case ACL_TYPE_DEFAULT: | 138 | case ACL_TYPE_DEFAULT: |
139 | name = POSIX_ACL_XATTR_DEFAULT; | 139 | name = XATTR_NAME_POSIX_ACL_DEFAULT; |
140 | break; | 140 | break; |
141 | default: | 141 | default: |
142 | BUG(); | 142 | BUG(); |
@@ -220,15 +220,12 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler, | |||
220 | struct posix_acl *acl; | 220 | struct posix_acl *acl; |
221 | int error; | 221 | int error; |
222 | 222 | ||
223 | if (strcmp(name, "") != 0) | ||
224 | return -EINVAL; | ||
225 | |||
226 | v9ses = v9fs_dentry2v9ses(dentry); | 223 | v9ses = v9fs_dentry2v9ses(dentry); |
227 | /* | 224 | /* |
228 | * We allow set/get/list of acl when access=client is not specified | 225 | * We allow set/get/list of acl when access=client is not specified |
229 | */ | 226 | */ |
230 | if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) | 227 | if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) |
231 | return v9fs_xattr_get(dentry, handler->prefix, buffer, size); | 228 | return v9fs_xattr_get(dentry, handler->name, buffer, size); |
232 | 229 | ||
233 | acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags); | 230 | acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags); |
234 | if (IS_ERR(acl)) | 231 | if (IS_ERR(acl)) |
@@ -250,16 +247,13 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, | |||
250 | struct v9fs_session_info *v9ses; | 247 | struct v9fs_session_info *v9ses; |
251 | struct inode *inode = d_inode(dentry); | 248 | struct inode *inode = d_inode(dentry); |
252 | 249 | ||
253 | if (strcmp(name, "") != 0) | ||
254 | return -EINVAL; | ||
255 | |||
256 | v9ses = v9fs_dentry2v9ses(dentry); | 250 | v9ses = v9fs_dentry2v9ses(dentry); |
257 | /* | 251 | /* |
258 | * set the attribute on the remote. Without even looking at the | 252 | * set the attribute on the remote. Without even looking at the |
259 | * xattr value. We leave it to the server to validate | 253 | * xattr value. We leave it to the server to validate |
260 | */ | 254 | */ |
261 | if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) | 255 | if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) |
262 | return v9fs_xattr_set(dentry, handler->prefix, value, size, | 256 | return v9fs_xattr_set(dentry, handler->name, value, size, |
263 | flags); | 257 | flags); |
264 | 258 | ||
265 | if (S_ISLNK(inode->i_mode)) | 259 | if (S_ISLNK(inode->i_mode)) |
@@ -319,7 +313,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, | |||
319 | default: | 313 | default: |
320 | BUG(); | 314 | BUG(); |
321 | } | 315 | } |
322 | retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags); | 316 | retval = v9fs_xattr_set(dentry, handler->name, value, size, flags); |
323 | if (!retval) | 317 | if (!retval) |
324 | set_cached_acl(inode, handler->flags, acl); | 318 | set_cached_acl(inode, handler->flags, acl); |
325 | err_out: | 319 | err_out: |
@@ -328,14 +322,14 @@ err_out: | |||
328 | } | 322 | } |
329 | 323 | ||
330 | const struct xattr_handler v9fs_xattr_acl_access_handler = { | 324 | const struct xattr_handler v9fs_xattr_acl_access_handler = { |
331 | .prefix = POSIX_ACL_XATTR_ACCESS, | 325 | .name = XATTR_NAME_POSIX_ACL_ACCESS, |
332 | .flags = ACL_TYPE_ACCESS, | 326 | .flags = ACL_TYPE_ACCESS, |
333 | .get = v9fs_xattr_get_acl, | 327 | .get = v9fs_xattr_get_acl, |
334 | .set = v9fs_xattr_set_acl, | 328 | .set = v9fs_xattr_set_acl, |
335 | }; | 329 | }; |
336 | 330 | ||
337 | const struct xattr_handler v9fs_xattr_acl_default_handler = { | 331 | const struct xattr_handler v9fs_xattr_acl_default_handler = { |
338 | .prefix = POSIX_ACL_XATTR_DEFAULT, | 332 | .name = XATTR_NAME_POSIX_ACL_DEFAULT, |
339 | .flags = ACL_TYPE_DEFAULT, | 333 | .flags = ACL_TYPE_DEFAULT, |
340 | .get = v9fs_xattr_get_acl, | 334 | .get = v9fs_xattr_get_acl, |
341 | .set = v9fs_xattr_set_acl, | 335 | .set = v9fs_xattr_set_acl, |
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index e3d026ac382e..9dd9b47a6c1a 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c | |||
@@ -143,8 +143,6 @@ static int v9fs_xattr_handler_get(const struct xattr_handler *handler, | |||
143 | { | 143 | { |
144 | const char *full_name = xattr_full_name(handler, name); | 144 | const char *full_name = xattr_full_name(handler, name); |
145 | 145 | ||
146 | if (strcmp(name, "") == 0) | ||
147 | return -EINVAL; | ||
148 | return v9fs_xattr_get(dentry, full_name, buffer, size); | 146 | return v9fs_xattr_get(dentry, full_name, buffer, size); |
149 | } | 147 | } |
150 | 148 | ||
@@ -154,8 +152,6 @@ static int v9fs_xattr_handler_set(const struct xattr_handler *handler, | |||
154 | { | 152 | { |
155 | const char *full_name = xattr_full_name(handler, name); | 153 | const char *full_name = xattr_full_name(handler, name); |
156 | 154 | ||
157 | if (strcmp(name, "") == 0) | ||
158 | return -EINVAL; | ||
159 | return v9fs_xattr_set(dentry, full_name, value, size, flags); | 155 | return v9fs_xattr_set(dentry, full_name, value, size, flags); |
160 | } | 156 | } |
161 | 157 | ||
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 9a0124a95851..f89db0c21b51 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -37,10 +37,10 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type) | |||
37 | 37 | ||
38 | switch (type) { | 38 | switch (type) { |
39 | case ACL_TYPE_ACCESS: | 39 | case ACL_TYPE_ACCESS: |
40 | name = POSIX_ACL_XATTR_ACCESS; | 40 | name = XATTR_NAME_POSIX_ACL_ACCESS; |
41 | break; | 41 | break; |
42 | case ACL_TYPE_DEFAULT: | 42 | case ACL_TYPE_DEFAULT: |
43 | name = POSIX_ACL_XATTR_DEFAULT; | 43 | name = XATTR_NAME_POSIX_ACL_DEFAULT; |
44 | break; | 44 | break; |
45 | default: | 45 | default: |
46 | BUG(); | 46 | BUG(); |
@@ -81,7 +81,7 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, | |||
81 | 81 | ||
82 | switch (type) { | 82 | switch (type) { |
83 | case ACL_TYPE_ACCESS: | 83 | case ACL_TYPE_ACCESS: |
84 | name = POSIX_ACL_XATTR_ACCESS; | 84 | name = XATTR_NAME_POSIX_ACL_ACCESS; |
85 | if (acl) { | 85 | if (acl) { |
86 | ret = posix_acl_equiv_mode(acl, &inode->i_mode); | 86 | ret = posix_acl_equiv_mode(acl, &inode->i_mode); |
87 | if (ret < 0) | 87 | if (ret < 0) |
@@ -94,7 +94,7 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, | |||
94 | case ACL_TYPE_DEFAULT: | 94 | case ACL_TYPE_DEFAULT: |
95 | if (!S_ISDIR(inode->i_mode)) | 95 | if (!S_ISDIR(inode->i_mode)) |
96 | return acl ? -EINVAL : 0; | 96 | return acl ? -EINVAL : 0; |
97 | name = POSIX_ACL_XATTR_DEFAULT; | 97 | name = XATTR_NAME_POSIX_ACL_DEFAULT; |
98 | break; | 98 | break; |
99 | default: | 99 | default: |
100 | return -EINVAL; | 100 | return -EINVAL; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1a41a65fd2ff..3b8856e182ae 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3550,10 +3550,10 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf, | |||
3550 | int scanned = 0; | 3550 | int scanned = 0; |
3551 | 3551 | ||
3552 | if (!xattr_access) { | 3552 | if (!xattr_access) { |
3553 | xattr_access = btrfs_name_hash(POSIX_ACL_XATTR_ACCESS, | 3553 | xattr_access = btrfs_name_hash(XATTR_NAME_POSIX_ACL_ACCESS, |
3554 | strlen(POSIX_ACL_XATTR_ACCESS)); | 3554 | strlen(XATTR_NAME_POSIX_ACL_ACCESS)); |
3555 | xattr_default = btrfs_name_hash(POSIX_ACL_XATTR_DEFAULT, | 3555 | xattr_default = btrfs_name_hash(XATTR_NAME_POSIX_ACL_DEFAULT, |
3556 | strlen(POSIX_ACL_XATTR_DEFAULT)); | 3556 | strlen(XATTR_NAME_POSIX_ACL_DEFAULT)); |
3557 | } | 3557 | } |
3558 | 3558 | ||
3559 | slot++; | 3559 | slot++; |
@@ -9996,7 +9996,7 @@ static const struct inode_operations btrfs_dir_inode_operations = { | |||
9996 | .setattr = btrfs_setattr, | 9996 | .setattr = btrfs_setattr, |
9997 | .mknod = btrfs_mknod, | 9997 | .mknod = btrfs_mknod, |
9998 | .setxattr = btrfs_setxattr, | 9998 | .setxattr = btrfs_setxattr, |
9999 | .getxattr = btrfs_getxattr, | 9999 | .getxattr = generic_getxattr, |
10000 | .listxattr = btrfs_listxattr, | 10000 | .listxattr = btrfs_listxattr, |
10001 | .removexattr = btrfs_removexattr, | 10001 | .removexattr = btrfs_removexattr, |
10002 | .permission = btrfs_permission, | 10002 | .permission = btrfs_permission, |
@@ -10073,7 +10073,7 @@ static const struct inode_operations btrfs_file_inode_operations = { | |||
10073 | .getattr = btrfs_getattr, | 10073 | .getattr = btrfs_getattr, |
10074 | .setattr = btrfs_setattr, | 10074 | .setattr = btrfs_setattr, |
10075 | .setxattr = btrfs_setxattr, | 10075 | .setxattr = btrfs_setxattr, |
10076 | .getxattr = btrfs_getxattr, | 10076 | .getxattr = generic_getxattr, |
10077 | .listxattr = btrfs_listxattr, | 10077 | .listxattr = btrfs_listxattr, |
10078 | .removexattr = btrfs_removexattr, | 10078 | .removexattr = btrfs_removexattr, |
10079 | .permission = btrfs_permission, | 10079 | .permission = btrfs_permission, |
@@ -10087,7 +10087,7 @@ static const struct inode_operations btrfs_special_inode_operations = { | |||
10087 | .setattr = btrfs_setattr, | 10087 | .setattr = btrfs_setattr, |
10088 | .permission = btrfs_permission, | 10088 | .permission = btrfs_permission, |
10089 | .setxattr = btrfs_setxattr, | 10089 | .setxattr = btrfs_setxattr, |
10090 | .getxattr = btrfs_getxattr, | 10090 | .getxattr = generic_getxattr, |
10091 | .listxattr = btrfs_listxattr, | 10091 | .listxattr = btrfs_listxattr, |
10092 | .removexattr = btrfs_removexattr, | 10092 | .removexattr = btrfs_removexattr, |
10093 | .get_acl = btrfs_get_acl, | 10093 | .get_acl = btrfs_get_acl, |
@@ -10101,7 +10101,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { | |||
10101 | .setattr = btrfs_setattr, | 10101 | .setattr = btrfs_setattr, |
10102 | .permission = btrfs_permission, | 10102 | .permission = btrfs_permission, |
10103 | .setxattr = btrfs_setxattr, | 10103 | .setxattr = btrfs_setxattr, |
10104 | .getxattr = btrfs_getxattr, | 10104 | .getxattr = generic_getxattr, |
10105 | .listxattr = btrfs_listxattr, | 10105 | .listxattr = btrfs_listxattr, |
10106 | .removexattr = btrfs_removexattr, | 10106 | .removexattr = btrfs_removexattr, |
10107 | .update_time = btrfs_update_time, | 10107 | .update_time = btrfs_update_time, |
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 1fcd7b6e7564..7cbef1a14fe1 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -351,137 +351,89 @@ err: | |||
351 | return ret; | 351 | return ret; |
352 | } | 352 | } |
353 | 353 | ||
354 | /* | 354 | static int btrfs_xattr_handler_get(const struct xattr_handler *handler, |
355 | * List of handlers for synthetic system.* attributes. All real ondisk | 355 | struct dentry *dentry, const char *name, |
356 | * attributes are handled directly. | 356 | void *buffer, size_t size) |
357 | */ | ||
358 | const struct xattr_handler *btrfs_xattr_handlers[] = { | ||
359 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL | ||
360 | &posix_acl_access_xattr_handler, | ||
361 | &posix_acl_default_xattr_handler, | ||
362 | #endif | ||
363 | NULL, | ||
364 | }; | ||
365 | |||
366 | /* | ||
367 | * Check if the attribute is in a supported namespace. | ||
368 | * | ||
369 | * This is applied after the check for the synthetic attributes in the system | ||
370 | * namespace. | ||
371 | */ | ||
372 | static int btrfs_is_valid_xattr(const char *name) | ||
373 | { | 357 | { |
374 | int len = strlen(name); | 358 | struct inode *inode = d_inode(dentry); |
375 | int prefixlen = 0; | ||
376 | |||
377 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | ||
378 | XATTR_SECURITY_PREFIX_LEN)) | ||
379 | prefixlen = XATTR_SECURITY_PREFIX_LEN; | ||
380 | else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
381 | prefixlen = XATTR_SYSTEM_PREFIX_LEN; | ||
382 | else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) | ||
383 | prefixlen = XATTR_TRUSTED_PREFIX_LEN; | ||
384 | else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) | ||
385 | prefixlen = XATTR_USER_PREFIX_LEN; | ||
386 | else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) | ||
387 | prefixlen = XATTR_BTRFS_PREFIX_LEN; | ||
388 | else | ||
389 | return -EOPNOTSUPP; | ||
390 | |||
391 | /* | ||
392 | * The name cannot consist of just prefix | ||
393 | */ | ||
394 | if (len <= prefixlen) | ||
395 | return -EINVAL; | ||
396 | 359 | ||
397 | return 0; | 360 | name = xattr_full_name(handler, name); |
361 | return __btrfs_getxattr(inode, name, buffer, size); | ||
398 | } | 362 | } |
399 | 363 | ||
400 | ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, | 364 | static int btrfs_xattr_handler_set(const struct xattr_handler *handler, |
401 | void *buffer, size_t size) | 365 | struct dentry *dentry, const char *name, |
366 | const void *buffer, size_t size, | ||
367 | int flags) | ||
402 | { | 368 | { |
403 | int ret; | 369 | struct inode *inode = d_inode(dentry); |
404 | 370 | ||
405 | /* | 371 | name = xattr_full_name(handler, name); |
406 | * If this is a request for a synthetic attribute in the system.* | 372 | return __btrfs_setxattr(NULL, inode, name, buffer, size, flags); |
407 | * namespace use the generic infrastructure to resolve a handler | 373 | } |
408 | * for it via sb->s_xattr. | ||
409 | */ | ||
410 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
411 | return generic_getxattr(dentry, name, buffer, size); | ||
412 | 374 | ||
413 | ret = btrfs_is_valid_xattr(name); | 375 | static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler, |
414 | if (ret) | 376 | struct dentry *dentry, |
415 | return ret; | 377 | const char *name, const void *value, |
416 | return __btrfs_getxattr(d_inode(dentry), name, buffer, size); | 378 | size_t size, int flags) |
379 | { | ||
380 | name = xattr_full_name(handler, name); | ||
381 | return btrfs_set_prop(d_inode(dentry), name, value, size, flags); | ||
417 | } | 382 | } |
418 | 383 | ||
384 | static const struct xattr_handler btrfs_security_xattr_handler = { | ||
385 | .prefix = XATTR_SECURITY_PREFIX, | ||
386 | .get = btrfs_xattr_handler_get, | ||
387 | .set = btrfs_xattr_handler_set, | ||
388 | }; | ||
389 | |||
390 | static const struct xattr_handler btrfs_trusted_xattr_handler = { | ||
391 | .prefix = XATTR_TRUSTED_PREFIX, | ||
392 | .get = btrfs_xattr_handler_get, | ||
393 | .set = btrfs_xattr_handler_set, | ||
394 | }; | ||
395 | |||
396 | static const struct xattr_handler btrfs_user_xattr_handler = { | ||
397 | .prefix = XATTR_USER_PREFIX, | ||
398 | .get = btrfs_xattr_handler_get, | ||
399 | .set = btrfs_xattr_handler_set, | ||
400 | }; | ||
401 | |||
402 | static const struct xattr_handler btrfs_btrfs_xattr_handler = { | ||
403 | .prefix = XATTR_BTRFS_PREFIX, | ||
404 | .get = btrfs_xattr_handler_get, | ||
405 | .set = btrfs_xattr_handler_set_prop, | ||
406 | }; | ||
407 | |||
408 | const struct xattr_handler *btrfs_xattr_handlers[] = { | ||
409 | &btrfs_security_xattr_handler, | ||
410 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL | ||
411 | &posix_acl_access_xattr_handler, | ||
412 | &posix_acl_default_xattr_handler, | ||
413 | #endif | ||
414 | &btrfs_trusted_xattr_handler, | ||
415 | &btrfs_user_xattr_handler, | ||
416 | &btrfs_btrfs_xattr_handler, | ||
417 | NULL, | ||
418 | }; | ||
419 | |||
419 | int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, | 420 | int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, |
420 | size_t size, int flags) | 421 | size_t size, int flags) |
421 | { | 422 | { |
422 | struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; | 423 | struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; |
423 | int ret; | ||
424 | 424 | ||
425 | /* | ||
426 | * The permission on security.* and system.* is not checked | ||
427 | * in permission(). | ||
428 | */ | ||
429 | if (btrfs_root_readonly(root)) | 425 | if (btrfs_root_readonly(root)) |
430 | return -EROFS; | 426 | return -EROFS; |
431 | 427 | return generic_setxattr(dentry, name, value, size, flags); | |
432 | /* | ||
433 | * If this is a request for a synthetic attribute in the system.* | ||
434 | * namespace use the generic infrastructure to resolve a handler | ||
435 | * for it via sb->s_xattr. | ||
436 | */ | ||
437 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
438 | return generic_setxattr(dentry, name, value, size, flags); | ||
439 | |||
440 | ret = btrfs_is_valid_xattr(name); | ||
441 | if (ret) | ||
442 | return ret; | ||
443 | |||
444 | if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) | ||
445 | return btrfs_set_prop(d_inode(dentry), name, | ||
446 | value, size, flags); | ||
447 | |||
448 | if (size == 0) | ||
449 | value = ""; /* empty EA, do not remove */ | ||
450 | |||
451 | return __btrfs_setxattr(NULL, d_inode(dentry), name, value, size, | ||
452 | flags); | ||
453 | } | 428 | } |
454 | 429 | ||
455 | int btrfs_removexattr(struct dentry *dentry, const char *name) | 430 | int btrfs_removexattr(struct dentry *dentry, const char *name) |
456 | { | 431 | { |
457 | struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; | 432 | struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root; |
458 | int ret; | ||
459 | 433 | ||
460 | /* | ||
461 | * The permission on security.* and system.* is not checked | ||
462 | * in permission(). | ||
463 | */ | ||
464 | if (btrfs_root_readonly(root)) | 434 | if (btrfs_root_readonly(root)) |
465 | return -EROFS; | 435 | return -EROFS; |
466 | 436 | return generic_removexattr(dentry, name); | |
467 | /* | ||
468 | * If this is a request for a synthetic attribute in the system.* | ||
469 | * namespace use the generic infrastructure to resolve a handler | ||
470 | * for it via sb->s_xattr. | ||
471 | */ | ||
472 | if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) | ||
473 | return generic_removexattr(dentry, name); | ||
474 | |||
475 | ret = btrfs_is_valid_xattr(name); | ||
476 | if (ret) | ||
477 | return ret; | ||
478 | |||
479 | if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN)) | ||
480 | return btrfs_set_prop(d_inode(dentry), name, | ||
481 | NULL, 0, XATTR_REPLACE); | ||
482 | |||
483 | return __btrfs_setxattr(NULL, d_inode(dentry), name, NULL, 0, | ||
484 | XATTR_REPLACE); | ||
485 | } | 437 | } |
486 | 438 | ||
487 | static int btrfs_initxattrs(struct inode *inode, | 439 | static int btrfs_initxattrs(struct inode *inode, |
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h index 5049608d1388..96807b3d22f5 100644 --- a/fs/btrfs/xattr.h +++ b/fs/btrfs/xattr.h | |||
@@ -28,8 +28,6 @@ extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name, | |||
28 | extern int __btrfs_setxattr(struct btrfs_trans_handle *trans, | 28 | extern int __btrfs_setxattr(struct btrfs_trans_handle *trans, |
29 | struct inode *inode, const char *name, | 29 | struct inode *inode, const char *name, |
30 | const void *value, size_t size, int flags); | 30 | const void *value, size_t size, int flags); |
31 | extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, | ||
32 | void *buffer, size_t size); | ||
33 | extern int btrfs_setxattr(struct dentry *dentry, const char *name, | 31 | extern int btrfs_setxattr(struct dentry *dentry, const char *name, |
34 | const void *value, size_t size, int flags); | 32 | const void *value, size_t size, int flags); |
35 | extern int btrfs_removexattr(struct dentry *dentry, const char *name); | 33 | extern int btrfs_removexattr(struct dentry *dentry, const char *name); |
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c index 8f84646f10e9..f19708487e2f 100644 --- a/fs/ceph/acl.c +++ b/fs/ceph/acl.c | |||
@@ -49,10 +49,10 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type) | |||
49 | 49 | ||
50 | switch (type) { | 50 | switch (type) { |
51 | case ACL_TYPE_ACCESS: | 51 | case ACL_TYPE_ACCESS: |
52 | name = POSIX_ACL_XATTR_ACCESS; | 52 | name = XATTR_NAME_POSIX_ACL_ACCESS; |
53 | break; | 53 | break; |
54 | case ACL_TYPE_DEFAULT: | 54 | case ACL_TYPE_DEFAULT: |
55 | name = POSIX_ACL_XATTR_DEFAULT; | 55 | name = XATTR_NAME_POSIX_ACL_DEFAULT; |
56 | break; | 56 | break; |
57 | default: | 57 | default: |
58 | BUG(); | 58 | BUG(); |
@@ -92,7 +92,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
92 | 92 | ||
93 | switch (type) { | 93 | switch (type) { |
94 | case ACL_TYPE_ACCESS: | 94 | case ACL_TYPE_ACCESS: |
95 | name = POSIX_ACL_XATTR_ACCESS; | 95 | name = XATTR_NAME_POSIX_ACL_ACCESS; |
96 | if (acl) { | 96 | if (acl) { |
97 | ret = posix_acl_equiv_mode(acl, &new_mode); | 97 | ret = posix_acl_equiv_mode(acl, &new_mode); |
98 | if (ret < 0) | 98 | if (ret < 0) |
@@ -106,7 +106,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
106 | ret = acl ? -EINVAL : 0; | 106 | ret = acl ? -EINVAL : 0; |
107 | goto out; | 107 | goto out; |
108 | } | 108 | } |
109 | name = POSIX_ACL_XATTR_DEFAULT; | 109 | name = XATTR_NAME_POSIX_ACL_DEFAULT; |
110 | break; | 110 | break; |
111 | default: | 111 | default: |
112 | ret = -EINVAL; | 112 | ret = -EINVAL; |
@@ -202,11 +202,11 @@ int ceph_pre_init_acls(struct inode *dir, umode_t *mode, | |||
202 | ceph_pagelist_encode_32(pagelist, acl && default_acl ? 2 : 1); | 202 | ceph_pagelist_encode_32(pagelist, acl && default_acl ? 2 : 1); |
203 | 203 | ||
204 | if (acl) { | 204 | if (acl) { |
205 | size_t len = strlen(POSIX_ACL_XATTR_ACCESS); | 205 | size_t len = strlen(XATTR_NAME_POSIX_ACL_ACCESS); |
206 | err = ceph_pagelist_reserve(pagelist, len + val_size1 + 8); | 206 | err = ceph_pagelist_reserve(pagelist, len + val_size1 + 8); |
207 | if (err) | 207 | if (err) |
208 | goto out_err; | 208 | goto out_err; |
209 | ceph_pagelist_encode_string(pagelist, POSIX_ACL_XATTR_ACCESS, | 209 | ceph_pagelist_encode_string(pagelist, XATTR_NAME_POSIX_ACL_ACCESS, |
210 | len); | 210 | len); |
211 | err = posix_acl_to_xattr(&init_user_ns, acl, | 211 | err = posix_acl_to_xattr(&init_user_ns, acl, |
212 | tmp_buf, val_size1); | 212 | tmp_buf, val_size1); |
@@ -216,12 +216,12 @@ int ceph_pre_init_acls(struct inode *dir, umode_t *mode, | |||
216 | ceph_pagelist_append(pagelist, tmp_buf, val_size1); | 216 | ceph_pagelist_append(pagelist, tmp_buf, val_size1); |
217 | } | 217 | } |
218 | if (default_acl) { | 218 | if (default_acl) { |
219 | size_t len = strlen(POSIX_ACL_XATTR_DEFAULT); | 219 | size_t len = strlen(XATTR_NAME_POSIX_ACL_DEFAULT); |
220 | err = ceph_pagelist_reserve(pagelist, len + val_size2 + 8); | 220 | err = ceph_pagelist_reserve(pagelist, len + val_size2 + 8); |
221 | if (err) | 221 | if (err) |
222 | goto out_err; | 222 | goto out_err; |
223 | err = ceph_pagelist_encode_string(pagelist, | 223 | err = ceph_pagelist_encode_string(pagelist, |
224 | POSIX_ACL_XATTR_DEFAULT, len); | 224 | XATTR_NAME_POSIX_ACL_DEFAULT, len); |
225 | err = posix_acl_to_xattr(&init_user_ns, default_acl, | 225 | err = posix_acl_to_xattr(&init_user_ns, default_acl, |
226 | tmp_buf, val_size2); | 226 | tmp_buf, val_size2); |
227 | if (err < 0) | 227 | if (err < 0) |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index ff9e1f8b16a4..f5dc2f0df4ad 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -190,8 +190,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
190 | #endif /* CONFIG_CIFS_ACL */ | 190 | #endif /* CONFIG_CIFS_ACL */ |
191 | } else { | 191 | } else { |
192 | int temp; | 192 | int temp; |
193 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 193 | temp = strncmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS, |
194 | strlen(POSIX_ACL_XATTR_ACCESS)); | 194 | strlen(XATTR_NAME_POSIX_ACL_ACCESS)); |
195 | if (temp == 0) { | 195 | if (temp == 0) { |
196 | #ifdef CONFIG_CIFS_POSIX | 196 | #ifdef CONFIG_CIFS_POSIX |
197 | if (sb->s_flags & MS_POSIXACL) | 197 | if (sb->s_flags & MS_POSIXACL) |
@@ -203,8 +203,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
203 | #else | 203 | #else |
204 | cifs_dbg(FYI, "set POSIX ACL not supported\n"); | 204 | cifs_dbg(FYI, "set POSIX ACL not supported\n"); |
205 | #endif | 205 | #endif |
206 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, | 206 | } else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT, |
207 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | 207 | strlen(XATTR_NAME_POSIX_ACL_DEFAULT)) == 0) { |
208 | #ifdef CONFIG_CIFS_POSIX | 208 | #ifdef CONFIG_CIFS_POSIX |
209 | if (sb->s_flags & MS_POSIXACL) | 209 | if (sb->s_flags & MS_POSIXACL) |
210 | rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, | 210 | rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, |
@@ -292,8 +292,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
292 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, | 292 | rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, |
293 | full_path, ea_name, ea_value, buf_size, | 293 | full_path, ea_name, ea_value, buf_size, |
294 | cifs_sb->local_nls, cifs_remap(cifs_sb)); | 294 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
295 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 295 | } else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS, |
296 | strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { | 296 | strlen(XATTR_NAME_POSIX_ACL_ACCESS)) == 0) { |
297 | #ifdef CONFIG_CIFS_POSIX | 297 | #ifdef CONFIG_CIFS_POSIX |
298 | if (sb->s_flags & MS_POSIXACL) | 298 | if (sb->s_flags & MS_POSIXACL) |
299 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, | 299 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, |
@@ -303,8 +303,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
303 | #else | 303 | #else |
304 | cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); | 304 | cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); |
305 | #endif /* CONFIG_CIFS_POSIX */ | 305 | #endif /* CONFIG_CIFS_POSIX */ |
306 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, | 306 | } else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT, |
307 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | 307 | strlen(XATTR_NAME_POSIX_ACL_DEFAULT)) == 0) { |
308 | #ifdef CONFIG_CIFS_POSIX | 308 | #ifdef CONFIG_CIFS_POSIX |
309 | if (sb->s_flags & MS_POSIXACL) | 309 | if (sb->s_flags & MS_POSIXACL) |
310 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, | 310 | rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, |
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index fa70848afa8f..cd95d14f9cc2 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c | |||
@@ -292,16 +292,21 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list", | |||
292 | const struct xattr_handler *handler = | 292 | const struct xattr_handler *handler = |
293 | ext2_xattr_handler(entry->e_name_index); | 293 | ext2_xattr_handler(entry->e_name_index); |
294 | 294 | ||
295 | if (handler) { | 295 | if (handler && (!handler->list || handler->list(dentry))) { |
296 | size_t size = handler->list(handler, dentry, buffer, | 296 | const char *prefix = handler->prefix ?: handler->name; |
297 | rest, entry->e_name, | 297 | size_t prefix_len = strlen(prefix); |
298 | entry->e_name_len); | 298 | size_t size = prefix_len + entry->e_name_len + 1; |
299 | |||
299 | if (buffer) { | 300 | if (buffer) { |
300 | if (size > rest) { | 301 | if (size > rest) { |
301 | error = -ERANGE; | 302 | error = -ERANGE; |
302 | goto cleanup; | 303 | goto cleanup; |
303 | } | 304 | } |
304 | buffer += size; | 305 | memcpy(buffer, prefix, prefix_len); |
306 | buffer += prefix_len; | ||
307 | memcpy(buffer, entry->e_name, entry->e_name_len); | ||
308 | buffer += entry->e_name_len; | ||
309 | *buffer++ = 0; | ||
305 | } | 310 | } |
306 | rest -= size; | 311 | rest -= size; |
307 | } | 312 | } |
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index dfb08750370d..ba97f243b050 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c | |||
@@ -7,29 +7,11 @@ | |||
7 | #include <linux/security.h> | 7 | #include <linux/security.h> |
8 | #include "xattr.h" | 8 | #include "xattr.h" |
9 | 9 | ||
10 | static size_t | ||
11 | ext2_xattr_security_list(const struct xattr_handler *handler, | ||
12 | struct dentry *dentry, char *list, size_t list_size, | ||
13 | const char *name, size_t name_len) | ||
14 | { | ||
15 | const int prefix_len = XATTR_SECURITY_PREFIX_LEN; | ||
16 | const size_t total_len = prefix_len + name_len + 1; | ||
17 | |||
18 | if (list && total_len <= list_size) { | ||
19 | memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); | ||
20 | memcpy(list+prefix_len, name, name_len); | ||
21 | list[prefix_len + name_len] = '\0'; | ||
22 | } | ||
23 | return total_len; | ||
24 | } | ||
25 | |||
26 | static int | 10 | static int |
27 | ext2_xattr_security_get(const struct xattr_handler *handler, | 11 | ext2_xattr_security_get(const struct xattr_handler *handler, |
28 | struct dentry *dentry, const char *name, | 12 | struct dentry *dentry, const char *name, |
29 | void *buffer, size_t size) | 13 | void *buffer, size_t size) |
30 | { | 14 | { |
31 | if (strcmp(name, "") == 0) | ||
32 | return -EINVAL; | ||
33 | return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, | 15 | return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, |
34 | buffer, size); | 16 | buffer, size); |
35 | } | 17 | } |
@@ -39,8 +21,6 @@ ext2_xattr_security_set(const struct xattr_handler *handler, | |||
39 | struct dentry *dentry, const char *name, | 21 | struct dentry *dentry, const char *name, |
40 | const void *value, size_t size, int flags) | 22 | const void *value, size_t size, int flags) |
41 | { | 23 | { |
42 | if (strcmp(name, "") == 0) | ||
43 | return -EINVAL; | ||
44 | return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, | 24 | return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name, |
45 | value, size, flags); | 25 | value, size, flags); |
46 | } | 26 | } |
@@ -71,7 +51,6 @@ ext2_init_security(struct inode *inode, struct inode *dir, | |||
71 | 51 | ||
72 | const struct xattr_handler ext2_xattr_security_handler = { | 52 | const struct xattr_handler ext2_xattr_security_handler = { |
73 | .prefix = XATTR_SECURITY_PREFIX, | 53 | .prefix = XATTR_SECURITY_PREFIX, |
74 | .list = ext2_xattr_security_list, | ||
75 | .get = ext2_xattr_security_get, | 54 | .get = ext2_xattr_security_get, |
76 | .set = ext2_xattr_security_set, | 55 | .set = ext2_xattr_security_set, |
77 | }; | 56 | }; |
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c index 3150dd3a7859..2c94d1930626 100644 --- a/fs/ext2/xattr_trusted.c +++ b/fs/ext2/xattr_trusted.c | |||
@@ -8,23 +8,10 @@ | |||
8 | #include "ext2.h" | 8 | #include "ext2.h" |
9 | #include "xattr.h" | 9 | #include "xattr.h" |
10 | 10 | ||
11 | static size_t | 11 | static bool |
12 | ext2_xattr_trusted_list(const struct xattr_handler *handler, | 12 | ext2_xattr_trusted_list(struct dentry *dentry) |
13 | struct dentry *dentry, char *list, size_t list_size, | ||
14 | const char *name, size_t name_len) | ||
15 | { | 13 | { |
16 | const int prefix_len = XATTR_TRUSTED_PREFIX_LEN; | 14 | return capable(CAP_SYS_ADMIN); |
17 | const size_t total_len = prefix_len + name_len + 1; | ||
18 | |||
19 | if (!capable(CAP_SYS_ADMIN)) | ||
20 | return 0; | ||
21 | |||
22 | if (list && total_len <= list_size) { | ||
23 | memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); | ||
24 | memcpy(list+prefix_len, name, name_len); | ||
25 | list[prefix_len + name_len] = '\0'; | ||
26 | } | ||
27 | return total_len; | ||
28 | } | 15 | } |
29 | 16 | ||
30 | static int | 17 | static int |
@@ -32,8 +19,6 @@ ext2_xattr_trusted_get(const struct xattr_handler *handler, | |||
32 | struct dentry *dentry, const char *name, | 19 | struct dentry *dentry, const char *name, |
33 | void *buffer, size_t size) | 20 | void *buffer, size_t size) |
34 | { | 21 | { |
35 | if (strcmp(name, "") == 0) | ||
36 | return -EINVAL; | ||
37 | return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, | 22 | return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, |
38 | buffer, size); | 23 | buffer, size); |
39 | } | 24 | } |
@@ -43,8 +28,6 @@ ext2_xattr_trusted_set(const struct xattr_handler *handler, | |||
43 | struct dentry *dentry, const char *name, | 28 | struct dentry *dentry, const char *name, |
44 | const void *value, size_t size, int flags) | 29 | const void *value, size_t size, int flags) |
45 | { | 30 | { |
46 | if (strcmp(name, "") == 0) | ||
47 | return -EINVAL; | ||
48 | return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, | 31 | return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name, |
49 | value, size, flags); | 32 | value, size, flags); |
50 | } | 33 | } |
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c index 339a49bbb8ef..72a2a96d677f 100644 --- a/fs/ext2/xattr_user.c +++ b/fs/ext2/xattr_user.c | |||
@@ -10,23 +10,10 @@ | |||
10 | #include "ext2.h" | 10 | #include "ext2.h" |
11 | #include "xattr.h" | 11 | #include "xattr.h" |
12 | 12 | ||
13 | static size_t | 13 | static bool |
14 | ext2_xattr_user_list(const struct xattr_handler *handler, | 14 | ext2_xattr_user_list(struct dentry *dentry) |
15 | struct dentry *dentry, char *list, size_t list_size, | ||
16 | const char *name, size_t name_len) | ||
17 | { | 15 | { |
18 | const size_t prefix_len = XATTR_USER_PREFIX_LEN; | 16 | return test_opt(dentry->d_sb, XATTR_USER); |
19 | const size_t total_len = prefix_len + name_len + 1; | ||
20 | |||
21 | if (!test_opt(dentry->d_sb, XATTR_USER)) | ||
22 | return 0; | ||
23 | |||
24 | if (list && total_len <= list_size) { | ||
25 | memcpy(list, XATTR_USER_PREFIX, prefix_len); | ||
26 | memcpy(list+prefix_len, name, name_len); | ||
27 | list[prefix_len + name_len] = '\0'; | ||
28 | } | ||
29 | return total_len; | ||
30 | } | 17 | } |
31 | 18 | ||
32 | static int | 19 | static int |
@@ -34,8 +21,6 @@ ext2_xattr_user_get(const struct xattr_handler *handler, | |||
34 | struct dentry *dentry, const char *name, | 21 | struct dentry *dentry, const char *name, |
35 | void *buffer, size_t size) | 22 | void *buffer, size_t size) |
36 | { | 23 | { |
37 | if (strcmp(name, "") == 0) | ||
38 | return -EINVAL; | ||
39 | if (!test_opt(dentry->d_sb, XATTR_USER)) | 24 | if (!test_opt(dentry->d_sb, XATTR_USER)) |
40 | return -EOPNOTSUPP; | 25 | return -EOPNOTSUPP; |
41 | return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER, | 26 | return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER, |
@@ -47,8 +32,6 @@ ext2_xattr_user_set(const struct xattr_handler *handler, | |||
47 | struct dentry *dentry, const char *name, | 32 | struct dentry *dentry, const char *name, |
48 | const void *value, size_t size, int flags) | 33 | const void *value, size_t size, int flags) |
49 | { | 34 | { |
50 | if (strcmp(name, "") == 0) | ||
51 | return -EINVAL; | ||
52 | if (!test_opt(dentry->d_sb, XATTR_USER)) | 35 | if (!test_opt(dentry->d_sb, XATTR_USER)) |
53 | return -EOPNOTSUPP; | 36 | return -EOPNOTSUPP; |
54 | 37 | ||
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 6b6b3e751f8c..e9b9afdd1d96 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -404,19 +404,24 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry, | |||
404 | const struct xattr_handler *handler = | 404 | const struct xattr_handler *handler = |
405 | ext4_xattr_handler(entry->e_name_index); | 405 | ext4_xattr_handler(entry->e_name_index); |
406 | 406 | ||
407 | if (handler) { | 407 | if (handler && (!handler->list || handler->list(dentry))) { |
408 | size_t size = handler->list(handler, dentry, buffer, | 408 | const char *prefix = handler->prefix ?: handler->name; |
409 | rest, entry->e_name, | 409 | size_t prefix_len = strlen(prefix); |
410 | entry->e_name_len); | 410 | size_t size = prefix_len + entry->e_name_len + 1; |
411 | |||
411 | if (buffer) { | 412 | if (buffer) { |
412 | if (size > rest) | 413 | if (size > rest) |
413 | return -ERANGE; | 414 | return -ERANGE; |
414 | buffer += size; | 415 | memcpy(buffer, prefix, prefix_len); |
416 | buffer += prefix_len; | ||
417 | memcpy(buffer, entry->e_name, entry->e_name_len); | ||
418 | buffer += entry->e_name_len; | ||
419 | *buffer++ = 0; | ||
415 | } | 420 | } |
416 | rest -= size; | 421 | rest -= size; |
417 | } | 422 | } |
418 | } | 423 | } |
419 | return buffer_size - rest; | 424 | return buffer_size - rest; /* total size */ |
420 | } | 425 | } |
421 | 426 | ||
422 | static int | 427 | static int |
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index 36f4c1a84c21..3e81bdca071a 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c | |||
@@ -11,30 +11,11 @@ | |||
11 | #include "ext4.h" | 11 | #include "ext4.h" |
12 | #include "xattr.h" | 12 | #include "xattr.h" |
13 | 13 | ||
14 | static size_t | ||
15 | ext4_xattr_security_list(const struct xattr_handler *handler, | ||
16 | struct dentry *dentry, char *list, size_t list_size, | ||
17 | const char *name, size_t name_len) | ||
18 | { | ||
19 | const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1; | ||
20 | const size_t total_len = prefix_len + name_len + 1; | ||
21 | |||
22 | |||
23 | if (list && total_len <= list_size) { | ||
24 | memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); | ||
25 | memcpy(list+prefix_len, name, name_len); | ||
26 | list[prefix_len + name_len] = '\0'; | ||
27 | } | ||
28 | return total_len; | ||
29 | } | ||
30 | |||
31 | static int | 14 | static int |
32 | ext4_xattr_security_get(const struct xattr_handler *handler, | 15 | ext4_xattr_security_get(const struct xattr_handler *handler, |
33 | struct dentry *dentry, const char *name, | 16 | struct dentry *dentry, const char *name, |
34 | void *buffer, size_t size) | 17 | void *buffer, size_t size) |
35 | { | 18 | { |
36 | if (strcmp(name, "") == 0) | ||
37 | return -EINVAL; | ||
38 | return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY, | 19 | return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY, |
39 | name, buffer, size); | 20 | name, buffer, size); |
40 | } | 21 | } |
@@ -44,8 +25,6 @@ ext4_xattr_security_set(const struct xattr_handler *handler, | |||
44 | struct dentry *dentry, const char *name, | 25 | struct dentry *dentry, const char *name, |
45 | const void *value, size_t size, int flags) | 26 | const void *value, size_t size, int flags) |
46 | { | 27 | { |
47 | if (strcmp(name, "") == 0) | ||
48 | return -EINVAL; | ||
49 | return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY, | 28 | return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY, |
50 | name, value, size, flags); | 29 | name, value, size, flags); |
51 | } | 30 | } |
@@ -79,7 +58,6 @@ ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir, | |||
79 | 58 | ||
80 | const struct xattr_handler ext4_xattr_security_handler = { | 59 | const struct xattr_handler ext4_xattr_security_handler = { |
81 | .prefix = XATTR_SECURITY_PREFIX, | 60 | .prefix = XATTR_SECURITY_PREFIX, |
82 | .list = ext4_xattr_security_list, | ||
83 | .get = ext4_xattr_security_get, | 61 | .get = ext4_xattr_security_get, |
84 | .set = ext4_xattr_security_set, | 62 | .set = ext4_xattr_security_set, |
85 | }; | 63 | }; |
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c index 488089053342..2a3c6f9b8cb8 100644 --- a/fs/ext4/xattr_trusted.c +++ b/fs/ext4/xattr_trusted.c | |||
@@ -12,23 +12,10 @@ | |||
12 | #include "ext4.h" | 12 | #include "ext4.h" |
13 | #include "xattr.h" | 13 | #include "xattr.h" |
14 | 14 | ||
15 | static size_t | 15 | static bool |
16 | ext4_xattr_trusted_list(const struct xattr_handler *handler, | 16 | ext4_xattr_trusted_list(struct dentry *dentry) |
17 | struct dentry *dentry, char *list, size_t list_size, | ||
18 | const char *name, size_t name_len) | ||
19 | { | 17 | { |
20 | const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; | 18 | return capable(CAP_SYS_ADMIN); |
21 | const size_t total_len = prefix_len + name_len + 1; | ||
22 | |||
23 | if (!capable(CAP_SYS_ADMIN)) | ||
24 | return 0; | ||
25 | |||
26 | if (list && total_len <= list_size) { | ||
27 | memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); | ||
28 | memcpy(list+prefix_len, name, name_len); | ||
29 | list[prefix_len + name_len] = '\0'; | ||
30 | } | ||
31 | return total_len; | ||
32 | } | 19 | } |
33 | 20 | ||
34 | static int | 21 | static int |
@@ -36,8 +23,6 @@ ext4_xattr_trusted_get(const struct xattr_handler *handler, | |||
36 | struct dentry *dentry, const char *name, void *buffer, | 23 | struct dentry *dentry, const char *name, void *buffer, |
37 | size_t size) | 24 | size_t size) |
38 | { | 25 | { |
39 | if (strcmp(name, "") == 0) | ||
40 | return -EINVAL; | ||
41 | return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED, | 26 | return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED, |
42 | name, buffer, size); | 27 | name, buffer, size); |
43 | } | 28 | } |
@@ -47,8 +32,6 @@ ext4_xattr_trusted_set(const struct xattr_handler *handler, | |||
47 | struct dentry *dentry, const char *name, | 32 | struct dentry *dentry, const char *name, |
48 | const void *value, size_t size, int flags) | 33 | const void *value, size_t size, int flags) |
49 | { | 34 | { |
50 | if (strcmp(name, "") == 0) | ||
51 | return -EINVAL; | ||
52 | return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED, | 35 | return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED, |
53 | name, value, size, flags); | 36 | name, value, size, flags); |
54 | } | 37 | } |
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c index d2dec3364062..d152f431e432 100644 --- a/fs/ext4/xattr_user.c +++ b/fs/ext4/xattr_user.c | |||
@@ -11,23 +11,10 @@ | |||
11 | #include "ext4.h" | 11 | #include "ext4.h" |
12 | #include "xattr.h" | 12 | #include "xattr.h" |
13 | 13 | ||
14 | static size_t | 14 | static bool |
15 | ext4_xattr_user_list(const struct xattr_handler *handler, | 15 | ext4_xattr_user_list(struct dentry *dentry) |
16 | struct dentry *dentry, char *list, size_t list_size, | ||
17 | const char *name, size_t name_len) | ||
18 | { | 16 | { |
19 | const size_t prefix_len = XATTR_USER_PREFIX_LEN; | 17 | return test_opt(dentry->d_sb, XATTR_USER); |
20 | const size_t total_len = prefix_len + name_len + 1; | ||
21 | |||
22 | if (!test_opt(dentry->d_sb, XATTR_USER)) | ||
23 | return 0; | ||
24 | |||
25 | if (list && total_len <= list_size) { | ||
26 | memcpy(list, XATTR_USER_PREFIX, prefix_len); | ||
27 | memcpy(list+prefix_len, name, name_len); | ||
28 | list[prefix_len + name_len] = '\0'; | ||
29 | } | ||
30 | return total_len; | ||
31 | } | 18 | } |
32 | 19 | ||
33 | static int | 20 | static int |
@@ -35,8 +22,6 @@ ext4_xattr_user_get(const struct xattr_handler *handler, | |||
35 | struct dentry *dentry, const char *name, | 22 | struct dentry *dentry, const char *name, |
36 | void *buffer, size_t size) | 23 | void *buffer, size_t size) |
37 | { | 24 | { |
38 | if (strcmp(name, "") == 0) | ||
39 | return -EINVAL; | ||
40 | if (!test_opt(dentry->d_sb, XATTR_USER)) | 25 | if (!test_opt(dentry->d_sb, XATTR_USER)) |
41 | return -EOPNOTSUPP; | 26 | return -EOPNOTSUPP; |
42 | return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER, | 27 | return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER, |
@@ -48,8 +33,6 @@ ext4_xattr_user_set(const struct xattr_handler *handler, | |||
48 | struct dentry *dentry, const char *name, | 33 | struct dentry *dentry, const char *name, |
49 | const void *value, size_t size, int flags) | 34 | const void *value, size_t size, int flags) |
50 | { | 35 | { |
51 | if (strcmp(name, "") == 0) | ||
52 | return -EINVAL; | ||
53 | if (!test_opt(dentry->d_sb, XATTR_USER)) | 36 | if (!test_opt(dentry->d_sb, XATTR_USER)) |
54 | return -EOPNOTSUPP; | 37 | return -EOPNOTSUPP; |
55 | return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER, | 38 | return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER, |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 862368a32e53..036952a945fa 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -25,38 +25,6 @@ | |||
25 | #include "f2fs.h" | 25 | #include "f2fs.h" |
26 | #include "xattr.h" | 26 | #include "xattr.h" |
27 | 27 | ||
28 | static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler, | ||
29 | struct dentry *dentry, char *list, size_t list_size, | ||
30 | const char *name, size_t len) | ||
31 | { | ||
32 | struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); | ||
33 | int total_len, prefix_len; | ||
34 | |||
35 | switch (handler->flags) { | ||
36 | case F2FS_XATTR_INDEX_USER: | ||
37 | if (!test_opt(sbi, XATTR_USER)) | ||
38 | return -EOPNOTSUPP; | ||
39 | break; | ||
40 | case F2FS_XATTR_INDEX_TRUSTED: | ||
41 | if (!capable(CAP_SYS_ADMIN)) | ||
42 | return -EPERM; | ||
43 | break; | ||
44 | case F2FS_XATTR_INDEX_SECURITY: | ||
45 | break; | ||
46 | default: | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | |||
50 | prefix_len = strlen(handler->prefix); | ||
51 | total_len = prefix_len + len + 1; | ||
52 | if (list && total_len <= list_size) { | ||
53 | memcpy(list, handler->prefix, prefix_len); | ||
54 | memcpy(list + prefix_len, name, len); | ||
55 | list[prefix_len + len] = '\0'; | ||
56 | } | ||
57 | return total_len; | ||
58 | } | ||
59 | |||
60 | static int f2fs_xattr_generic_get(const struct xattr_handler *handler, | 28 | static int f2fs_xattr_generic_get(const struct xattr_handler *handler, |
61 | struct dentry *dentry, const char *name, void *buffer, | 29 | struct dentry *dentry, const char *name, void *buffer, |
62 | size_t size) | 30 | size_t size) |
@@ -77,8 +45,6 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler, | |||
77 | default: | 45 | default: |
78 | return -EINVAL; | 46 | return -EINVAL; |
79 | } | 47 | } |
80 | if (strcmp(name, "") == 0) | ||
81 | return -EINVAL; | ||
82 | return f2fs_getxattr(d_inode(dentry), handler->flags, name, | 48 | return f2fs_getxattr(d_inode(dentry), handler->flags, name, |
83 | buffer, size, NULL); | 49 | buffer, size, NULL); |
84 | } | 50 | } |
@@ -103,24 +69,20 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler, | |||
103 | default: | 69 | default: |
104 | return -EINVAL; | 70 | return -EINVAL; |
105 | } | 71 | } |
106 | if (strcmp(name, "") == 0) | ||
107 | return -EINVAL; | ||
108 | |||
109 | return f2fs_setxattr(d_inode(dentry), handler->flags, name, | 72 | return f2fs_setxattr(d_inode(dentry), handler->flags, name, |
110 | value, size, NULL, flags); | 73 | value, size, NULL, flags); |
111 | } | 74 | } |
112 | 75 | ||
113 | static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler, | 76 | static bool f2fs_xattr_user_list(struct dentry *dentry) |
114 | struct dentry *dentry, char *list, size_t list_size, | ||
115 | const char *name, size_t len) | ||
116 | { | 77 | { |
117 | const char *xname = F2FS_SYSTEM_ADVISE_PREFIX; | 78 | struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); |
118 | size_t size; | ||
119 | 79 | ||
120 | size = strlen(xname) + 1; | 80 | return test_opt(sbi, XATTR_USER); |
121 | if (list && size <= list_size) | 81 | } |
122 | memcpy(list, xname, size); | 82 | |
123 | return size; | 83 | static bool f2fs_xattr_trusted_list(struct dentry *dentry) |
84 | { | ||
85 | return capable(CAP_SYS_ADMIN); | ||
124 | } | 86 | } |
125 | 87 | ||
126 | static int f2fs_xattr_advise_get(const struct xattr_handler *handler, | 88 | static int f2fs_xattr_advise_get(const struct xattr_handler *handler, |
@@ -129,9 +91,6 @@ static int f2fs_xattr_advise_get(const struct xattr_handler *handler, | |||
129 | { | 91 | { |
130 | struct inode *inode = d_inode(dentry); | 92 | struct inode *inode = d_inode(dentry); |
131 | 93 | ||
132 | if (strcmp(name, "") != 0) | ||
133 | return -EINVAL; | ||
134 | |||
135 | if (buffer) | 94 | if (buffer) |
136 | *((char *)buffer) = F2FS_I(inode)->i_advise; | 95 | *((char *)buffer) = F2FS_I(inode)->i_advise; |
137 | return sizeof(char); | 96 | return sizeof(char); |
@@ -143,8 +102,6 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler, | |||
143 | { | 102 | { |
144 | struct inode *inode = d_inode(dentry); | 103 | struct inode *inode = d_inode(dentry); |
145 | 104 | ||
146 | if (strcmp(name, "") != 0) | ||
147 | return -EINVAL; | ||
148 | if (!inode_owner_or_capable(inode)) | 105 | if (!inode_owner_or_capable(inode)) |
149 | return -EPERM; | 106 | return -EPERM; |
150 | if (value == NULL) | 107 | if (value == NULL) |
@@ -183,7 +140,7 @@ int f2fs_init_security(struct inode *inode, struct inode *dir, | |||
183 | const struct xattr_handler f2fs_xattr_user_handler = { | 140 | const struct xattr_handler f2fs_xattr_user_handler = { |
184 | .prefix = XATTR_USER_PREFIX, | 141 | .prefix = XATTR_USER_PREFIX, |
185 | .flags = F2FS_XATTR_INDEX_USER, | 142 | .flags = F2FS_XATTR_INDEX_USER, |
186 | .list = f2fs_xattr_generic_list, | 143 | .list = f2fs_xattr_user_list, |
187 | .get = f2fs_xattr_generic_get, | 144 | .get = f2fs_xattr_generic_get, |
188 | .set = f2fs_xattr_generic_set, | 145 | .set = f2fs_xattr_generic_set, |
189 | }; | 146 | }; |
@@ -191,15 +148,14 @@ const struct xattr_handler f2fs_xattr_user_handler = { | |||
191 | const struct xattr_handler f2fs_xattr_trusted_handler = { | 148 | const struct xattr_handler f2fs_xattr_trusted_handler = { |
192 | .prefix = XATTR_TRUSTED_PREFIX, | 149 | .prefix = XATTR_TRUSTED_PREFIX, |
193 | .flags = F2FS_XATTR_INDEX_TRUSTED, | 150 | .flags = F2FS_XATTR_INDEX_TRUSTED, |
194 | .list = f2fs_xattr_generic_list, | 151 | .list = f2fs_xattr_trusted_list, |
195 | .get = f2fs_xattr_generic_get, | 152 | .get = f2fs_xattr_generic_get, |
196 | .set = f2fs_xattr_generic_set, | 153 | .set = f2fs_xattr_generic_set, |
197 | }; | 154 | }; |
198 | 155 | ||
199 | const struct xattr_handler f2fs_xattr_advise_handler = { | 156 | const struct xattr_handler f2fs_xattr_advise_handler = { |
200 | .prefix = F2FS_SYSTEM_ADVISE_PREFIX, | 157 | .name = F2FS_SYSTEM_ADVISE_NAME, |
201 | .flags = F2FS_XATTR_INDEX_ADVISE, | 158 | .flags = F2FS_XATTR_INDEX_ADVISE, |
202 | .list = f2fs_xattr_advise_list, | ||
203 | .get = f2fs_xattr_advise_get, | 159 | .get = f2fs_xattr_advise_get, |
204 | .set = f2fs_xattr_advise_set, | 160 | .set = f2fs_xattr_advise_set, |
205 | }; | 161 | }; |
@@ -207,7 +163,6 @@ const struct xattr_handler f2fs_xattr_advise_handler = { | |||
207 | const struct xattr_handler f2fs_xattr_security_handler = { | 163 | const struct xattr_handler f2fs_xattr_security_handler = { |
208 | .prefix = XATTR_SECURITY_PREFIX, | 164 | .prefix = XATTR_SECURITY_PREFIX, |
209 | .flags = F2FS_XATTR_INDEX_SECURITY, | 165 | .flags = F2FS_XATTR_INDEX_SECURITY, |
210 | .list = f2fs_xattr_generic_list, | ||
211 | .get = f2fs_xattr_generic_get, | 166 | .get = f2fs_xattr_generic_get, |
212 | .set = f2fs_xattr_generic_set, | 167 | .set = f2fs_xattr_generic_set, |
213 | }; | 168 | }; |
@@ -455,20 +410,27 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
455 | list_for_each_xattr(entry, base_addr) { | 410 | list_for_each_xattr(entry, base_addr) { |
456 | const struct xattr_handler *handler = | 411 | const struct xattr_handler *handler = |
457 | f2fs_xattr_handler(entry->e_name_index); | 412 | f2fs_xattr_handler(entry->e_name_index); |
413 | const char *prefix; | ||
414 | size_t prefix_len; | ||
458 | size_t size; | 415 | size_t size; |
459 | 416 | ||
460 | if (!handler) | 417 | if (!handler || (handler->list && !handler->list(dentry))) |
461 | continue; | 418 | continue; |
462 | 419 | ||
463 | size = handler->list(handler, dentry, buffer, rest, | 420 | prefix = handler->prefix ?: handler->name; |
464 | entry->e_name, entry->e_name_len); | 421 | prefix_len = strlen(prefix); |
465 | if (buffer && size > rest) { | 422 | size = prefix_len + entry->e_name_len + 1; |
466 | error = -ERANGE; | 423 | if (buffer) { |
467 | goto cleanup; | 424 | if (size > rest) { |
425 | error = -ERANGE; | ||
426 | goto cleanup; | ||
427 | } | ||
428 | memcpy(buffer, prefix, prefix_len); | ||
429 | buffer += prefix_len; | ||
430 | memcpy(buffer, entry->e_name, entry->e_name_len); | ||
431 | buffer += entry->e_name_len; | ||
432 | *buffer++ = 0; | ||
468 | } | 433 | } |
469 | |||
470 | if (buffer) | ||
471 | buffer += size; | ||
472 | rest -= size; | 434 | rest -= size; |
473 | } | 435 | } |
474 | error = buffer_size - rest; | 436 | error = buffer_size - rest; |
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 71a7100d5492..79dccc8252dd 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define F2FS_XATTR_REFCOUNT_MAX 1024 | 27 | #define F2FS_XATTR_REFCOUNT_MAX 1024 |
28 | 28 | ||
29 | /* Name indexes */ | 29 | /* Name indexes */ |
30 | #define F2FS_SYSTEM_ADVISE_PREFIX "system.advise" | 30 | #define F2FS_SYSTEM_ADVISE_NAME "system.advise" |
31 | #define F2FS_XATTR_INDEX_USER 1 | 31 | #define F2FS_XATTR_INDEX_USER 1 |
32 | #define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2 | 32 | #define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2 |
33 | #define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 | 33 | #define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 |
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 1be3b061c05c..791932617d1a 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c | |||
@@ -31,9 +31,9 @@ static const char *gfs2_acl_name(int type) | |||
31 | { | 31 | { |
32 | switch (type) { | 32 | switch (type) { |
33 | case ACL_TYPE_ACCESS: | 33 | case ACL_TYPE_ACCESS: |
34 | return GFS2_POSIX_ACL_ACCESS; | 34 | return XATTR_POSIX_ACL_ACCESS; |
35 | case ACL_TYPE_DEFAULT: | 35 | case ACL_TYPE_DEFAULT: |
36 | return GFS2_POSIX_ACL_DEFAULT; | 36 | return XATTR_POSIX_ACL_DEFAULT; |
37 | } | 37 | } |
38 | return NULL; | 38 | return NULL; |
39 | } | 39 | } |
diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h index 2d65ec4cd4be..3af4f407a483 100644 --- a/fs/gfs2/acl.h +++ b/fs/gfs2/acl.h | |||
@@ -12,8 +12,6 @@ | |||
12 | 12 | ||
13 | #include "incore.h" | 13 | #include "incore.h" |
14 | 14 | ||
15 | #define GFS2_POSIX_ACL_ACCESS "posix_acl_access" | ||
16 | #define GFS2_POSIX_ACL_DEFAULT "posix_acl_default" | ||
17 | #define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12) | 15 | #define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12) |
18 | 16 | ||
19 | extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type); | 17 | extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type); |
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 53ce76a374fe..84f2d81fe451 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c | |||
@@ -1237,56 +1237,6 @@ static int gfs2_xattr_set(const struct xattr_handler *handler, | |||
1237 | size, flags, handler->flags); | 1237 | size, flags, handler->flags); |
1238 | } | 1238 | } |
1239 | 1239 | ||
1240 | |||
1241 | static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip, | ||
1242 | struct gfs2_ea_header *ea, char *data) | ||
1243 | { | ||
1244 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
1245 | unsigned int amount = GFS2_EA_DATA_LEN(ea); | ||
1246 | unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize); | ||
1247 | int ret; | ||
1248 | |||
1249 | ret = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0); | ||
1250 | if (ret) | ||
1251 | return ret; | ||
1252 | |||
1253 | ret = gfs2_iter_unstuffed(ip, ea, data, NULL); | ||
1254 | gfs2_trans_end(sdp); | ||
1255 | |||
1256 | return ret; | ||
1257 | } | ||
1258 | |||
1259 | int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data) | ||
1260 | { | ||
1261 | struct inode *inode = &ip->i_inode; | ||
1262 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
1263 | struct gfs2_ea_location el; | ||
1264 | int error; | ||
1265 | |||
1266 | error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el); | ||
1267 | if (error) | ||
1268 | return error; | ||
1269 | |||
1270 | if (GFS2_EA_IS_STUFFED(el.el_ea)) { | ||
1271 | error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0); | ||
1272 | if (error == 0) { | ||
1273 | gfs2_trans_add_meta(ip->i_gl, el.el_bh); | ||
1274 | memcpy(GFS2_EA2DATA(el.el_ea), data, | ||
1275 | GFS2_EA_DATA_LEN(el.el_ea)); | ||
1276 | } | ||
1277 | } else { | ||
1278 | error = ea_acl_chmod_unstuffed(ip, el.el_ea, data); | ||
1279 | } | ||
1280 | |||
1281 | brelse(el.el_bh); | ||
1282 | if (error) | ||
1283 | return error; | ||
1284 | |||
1285 | error = gfs2_setattr_simple(inode, attr); | ||
1286 | gfs2_trans_end(sdp); | ||
1287 | return error; | ||
1288 | } | ||
1289 | |||
1290 | static int ea_dealloc_indirect(struct gfs2_inode *ip) | 1240 | static int ea_dealloc_indirect(struct gfs2_inode *ip) |
1291 | { | 1241 | { |
1292 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1242 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
diff --git a/fs/gfs2/xattr.h b/fs/gfs2/xattr.h index d392f8358f2f..2d887c88eb49 100644 --- a/fs/gfs2/xattr.h +++ b/fs/gfs2/xattr.h | |||
@@ -62,6 +62,5 @@ extern int gfs2_ea_dealloc(struct gfs2_inode *ip); | |||
62 | /* Exported to acl.c */ | 62 | /* Exported to acl.c */ |
63 | 63 | ||
64 | extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data); | 64 | extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data); |
65 | extern int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data); | ||
66 | 65 | ||
67 | #endif /* __EATTR_DOT_H__ */ | 66 | #endif /* __EATTR_DOT_H__ */ |
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c index df0c9af68d05..afb33eda6d7d 100644 --- a/fs/hfsplus/posix_acl.c +++ b/fs/hfsplus/posix_acl.c | |||
@@ -21,10 +21,10 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type) | |||
21 | 21 | ||
22 | switch (type) { | 22 | switch (type) { |
23 | case ACL_TYPE_ACCESS: | 23 | case ACL_TYPE_ACCESS: |
24 | xattr_name = POSIX_ACL_XATTR_ACCESS; | 24 | xattr_name = XATTR_NAME_POSIX_ACL_ACCESS; |
25 | break; | 25 | break; |
26 | case ACL_TYPE_DEFAULT: | 26 | case ACL_TYPE_DEFAULT: |
27 | xattr_name = POSIX_ACL_XATTR_DEFAULT; | 27 | xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT; |
28 | break; | 28 | break; |
29 | default: | 29 | default: |
30 | return ERR_PTR(-EINVAL); | 30 | return ERR_PTR(-EINVAL); |
@@ -66,7 +66,7 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, | |||
66 | 66 | ||
67 | switch (type) { | 67 | switch (type) { |
68 | case ACL_TYPE_ACCESS: | 68 | case ACL_TYPE_ACCESS: |
69 | xattr_name = POSIX_ACL_XATTR_ACCESS; | 69 | xattr_name = XATTR_NAME_POSIX_ACL_ACCESS; |
70 | if (acl) { | 70 | if (acl) { |
71 | err = posix_acl_equiv_mode(acl, &inode->i_mode); | 71 | err = posix_acl_equiv_mode(acl, &inode->i_mode); |
72 | if (err < 0) | 72 | if (err < 0) |
@@ -76,7 +76,7 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, | |||
76 | break; | 76 | break; |
77 | 77 | ||
78 | case ACL_TYPE_DEFAULT: | 78 | case ACL_TYPE_DEFAULT: |
79 | xattr_name = POSIX_ACL_XATTR_DEFAULT; | 79 | xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT; |
80 | if (!S_ISDIR(inode->i_mode)) | 80 | if (!S_ISDIR(inode->i_mode)) |
81 | return acl ? -EACCES : 0; | 81 | return acl ? -EACCES : 0; |
82 | break; | 82 | break; |
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index e41a010cd89c..ab01530b4930 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c | |||
@@ -431,9 +431,6 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name, | |||
431 | char *xattr_name; | 431 | char *xattr_name; |
432 | int res; | 432 | int res; |
433 | 433 | ||
434 | if (!strcmp(name, "")) | ||
435 | return -EINVAL; | ||
436 | |||
437 | xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, | 434 | xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, |
438 | GFP_KERNEL); | 435 | GFP_KERNEL); |
439 | if (!xattr_name) | 436 | if (!xattr_name) |
@@ -589,9 +586,6 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, | |||
589 | int res; | 586 | int res; |
590 | char *xattr_name; | 587 | char *xattr_name; |
591 | 588 | ||
592 | if (!strcmp(name, "")) | ||
593 | return -EINVAL; | ||
594 | |||
595 | xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, | 589 | xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1, |
596 | GFP_KERNEL); | 590 | GFP_KERNEL); |
597 | if (!xattr_name) | 591 | if (!xattr_name) |
@@ -853,9 +847,6 @@ static int hfsplus_osx_getxattr(const struct xattr_handler *handler, | |||
853 | struct dentry *dentry, const char *name, | 847 | struct dentry *dentry, const char *name, |
854 | void *buffer, size_t size) | 848 | void *buffer, size_t size) |
855 | { | 849 | { |
856 | if (!strcmp(name, "")) | ||
857 | return -EINVAL; | ||
858 | |||
859 | /* | 850 | /* |
860 | * Don't allow retrieving properly prefixed attributes | 851 | * Don't allow retrieving properly prefixed attributes |
861 | * by prepending them with "osx." | 852 | * by prepending them with "osx." |
@@ -876,9 +867,6 @@ static int hfsplus_osx_setxattr(const struct xattr_handler *handler, | |||
876 | struct dentry *dentry, const char *name, | 867 | struct dentry *dentry, const char *name, |
877 | const void *buffer, size_t size, int flags) | 868 | const void *buffer, size_t size, int flags) |
878 | { | 869 | { |
879 | if (!strcmp(name, "")) | ||
880 | return -EINVAL; | ||
881 | |||
882 | /* | 870 | /* |
883 | * Don't allow setting properly prefixed attributes | 871 | * Don't allow setting properly prefixed attributes |
884 | * by prepending them with "osx." | 872 | * by prepending them with "osx." |
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index bf12fe5f83d7..7a28facd7175 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c | |||
@@ -52,9 +52,6 @@ static int jffs2_security_getxattr(const struct xattr_handler *handler, | |||
52 | struct dentry *dentry, const char *name, | 52 | struct dentry *dentry, const char *name, |
53 | void *buffer, size_t size) | 53 | void *buffer, size_t size) |
54 | { | 54 | { |
55 | if (!strcmp(name, "")) | ||
56 | return -EINVAL; | ||
57 | |||
58 | return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY, | 55 | return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY, |
59 | name, buffer, size); | 56 | name, buffer, size); |
60 | } | 57 | } |
@@ -63,31 +60,12 @@ static int jffs2_security_setxattr(const struct xattr_handler *handler, | |||
63 | struct dentry *dentry, const char *name, | 60 | struct dentry *dentry, const char *name, |
64 | const void *buffer, size_t size, int flags) | 61 | const void *buffer, size_t size, int flags) |
65 | { | 62 | { |
66 | if (!strcmp(name, "")) | ||
67 | return -EINVAL; | ||
68 | |||
69 | return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY, | 63 | return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY, |
70 | name, buffer, size, flags); | 64 | name, buffer, size, flags); |
71 | } | 65 | } |
72 | 66 | ||
73 | static size_t jffs2_security_listxattr(const struct xattr_handler *handler, | ||
74 | struct dentry *dentry, char *list, | ||
75 | size_t list_size, const char *name, | ||
76 | size_t name_len) | ||
77 | { | ||
78 | size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1; | ||
79 | |||
80 | if (list && retlen <= list_size) { | ||
81 | strcpy(list, XATTR_SECURITY_PREFIX); | ||
82 | strcpy(list + XATTR_SECURITY_PREFIX_LEN, name); | ||
83 | } | ||
84 | |||
85 | return retlen; | ||
86 | } | ||
87 | |||
88 | const struct xattr_handler jffs2_security_xattr_handler = { | 67 | const struct xattr_handler jffs2_security_xattr_handler = { |
89 | .prefix = XATTR_SECURITY_PREFIX, | 68 | .prefix = XATTR_SECURITY_PREFIX, |
90 | .list = jffs2_security_listxattr, | ||
91 | .set = jffs2_security_setxattr, | 69 | .set = jffs2_security_setxattr, |
92 | .get = jffs2_security_getxattr | 70 | .get = jffs2_security_getxattr |
93 | }; | 71 | }; |
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 4c2c03663533..da3e18503c65 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
@@ -967,7 +967,8 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
967 | struct jffs2_xattr_ref *ref, **pref; | 967 | struct jffs2_xattr_ref *ref, **pref; |
968 | struct jffs2_xattr_datum *xd; | 968 | struct jffs2_xattr_datum *xd; |
969 | const struct xattr_handler *xhandle; | 969 | const struct xattr_handler *xhandle; |
970 | ssize_t len, rc; | 970 | const char *prefix; |
971 | ssize_t prefix_len, len, rc; | ||
971 | int retry = 0; | 972 | int retry = 0; |
972 | 973 | ||
973 | rc = check_xattr_ref_inode(c, ic); | 974 | rc = check_xattr_ref_inode(c, ic); |
@@ -998,18 +999,23 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
998 | } | 999 | } |
999 | } | 1000 | } |
1000 | xhandle = xprefix_to_handler(xd->xprefix); | 1001 | xhandle = xprefix_to_handler(xd->xprefix); |
1001 | if (!xhandle) | 1002 | if (!xhandle || (xhandle->list && !xhandle->list(dentry))) |
1002 | continue; | 1003 | continue; |
1004 | prefix = xhandle->prefix ?: xhandle->name; | ||
1005 | prefix_len = strlen(prefix); | ||
1006 | rc = prefix_len + xd->name_len + 1; | ||
1007 | |||
1003 | if (buffer) { | 1008 | if (buffer) { |
1004 | rc = xhandle->list(xhandle, dentry, buffer + len, | 1009 | if (rc > size - len) { |
1005 | size - len, xd->xname, | 1010 | rc = -ERANGE; |
1006 | xd->name_len); | 1011 | goto out; |
1007 | } else { | 1012 | } |
1008 | rc = xhandle->list(xhandle, dentry, NULL, 0, | 1013 | memcpy(buffer, prefix, prefix_len); |
1009 | xd->xname, xd->name_len); | 1014 | buffer += prefix_len; |
1015 | memcpy(buffer, xd->xname, xd->name_len); | ||
1016 | buffer += xd->name_len; | ||
1017 | *buffer++ = 0; | ||
1010 | } | 1018 | } |
1011 | if (rc < 0) | ||
1012 | goto out; | ||
1013 | len += rc; | 1019 | len += rc; |
1014 | } | 1020 | } |
1015 | rc = len; | 1021 | rc = len; |
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c index a562da0d6a26..b2555ef07a12 100644 --- a/fs/jffs2/xattr_trusted.c +++ b/fs/jffs2/xattr_trusted.c | |||
@@ -20,8 +20,6 @@ static int jffs2_trusted_getxattr(const struct xattr_handler *handler, | |||
20 | struct dentry *dentry, const char *name, | 20 | struct dentry *dentry, const char *name, |
21 | void *buffer, size_t size) | 21 | void *buffer, size_t size) |
22 | { | 22 | { |
23 | if (!strcmp(name, "")) | ||
24 | return -EINVAL; | ||
25 | return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED, | 23 | return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED, |
26 | name, buffer, size); | 24 | name, buffer, size); |
27 | } | 25 | } |
@@ -30,28 +28,13 @@ static int jffs2_trusted_setxattr(const struct xattr_handler *handler, | |||
30 | struct dentry *dentry, const char *name, | 28 | struct dentry *dentry, const char *name, |
31 | const void *buffer, size_t size, int flags) | 29 | const void *buffer, size_t size, int flags) |
32 | { | 30 | { |
33 | if (!strcmp(name, "")) | ||
34 | return -EINVAL; | ||
35 | return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED, | 31 | return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED, |
36 | name, buffer, size, flags); | 32 | name, buffer, size, flags); |
37 | } | 33 | } |
38 | 34 | ||
39 | static size_t jffs2_trusted_listxattr(const struct xattr_handler *handler, | 35 | static bool jffs2_trusted_listxattr(struct dentry *dentry) |
40 | struct dentry *dentry, char *list, | ||
41 | size_t list_size, const char *name, | ||
42 | size_t name_len) | ||
43 | { | 36 | { |
44 | size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1; | 37 | return capable(CAP_SYS_ADMIN); |
45 | |||
46 | if (!capable(CAP_SYS_ADMIN)) | ||
47 | return 0; | ||
48 | |||
49 | if (list && retlen<=list_size) { | ||
50 | strcpy(list, XATTR_TRUSTED_PREFIX); | ||
51 | strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name); | ||
52 | } | ||
53 | |||
54 | return retlen; | ||
55 | } | 38 | } |
56 | 39 | ||
57 | const struct xattr_handler jffs2_trusted_xattr_handler = { | 40 | const struct xattr_handler jffs2_trusted_xattr_handler = { |
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c index cbc0472e59a8..539bd630b5e4 100644 --- a/fs/jffs2/xattr_user.c +++ b/fs/jffs2/xattr_user.c | |||
@@ -20,8 +20,6 @@ static int jffs2_user_getxattr(const struct xattr_handler *handler, | |||
20 | struct dentry *dentry, const char *name, | 20 | struct dentry *dentry, const char *name, |
21 | void *buffer, size_t size) | 21 | void *buffer, size_t size) |
22 | { | 22 | { |
23 | if (!strcmp(name, "")) | ||
24 | return -EINVAL; | ||
25 | return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER, | 23 | return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER, |
26 | name, buffer, size); | 24 | name, buffer, size); |
27 | } | 25 | } |
@@ -30,30 +28,12 @@ static int jffs2_user_setxattr(const struct xattr_handler *handler, | |||
30 | struct dentry *dentry, const char *name, | 28 | struct dentry *dentry, const char *name, |
31 | const void *buffer, size_t size, int flags) | 29 | const void *buffer, size_t size, int flags) |
32 | { | 30 | { |
33 | if (!strcmp(name, "")) | ||
34 | return -EINVAL; | ||
35 | return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER, | 31 | return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER, |
36 | name, buffer, size, flags); | 32 | name, buffer, size, flags); |
37 | } | 33 | } |
38 | 34 | ||
39 | static size_t jffs2_user_listxattr(const struct xattr_handler *handler, | ||
40 | struct dentry *dentry, char *list, | ||
41 | size_t list_size, const char *name, | ||
42 | size_t name_len) | ||
43 | { | ||
44 | size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1; | ||
45 | |||
46 | if (list && retlen <= list_size) { | ||
47 | strcpy(list, XATTR_USER_PREFIX); | ||
48 | strcpy(list + XATTR_USER_PREFIX_LEN, name); | ||
49 | } | ||
50 | |||
51 | return retlen; | ||
52 | } | ||
53 | |||
54 | const struct xattr_handler jffs2_user_xattr_handler = { | 35 | const struct xattr_handler jffs2_user_xattr_handler = { |
55 | .prefix = XATTR_USER_PREFIX, | 36 | .prefix = XATTR_USER_PREFIX, |
56 | .list = jffs2_user_listxattr, | ||
57 | .set = jffs2_user_setxattr, | 37 | .set = jffs2_user_setxattr, |
58 | .get = jffs2_user_getxattr | 38 | .get = jffs2_user_getxattr |
59 | }; | 39 | }; |
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index 0c8ca830b113..49456853e9de 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c | |||
@@ -40,10 +40,10 @@ struct posix_acl *jfs_get_acl(struct inode *inode, int type) | |||
40 | 40 | ||
41 | switch(type) { | 41 | switch(type) { |
42 | case ACL_TYPE_ACCESS: | 42 | case ACL_TYPE_ACCESS: |
43 | ea_name = POSIX_ACL_XATTR_ACCESS; | 43 | ea_name = XATTR_NAME_POSIX_ACL_ACCESS; |
44 | break; | 44 | break; |
45 | case ACL_TYPE_DEFAULT: | 45 | case ACL_TYPE_DEFAULT: |
46 | ea_name = POSIX_ACL_XATTR_DEFAULT; | 46 | ea_name = XATTR_NAME_POSIX_ACL_DEFAULT; |
47 | break; | 47 | break; |
48 | default: | 48 | default: |
49 | return ERR_PTR(-EINVAL); | 49 | return ERR_PTR(-EINVAL); |
@@ -82,7 +82,7 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, | |||
82 | 82 | ||
83 | switch (type) { | 83 | switch (type) { |
84 | case ACL_TYPE_ACCESS: | 84 | case ACL_TYPE_ACCESS: |
85 | ea_name = POSIX_ACL_XATTR_ACCESS; | 85 | ea_name = XATTR_NAME_POSIX_ACL_ACCESS; |
86 | if (acl) { | 86 | if (acl) { |
87 | rc = posix_acl_equiv_mode(acl, &inode->i_mode); | 87 | rc = posix_acl_equiv_mode(acl, &inode->i_mode); |
88 | if (rc < 0) | 88 | if (rc < 0) |
@@ -94,7 +94,7 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, | |||
94 | } | 94 | } |
95 | break; | 95 | break; |
96 | case ACL_TYPE_DEFAULT: | 96 | case ACL_TYPE_DEFAULT: |
97 | ea_name = POSIX_ACL_XATTR_DEFAULT; | 97 | ea_name = XATTR_NAME_POSIX_ACL_DEFAULT; |
98 | break; | 98 | break; |
99 | default: | 99 | default: |
100 | return -EINVAL; | 100 | return -EINVAL; |
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 756dd56aaf60..16405ae88d2d 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c | |||
@@ -205,7 +205,7 @@ int kernfs_iop_removexattr(struct dentry *dentry, const char *name) | |||
205 | if (!attrs) | 205 | if (!attrs) |
206 | return -ENOMEM; | 206 | return -ENOMEM; |
207 | 207 | ||
208 | return simple_xattr_remove(&attrs->xattrs, name); | 208 | return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE); |
209 | } | 209 | } |
210 | 210 | ||
211 | ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, | 211 | ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, |
@@ -230,7 +230,7 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) | |||
230 | if (!attrs) | 230 | if (!attrs) |
231 | return -ENOMEM; | 231 | return -ENOMEM; |
232 | 232 | ||
233 | return simple_xattr_list(&attrs->xattrs, buf, size); | 233 | return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size); |
234 | } | 234 | } |
235 | 235 | ||
236 | static inline void set_default_inode_attr(struct inode *inode, umode_t mode) | 236 | static inline void set_default_inode_attr(struct inode *inode, umode_t mode) |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 1ebe2fc7cda2..17c0fa1eccfa 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -284,12 +284,12 @@ nfs3_listxattr(struct dentry *dentry, char *data, size_t size) | |||
284 | int error; | 284 | int error; |
285 | 285 | ||
286 | error = nfs3_list_one_acl(inode, ACL_TYPE_ACCESS, | 286 | error = nfs3_list_one_acl(inode, ACL_TYPE_ACCESS, |
287 | POSIX_ACL_XATTR_ACCESS, data, size, &result); | 287 | XATTR_NAME_POSIX_ACL_ACCESS, data, size, &result); |
288 | if (error) | 288 | if (error) |
289 | return error; | 289 | return error; |
290 | 290 | ||
291 | error = nfs3_list_one_acl(inode, ACL_TYPE_DEFAULT, | 291 | error = nfs3_list_one_acl(inode, ACL_TYPE_DEFAULT, |
292 | POSIX_ACL_XATTR_DEFAULT, data, size, &result); | 292 | XATTR_NAME_POSIX_ACL_DEFAULT, data, size, &result); |
293 | if (error) | 293 | if (error) |
294 | return error; | 294 | return error; |
295 | return result; | 295 | return result; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 89818036f035..c57d1332c1c8 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -6253,9 +6253,6 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler, | |||
6253 | const void *buf, size_t buflen, | 6253 | const void *buf, size_t buflen, |
6254 | int flags) | 6254 | int flags) |
6255 | { | 6255 | { |
6256 | if (strcmp(key, "") != 0) | ||
6257 | return -EINVAL; | ||
6258 | |||
6259 | return nfs4_proc_set_acl(d_inode(dentry), buf, buflen); | 6256 | return nfs4_proc_set_acl(d_inode(dentry), buf, buflen); |
6260 | } | 6257 | } |
6261 | 6258 | ||
@@ -6263,32 +6260,15 @@ static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler, | |||
6263 | struct dentry *dentry, const char *key, | 6260 | struct dentry *dentry, const char *key, |
6264 | void *buf, size_t buflen) | 6261 | void *buf, size_t buflen) |
6265 | { | 6262 | { |
6266 | if (strcmp(key, "") != 0) | ||
6267 | return -EINVAL; | ||
6268 | |||
6269 | return nfs4_proc_get_acl(d_inode(dentry), buf, buflen); | 6263 | return nfs4_proc_get_acl(d_inode(dentry), buf, buflen); |
6270 | } | 6264 | } |
6271 | 6265 | ||
6272 | static size_t nfs4_xattr_list_nfs4_acl(const struct xattr_handler *handler, | 6266 | static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry) |
6273 | struct dentry *dentry, char *list, | ||
6274 | size_t list_len, const char *name, | ||
6275 | size_t name_len) | ||
6276 | { | 6267 | { |
6277 | size_t len = sizeof(XATTR_NAME_NFSV4_ACL); | 6268 | return nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry))); |
6278 | |||
6279 | if (!nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry)))) | ||
6280 | return 0; | ||
6281 | |||
6282 | if (list && len <= list_len) | ||
6283 | memcpy(list, XATTR_NAME_NFSV4_ACL, len); | ||
6284 | return len; | ||
6285 | } | 6269 | } |
6286 | 6270 | ||
6287 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 6271 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
6288 | static inline int nfs4_server_supports_labels(struct nfs_server *server) | ||
6289 | { | ||
6290 | return server->caps & NFS_CAP_SECURITY_LABEL; | ||
6291 | } | ||
6292 | 6272 | ||
6293 | static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler, | 6273 | static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler, |
6294 | struct dentry *dentry, const char *key, | 6274 | struct dentry *dentry, const char *key, |
@@ -6310,29 +6290,34 @@ static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler, | |||
6310 | return -EOPNOTSUPP; | 6290 | return -EOPNOTSUPP; |
6311 | } | 6291 | } |
6312 | 6292 | ||
6313 | static size_t nfs4_xattr_list_nfs4_label(const struct xattr_handler *handler, | 6293 | static ssize_t |
6314 | struct dentry *dentry, char *list, | 6294 | nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len) |
6315 | size_t list_len, const char *name, | ||
6316 | size_t name_len) | ||
6317 | { | 6295 | { |
6318 | size_t len = 0; | 6296 | int len = 0; |
6319 | 6297 | ||
6320 | if (nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) { | 6298 | if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) { |
6321 | len = security_inode_listsecurity(d_inode(dentry), NULL, 0); | 6299 | len = security_inode_listsecurity(inode, list, list_len); |
6322 | if (list && len <= list_len) | 6300 | if (list_len && len > list_len) |
6323 | security_inode_listsecurity(d_inode(dentry), list, len); | 6301 | return -ERANGE; |
6324 | } | 6302 | } |
6325 | return len; | 6303 | return len; |
6326 | } | 6304 | } |
6327 | 6305 | ||
6328 | static const struct xattr_handler nfs4_xattr_nfs4_label_handler = { | 6306 | static const struct xattr_handler nfs4_xattr_nfs4_label_handler = { |
6329 | .prefix = XATTR_SECURITY_PREFIX, | 6307 | .prefix = XATTR_SECURITY_PREFIX, |
6330 | .list = nfs4_xattr_list_nfs4_label, | ||
6331 | .get = nfs4_xattr_get_nfs4_label, | 6308 | .get = nfs4_xattr_get_nfs4_label, |
6332 | .set = nfs4_xattr_set_nfs4_label, | 6309 | .set = nfs4_xattr_set_nfs4_label, |
6333 | }; | 6310 | }; |
6334 | #endif | ||
6335 | 6311 | ||
6312 | #else | ||
6313 | |||
6314 | static ssize_t | ||
6315 | nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len) | ||
6316 | { | ||
6317 | return 0; | ||
6318 | } | ||
6319 | |||
6320 | #endif | ||
6336 | 6321 | ||
6337 | /* | 6322 | /* |
6338 | * nfs_fhget will use either the mounted_on_fileid or the fileid | 6323 | * nfs_fhget will use either the mounted_on_fileid or the fileid |
@@ -8749,6 +8734,24 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { | |||
8749 | #endif | 8734 | #endif |
8750 | }; | 8735 | }; |
8751 | 8736 | ||
8737 | ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size) | ||
8738 | { | ||
8739 | ssize_t error, error2; | ||
8740 | |||
8741 | error = generic_listxattr(dentry, list, size); | ||
8742 | if (error < 0) | ||
8743 | return error; | ||
8744 | if (list) { | ||
8745 | list += error; | ||
8746 | size -= error; | ||
8747 | } | ||
8748 | |||
8749 | error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, size); | ||
8750 | if (error2 < 0) | ||
8751 | return error2; | ||
8752 | return error + error2; | ||
8753 | } | ||
8754 | |||
8752 | static const struct inode_operations nfs4_dir_inode_operations = { | 8755 | static const struct inode_operations nfs4_dir_inode_operations = { |
8753 | .create = nfs_create, | 8756 | .create = nfs_create, |
8754 | .lookup = nfs_lookup, | 8757 | .lookup = nfs_lookup, |
@@ -8765,7 +8768,7 @@ static const struct inode_operations nfs4_dir_inode_operations = { | |||
8765 | .setattr = nfs_setattr, | 8768 | .setattr = nfs_setattr, |
8766 | .getxattr = generic_getxattr, | 8769 | .getxattr = generic_getxattr, |
8767 | .setxattr = generic_setxattr, | 8770 | .setxattr = generic_setxattr, |
8768 | .listxattr = generic_listxattr, | 8771 | .listxattr = nfs4_listxattr, |
8769 | .removexattr = generic_removexattr, | 8772 | .removexattr = generic_removexattr, |
8770 | }; | 8773 | }; |
8771 | 8774 | ||
@@ -8775,7 +8778,7 @@ static const struct inode_operations nfs4_file_inode_operations = { | |||
8775 | .setattr = nfs_setattr, | 8778 | .setattr = nfs_setattr, |
8776 | .getxattr = generic_getxattr, | 8779 | .getxattr = generic_getxattr, |
8777 | .setxattr = generic_setxattr, | 8780 | .setxattr = generic_setxattr, |
8778 | .listxattr = generic_listxattr, | 8781 | .listxattr = nfs4_listxattr, |
8779 | .removexattr = generic_removexattr, | 8782 | .removexattr = generic_removexattr, |
8780 | }; | 8783 | }; |
8781 | 8784 | ||
@@ -8834,7 +8837,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
8834 | }; | 8837 | }; |
8835 | 8838 | ||
8836 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | 8839 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |
8837 | .prefix = XATTR_NAME_NFSV4_ACL, | 8840 | .name = XATTR_NAME_NFSV4_ACL, |
8838 | .list = nfs4_xattr_list_nfs4_acl, | 8841 | .list = nfs4_xattr_list_nfs4_acl, |
8839 | .get = nfs4_xattr_get_nfs4_acl, | 8842 | .get = nfs4_xattr_get_nfs4_acl, |
8840 | .set = nfs4_xattr_set_nfs4_acl, | 8843 | .set = nfs4_xattr_set_nfs4_acl, |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e9164f09841b..f0e241ffd94f 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -544,8 +544,7 @@ static inline const char *ocfs2_xattr_prefix(int name_index) | |||
544 | 544 | ||
545 | if (name_index > 0 && name_index < OCFS2_XATTR_MAX) | 545 | if (name_index > 0 && name_index < OCFS2_XATTR_MAX) |
546 | handler = ocfs2_xattr_handler_map[name_index]; | 546 | handler = ocfs2_xattr_handler_map[name_index]; |
547 | 547 | return handler ? xattr_prefix(handler) : NULL; | |
548 | return handler ? handler->prefix : NULL; | ||
549 | } | 548 | } |
550 | 549 | ||
551 | static u32 ocfs2_xattr_name_hash(struct inode *inode, | 550 | static u32 ocfs2_xattr_name_hash(struct inode *inode, |
@@ -884,14 +883,39 @@ static int ocfs2_xattr_value_truncate(struct inode *inode, | |||
884 | return ret; | 883 | return ret; |
885 | } | 884 | } |
886 | 885 | ||
887 | static int ocfs2_xattr_list_entry(char *buffer, size_t size, | 886 | static int ocfs2_xattr_list_entry(struct super_block *sb, |
888 | size_t *result, const char *prefix, | 887 | char *buffer, size_t size, |
888 | size_t *result, int type, | ||
889 | const char *name, int name_len) | 889 | const char *name, int name_len) |
890 | { | 890 | { |
891 | char *p = buffer + *result; | 891 | char *p = buffer + *result; |
892 | int prefix_len = strlen(prefix); | 892 | const char *prefix; |
893 | int total_len = prefix_len + name_len + 1; | 893 | int prefix_len; |
894 | int total_len; | ||
894 | 895 | ||
896 | switch(type) { | ||
897 | case OCFS2_XATTR_INDEX_USER: | ||
898 | if (OCFS2_SB(sb)->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) | ||
899 | return 0; | ||
900 | break; | ||
901 | |||
902 | case OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS: | ||
903 | case OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT: | ||
904 | if (!(sb->s_flags & MS_POSIXACL)) | ||
905 | return 0; | ||
906 | break; | ||
907 | |||
908 | case OCFS2_XATTR_INDEX_TRUSTED: | ||
909 | if (!capable(CAP_SYS_ADMIN)) | ||
910 | return 0; | ||
911 | break; | ||
912 | } | ||
913 | |||
914 | prefix = ocfs2_xattr_prefix(type); | ||
915 | if (!prefix) | ||
916 | return 0; | ||
917 | prefix_len = strlen(prefix); | ||
918 | total_len = prefix_len + name_len + 1; | ||
895 | *result += total_len; | 919 | *result += total_len; |
896 | 920 | ||
897 | /* we are just looking for how big our buffer needs to be */ | 921 | /* we are just looking for how big our buffer needs to be */ |
@@ -914,23 +938,20 @@ static int ocfs2_xattr_list_entries(struct inode *inode, | |||
914 | { | 938 | { |
915 | size_t result = 0; | 939 | size_t result = 0; |
916 | int i, type, ret; | 940 | int i, type, ret; |
917 | const char *prefix, *name; | 941 | const char *name; |
918 | 942 | ||
919 | for (i = 0 ; i < le16_to_cpu(header->xh_count); i++) { | 943 | for (i = 0 ; i < le16_to_cpu(header->xh_count); i++) { |
920 | struct ocfs2_xattr_entry *entry = &header->xh_entries[i]; | 944 | struct ocfs2_xattr_entry *entry = &header->xh_entries[i]; |
921 | type = ocfs2_xattr_get_type(entry); | 945 | type = ocfs2_xattr_get_type(entry); |
922 | prefix = ocfs2_xattr_prefix(type); | 946 | name = (const char *)header + |
923 | 947 | le16_to_cpu(entry->xe_name_offset); | |
924 | if (prefix) { | ||
925 | name = (const char *)header + | ||
926 | le16_to_cpu(entry->xe_name_offset); | ||
927 | 948 | ||
928 | ret = ocfs2_xattr_list_entry(buffer, buffer_size, | 949 | ret = ocfs2_xattr_list_entry(inode->i_sb, |
929 | &result, prefix, name, | 950 | buffer, buffer_size, |
930 | entry->xe_name_len); | 951 | &result, type, name, |
931 | if (ret) | 952 | entry->xe_name_len); |
932 | return ret; | 953 | if (ret) |
933 | } | 954 | return ret; |
934 | } | 955 | } |
935 | 956 | ||
936 | return result; | 957 | return result; |
@@ -4033,32 +4054,30 @@ static int ocfs2_list_xattr_bucket(struct inode *inode, | |||
4033 | int ret = 0, type; | 4054 | int ret = 0, type; |
4034 | struct ocfs2_xattr_tree_list *xl = (struct ocfs2_xattr_tree_list *)para; | 4055 | struct ocfs2_xattr_tree_list *xl = (struct ocfs2_xattr_tree_list *)para; |
4035 | int i, block_off, new_offset; | 4056 | int i, block_off, new_offset; |
4036 | const char *prefix, *name; | 4057 | const char *name; |
4037 | 4058 | ||
4038 | for (i = 0 ; i < le16_to_cpu(bucket_xh(bucket)->xh_count); i++) { | 4059 | for (i = 0 ; i < le16_to_cpu(bucket_xh(bucket)->xh_count); i++) { |
4039 | struct ocfs2_xattr_entry *entry = &bucket_xh(bucket)->xh_entries[i]; | 4060 | struct ocfs2_xattr_entry *entry = &bucket_xh(bucket)->xh_entries[i]; |
4040 | type = ocfs2_xattr_get_type(entry); | 4061 | type = ocfs2_xattr_get_type(entry); |
4041 | prefix = ocfs2_xattr_prefix(type); | ||
4042 | 4062 | ||
4043 | if (prefix) { | 4063 | ret = ocfs2_xattr_bucket_get_name_value(inode->i_sb, |
4044 | ret = ocfs2_xattr_bucket_get_name_value(inode->i_sb, | 4064 | bucket_xh(bucket), |
4045 | bucket_xh(bucket), | 4065 | i, |
4046 | i, | 4066 | &block_off, |
4047 | &block_off, | 4067 | &new_offset); |
4048 | &new_offset); | 4068 | if (ret) |
4049 | if (ret) | 4069 | break; |
4050 | break; | ||
4051 | 4070 | ||
4052 | name = (const char *)bucket_block(bucket, block_off) + | 4071 | name = (const char *)bucket_block(bucket, block_off) + |
4053 | new_offset; | 4072 | new_offset; |
4054 | ret = ocfs2_xattr_list_entry(xl->buffer, | 4073 | ret = ocfs2_xattr_list_entry(inode->i_sb, |
4055 | xl->buffer_size, | 4074 | xl->buffer, |
4056 | &xl->result, | 4075 | xl->buffer_size, |
4057 | prefix, name, | 4076 | &xl->result, |
4058 | entry->xe_name_len); | 4077 | type, name, |
4059 | if (ret) | 4078 | entry->xe_name_len); |
4060 | break; | 4079 | if (ret) |
4061 | } | 4080 | break; |
4062 | } | 4081 | } |
4063 | 4082 | ||
4064 | return ret; | 4083 | return ret; |
@@ -7226,31 +7245,14 @@ int ocfs2_init_security_and_acl(struct inode *dir, | |||
7226 | leave: | 7245 | leave: |
7227 | return ret; | 7246 | return ret; |
7228 | } | 7247 | } |
7248 | |||
7229 | /* | 7249 | /* |
7230 | * 'security' attributes support | 7250 | * 'security' attributes support |
7231 | */ | 7251 | */ |
7232 | static size_t ocfs2_xattr_security_list(const struct xattr_handler *handler, | ||
7233 | struct dentry *dentry, char *list, | ||
7234 | size_t list_size, const char *name, | ||
7235 | size_t name_len) | ||
7236 | { | ||
7237 | const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN; | ||
7238 | const size_t total_len = prefix_len + name_len + 1; | ||
7239 | |||
7240 | if (list && total_len <= list_size) { | ||
7241 | memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); | ||
7242 | memcpy(list + prefix_len, name, name_len); | ||
7243 | list[prefix_len + name_len] = '\0'; | ||
7244 | } | ||
7245 | return total_len; | ||
7246 | } | ||
7247 | |||
7248 | static int ocfs2_xattr_security_get(const struct xattr_handler *handler, | 7252 | static int ocfs2_xattr_security_get(const struct xattr_handler *handler, |
7249 | struct dentry *dentry, const char *name, | 7253 | struct dentry *dentry, const char *name, |
7250 | void *buffer, size_t size) | 7254 | void *buffer, size_t size) |
7251 | { | 7255 | { |
7252 | if (strcmp(name, "") == 0) | ||
7253 | return -EINVAL; | ||
7254 | return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY, | 7256 | return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY, |
7255 | name, buffer, size); | 7257 | name, buffer, size); |
7256 | } | 7258 | } |
@@ -7259,9 +7261,6 @@ static int ocfs2_xattr_security_set(const struct xattr_handler *handler, | |||
7259 | struct dentry *dentry, const char *name, | 7261 | struct dentry *dentry, const char *name, |
7260 | const void *value, size_t size, int flags) | 7262 | const void *value, size_t size, int flags) |
7261 | { | 7263 | { |
7262 | if (strcmp(name, "") == 0) | ||
7263 | return -EINVAL; | ||
7264 | |||
7265 | return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY, | 7264 | return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY, |
7266 | name, value, size, flags); | 7265 | name, value, size, flags); |
7267 | } | 7266 | } |
@@ -7314,7 +7313,6 @@ int ocfs2_init_security_set(handle_t *handle, | |||
7314 | 7313 | ||
7315 | const struct xattr_handler ocfs2_xattr_security_handler = { | 7314 | const struct xattr_handler ocfs2_xattr_security_handler = { |
7316 | .prefix = XATTR_SECURITY_PREFIX, | 7315 | .prefix = XATTR_SECURITY_PREFIX, |
7317 | .list = ocfs2_xattr_security_list, | ||
7318 | .get = ocfs2_xattr_security_get, | 7316 | .get = ocfs2_xattr_security_get, |
7319 | .set = ocfs2_xattr_security_set, | 7317 | .set = ocfs2_xattr_security_set, |
7320 | }; | 7318 | }; |
@@ -7322,31 +7320,10 @@ const struct xattr_handler ocfs2_xattr_security_handler = { | |||
7322 | /* | 7320 | /* |
7323 | * 'trusted' attributes support | 7321 | * 'trusted' attributes support |
7324 | */ | 7322 | */ |
7325 | static size_t ocfs2_xattr_trusted_list(const struct xattr_handler *handler, | ||
7326 | struct dentry *dentry, char *list, | ||
7327 | size_t list_size, const char *name, | ||
7328 | size_t name_len) | ||
7329 | { | ||
7330 | const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN; | ||
7331 | const size_t total_len = prefix_len + name_len + 1; | ||
7332 | |||
7333 | if (!capable(CAP_SYS_ADMIN)) | ||
7334 | return 0; | ||
7335 | |||
7336 | if (list && total_len <= list_size) { | ||
7337 | memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len); | ||
7338 | memcpy(list + prefix_len, name, name_len); | ||
7339 | list[prefix_len + name_len] = '\0'; | ||
7340 | } | ||
7341 | return total_len; | ||
7342 | } | ||
7343 | |||
7344 | static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler, | 7323 | static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler, |
7345 | struct dentry *dentry, const char *name, | 7324 | struct dentry *dentry, const char *name, |
7346 | void *buffer, size_t size) | 7325 | void *buffer, size_t size) |
7347 | { | 7326 | { |
7348 | if (strcmp(name, "") == 0) | ||
7349 | return -EINVAL; | ||
7350 | return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED, | 7327 | return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED, |
7351 | name, buffer, size); | 7328 | name, buffer, size); |
7352 | } | 7329 | } |
@@ -7355,16 +7332,12 @@ static int ocfs2_xattr_trusted_set(const struct xattr_handler *handler, | |||
7355 | struct dentry *dentry, const char *name, | 7332 | struct dentry *dentry, const char *name, |
7356 | const void *value, size_t size, int flags) | 7333 | const void *value, size_t size, int flags) |
7357 | { | 7334 | { |
7358 | if (strcmp(name, "") == 0) | ||
7359 | return -EINVAL; | ||
7360 | |||
7361 | return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED, | 7335 | return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED, |
7362 | name, value, size, flags); | 7336 | name, value, size, flags); |
7363 | } | 7337 | } |
7364 | 7338 | ||
7365 | const struct xattr_handler ocfs2_xattr_trusted_handler = { | 7339 | const struct xattr_handler ocfs2_xattr_trusted_handler = { |
7366 | .prefix = XATTR_TRUSTED_PREFIX, | 7340 | .prefix = XATTR_TRUSTED_PREFIX, |
7367 | .list = ocfs2_xattr_trusted_list, | ||
7368 | .get = ocfs2_xattr_trusted_get, | 7341 | .get = ocfs2_xattr_trusted_get, |
7369 | .set = ocfs2_xattr_trusted_set, | 7342 | .set = ocfs2_xattr_trusted_set, |
7370 | }; | 7343 | }; |
@@ -7372,34 +7345,12 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = { | |||
7372 | /* | 7345 | /* |
7373 | * 'user' attributes support | 7346 | * 'user' attributes support |
7374 | */ | 7347 | */ |
7375 | static size_t ocfs2_xattr_user_list(const struct xattr_handler *handler, | ||
7376 | struct dentry *dentry, char *list, | ||
7377 | size_t list_size, const char *name, | ||
7378 | size_t name_len) | ||
7379 | { | ||
7380 | const size_t prefix_len = XATTR_USER_PREFIX_LEN; | ||
7381 | const size_t total_len = prefix_len + name_len + 1; | ||
7382 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); | ||
7383 | |||
7384 | if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) | ||
7385 | return 0; | ||
7386 | |||
7387 | if (list && total_len <= list_size) { | ||
7388 | memcpy(list, XATTR_USER_PREFIX, prefix_len); | ||
7389 | memcpy(list + prefix_len, name, name_len); | ||
7390 | list[prefix_len + name_len] = '\0'; | ||
7391 | } | ||
7392 | return total_len; | ||
7393 | } | ||
7394 | |||
7395 | static int ocfs2_xattr_user_get(const struct xattr_handler *handler, | 7348 | static int ocfs2_xattr_user_get(const struct xattr_handler *handler, |
7396 | struct dentry *dentry, const char *name, | 7349 | struct dentry *dentry, const char *name, |
7397 | void *buffer, size_t size) | 7350 | void *buffer, size_t size) |
7398 | { | 7351 | { |
7399 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); | 7352 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); |
7400 | 7353 | ||
7401 | if (strcmp(name, "") == 0) | ||
7402 | return -EINVAL; | ||
7403 | if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) | 7354 | if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) |
7404 | return -EOPNOTSUPP; | 7355 | return -EOPNOTSUPP; |
7405 | return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name, | 7356 | return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name, |
@@ -7412,8 +7363,6 @@ static int ocfs2_xattr_user_set(const struct xattr_handler *handler, | |||
7412 | { | 7363 | { |
7413 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); | 7364 | struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb); |
7414 | 7365 | ||
7415 | if (strcmp(name, "") == 0) | ||
7416 | return -EINVAL; | ||
7417 | if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) | 7366 | if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR) |
7418 | return -EOPNOTSUPP; | 7367 | return -EOPNOTSUPP; |
7419 | 7368 | ||
@@ -7423,7 +7372,6 @@ static int ocfs2_xattr_user_set(const struct xattr_handler *handler, | |||
7423 | 7372 | ||
7424 | const struct xattr_handler ocfs2_xattr_user_handler = { | 7373 | const struct xattr_handler ocfs2_xattr_user_handler = { |
7425 | .prefix = XATTR_USER_PREFIX, | 7374 | .prefix = XATTR_USER_PREFIX, |
7426 | .list = ocfs2_xattr_user_list, | ||
7427 | .get = ocfs2_xattr_user_get, | 7375 | .get = ocfs2_xattr_user_get, |
7428 | .set = ocfs2_xattr_user_set, | 7376 | .set = ocfs2_xattr_user_set, |
7429 | }; | 7377 | }; |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 4adde1e2cbec..711dd5170376 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -769,8 +769,6 @@ posix_acl_xattr_get(const struct xattr_handler *handler, | |||
769 | struct posix_acl *acl; | 769 | struct posix_acl *acl; |
770 | int error; | 770 | int error; |
771 | 771 | ||
772 | if (strcmp(name, "") != 0) | ||
773 | return -EINVAL; | ||
774 | if (!IS_POSIXACL(d_backing_inode(dentry))) | 772 | if (!IS_POSIXACL(d_backing_inode(dentry))) |
775 | return -EOPNOTSUPP; | 773 | return -EOPNOTSUPP; |
776 | if (d_is_symlink(dentry)) | 774 | if (d_is_symlink(dentry)) |
@@ -797,8 +795,6 @@ posix_acl_xattr_set(const struct xattr_handler *handler, | |||
797 | struct posix_acl *acl = NULL; | 795 | struct posix_acl *acl = NULL; |
798 | int ret; | 796 | int ret; |
799 | 797 | ||
800 | if (strcmp(name, "") != 0) | ||
801 | return -EINVAL; | ||
802 | if (!IS_POSIXACL(inode)) | 798 | if (!IS_POSIXACL(inode)) |
803 | return -EOPNOTSUPP; | 799 | return -EOPNOTSUPP; |
804 | if (!inode->i_op->set_acl) | 800 | if (!inode->i_op->set_acl) |
@@ -827,25 +823,14 @@ out: | |||
827 | return ret; | 823 | return ret; |
828 | } | 824 | } |
829 | 825 | ||
830 | static size_t | 826 | static bool |
831 | posix_acl_xattr_list(const struct xattr_handler *handler, | 827 | posix_acl_xattr_list(struct dentry *dentry) |
832 | struct dentry *dentry, char *list, size_t list_size, | ||
833 | const char *name, size_t name_len) | ||
834 | { | 828 | { |
835 | const char *xname = handler->prefix; | 829 | return IS_POSIXACL(d_backing_inode(dentry)); |
836 | size_t size; | ||
837 | |||
838 | if (!IS_POSIXACL(d_backing_inode(dentry))) | ||
839 | return 0; | ||
840 | |||
841 | size = strlen(xname) + 1; | ||
842 | if (list && size <= list_size) | ||
843 | memcpy(list, xname, size); | ||
844 | return size; | ||
845 | } | 830 | } |
846 | 831 | ||
847 | const struct xattr_handler posix_acl_access_xattr_handler = { | 832 | const struct xattr_handler posix_acl_access_xattr_handler = { |
848 | .prefix = POSIX_ACL_XATTR_ACCESS, | 833 | .name = XATTR_NAME_POSIX_ACL_ACCESS, |
849 | .flags = ACL_TYPE_ACCESS, | 834 | .flags = ACL_TYPE_ACCESS, |
850 | .list = posix_acl_xattr_list, | 835 | .list = posix_acl_xattr_list, |
851 | .get = posix_acl_xattr_get, | 836 | .get = posix_acl_xattr_get, |
@@ -854,7 +839,7 @@ const struct xattr_handler posix_acl_access_xattr_handler = { | |||
854 | EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler); | 839 | EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler); |
855 | 840 | ||
856 | const struct xattr_handler posix_acl_default_xattr_handler = { | 841 | const struct xattr_handler posix_acl_default_xattr_handler = { |
857 | .prefix = POSIX_ACL_XATTR_DEFAULT, | 842 | .name = XATTR_NAME_POSIX_ACL_DEFAULT, |
858 | .flags = ACL_TYPE_DEFAULT, | 843 | .flags = ACL_TYPE_DEFAULT, |
859 | .list = posix_acl_xattr_list, | 844 | .list = posix_acl_xattr_list, |
860 | .get = posix_acl_xattr_get, | 845 | .get = posix_acl_xattr_get, |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 66b26fdfff8d..e5ddb4e5ea94 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -756,7 +756,8 @@ find_xattr_handler_prefix(const struct xattr_handler **handlers, | |||
756 | return NULL; | 756 | return NULL; |
757 | 757 | ||
758 | for_each_xattr_handler(handlers, xah) { | 758 | for_each_xattr_handler(handlers, xah) { |
759 | if (strncmp(xah->prefix, name, strlen(xah->prefix)) == 0) | 759 | const char *prefix = xattr_prefix(xah); |
760 | if (strncmp(prefix, name, strlen(prefix)) == 0) | ||
760 | break; | 761 | break; |
761 | } | 762 | } |
762 | 763 | ||
@@ -839,19 +840,16 @@ static int listxattr_filler(struct dir_context *ctx, const char *name, | |||
839 | 840 | ||
840 | handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr, | 841 | handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr, |
841 | name); | 842 | name); |
842 | if (!handler) /* Unsupported xattr name */ | 843 | if (!handler /* Unsupported xattr name */ || |
844 | (handler->list && !handler->list(b->dentry))) | ||
843 | return 0; | 845 | return 0; |
846 | size = namelen + 1; | ||
844 | if (b->buf) { | 847 | if (b->buf) { |
845 | size = handler->list(handler, b->dentry, | ||
846 | b->buf + b->pos, b->size, name, | ||
847 | namelen); | ||
848 | if (size > b->size) | 848 | if (size > b->size) |
849 | return -ERANGE; | 849 | return -ERANGE; |
850 | } else { | 850 | memcpy(b->buf + b->pos, name, namelen); |
851 | size = handler->list(handler, b->dentry, | 851 | b->buf[b->pos + namelen] = 0; |
852 | NULL, 0, name, namelen); | ||
853 | } | 852 | } |
854 | |||
855 | b->pos += size; | 853 | b->pos += size; |
856 | } | 854 | } |
857 | return 0; | 855 | return 0; |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 4b34b9dc03dd..558a16beaacb 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
@@ -186,10 +186,10 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type) | |||
186 | 186 | ||
187 | switch (type) { | 187 | switch (type) { |
188 | case ACL_TYPE_ACCESS: | 188 | case ACL_TYPE_ACCESS: |
189 | name = POSIX_ACL_XATTR_ACCESS; | 189 | name = XATTR_NAME_POSIX_ACL_ACCESS; |
190 | break; | 190 | break; |
191 | case ACL_TYPE_DEFAULT: | 191 | case ACL_TYPE_DEFAULT: |
192 | name = POSIX_ACL_XATTR_DEFAULT; | 192 | name = XATTR_NAME_POSIX_ACL_DEFAULT; |
193 | break; | 193 | break; |
194 | default: | 194 | default: |
195 | BUG(); | 195 | BUG(); |
@@ -244,7 +244,7 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, | |||
244 | 244 | ||
245 | switch (type) { | 245 | switch (type) { |
246 | case ACL_TYPE_ACCESS: | 246 | case ACL_TYPE_ACCESS: |
247 | name = POSIX_ACL_XATTR_ACCESS; | 247 | name = XATTR_NAME_POSIX_ACL_ACCESS; |
248 | if (acl) { | 248 | if (acl) { |
249 | error = posix_acl_equiv_mode(acl, &inode->i_mode); | 249 | error = posix_acl_equiv_mode(acl, &inode->i_mode); |
250 | if (error < 0) | 250 | if (error < 0) |
@@ -256,7 +256,7 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode, | |||
256 | } | 256 | } |
257 | break; | 257 | break; |
258 | case ACL_TYPE_DEFAULT: | 258 | case ACL_TYPE_DEFAULT: |
259 | name = POSIX_ACL_XATTR_DEFAULT; | 259 | name = XATTR_NAME_POSIX_ACL_DEFAULT; |
260 | if (!S_ISDIR(inode->i_mode)) | 260 | if (!S_ISDIR(inode->i_mode)) |
261 | return acl ? -EACCES : 0; | 261 | return acl ? -EACCES : 0; |
262 | break; | 262 | break; |
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index ac659af431ae..ab0217d32039 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c | |||
@@ -34,21 +34,9 @@ security_set(const struct xattr_handler *handler, struct dentry *dentry, | |||
34 | return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); | 34 | return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); |
35 | } | 35 | } |
36 | 36 | ||
37 | static size_t security_list(const struct xattr_handler *handler, | 37 | static bool security_list(struct dentry *dentry) |
38 | struct dentry *dentry, char *list, size_t list_len, | ||
39 | const char *name, size_t namelen) | ||
40 | { | 38 | { |
41 | const size_t len = namelen + 1; | 39 | return !IS_PRIVATE(d_inode(dentry)); |
42 | |||
43 | if (IS_PRIVATE(d_inode(dentry))) | ||
44 | return 0; | ||
45 | |||
46 | if (list && len <= list_len) { | ||
47 | memcpy(list, name, namelen); | ||
48 | list[namelen] = '\0'; | ||
49 | } | ||
50 | |||
51 | return len; | ||
52 | } | 40 | } |
53 | 41 | ||
54 | /* Initializes the security context for a new inode and returns the number | 42 | /* Initializes the security context for a new inode and returns the number |
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c index a338adf1b8b4..64b67aa643a9 100644 --- a/fs/reiserfs/xattr_trusted.c +++ b/fs/reiserfs/xattr_trusted.c | |||
@@ -33,20 +33,9 @@ trusted_set(const struct xattr_handler *handler, struct dentry *dentry, | |||
33 | return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); | 33 | return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); |
34 | } | 34 | } |
35 | 35 | ||
36 | static size_t trusted_list(const struct xattr_handler *handler, | 36 | static bool trusted_list(struct dentry *dentry) |
37 | struct dentry *dentry, char *list, size_t list_size, | ||
38 | const char *name, size_t name_len) | ||
39 | { | 37 | { |
40 | const size_t len = name_len + 1; | 38 | return capable(CAP_SYS_ADMIN) && !IS_PRIVATE(d_inode(dentry)); |
41 | |||
42 | if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry))) | ||
43 | return 0; | ||
44 | |||
45 | if (list && len <= list_size) { | ||
46 | memcpy(list, name, name_len); | ||
47 | list[name_len] = '\0'; | ||
48 | } | ||
49 | return len; | ||
50 | } | 39 | } |
51 | 40 | ||
52 | const struct xattr_handler reiserfs_xattr_trusted_handler = { | 41 | const struct xattr_handler reiserfs_xattr_trusted_handler = { |
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c index 39c9667191c5..12e6306f562a 100644 --- a/fs/reiserfs/xattr_user.c +++ b/fs/reiserfs/xattr_user.c | |||
@@ -30,19 +30,9 @@ user_set(const struct xattr_handler *handler, struct dentry *dentry, | |||
30 | return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); | 30 | return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags); |
31 | } | 31 | } |
32 | 32 | ||
33 | static size_t user_list(const struct xattr_handler *handler, | 33 | static bool user_list(struct dentry *dentry) |
34 | struct dentry *dentry, char *list, size_t list_size, | ||
35 | const char *name, size_t name_len) | ||
36 | { | 34 | { |
37 | const size_t len = name_len + 1; | 35 | return reiserfs_xattrs_user(dentry->d_sb); |
38 | |||
39 | if (!reiserfs_xattrs_user(dentry->d_sb)) | ||
40 | return 0; | ||
41 | if (list && len <= list_size) { | ||
42 | memcpy(list, name, name_len); | ||
43 | list[name_len] = '\0'; | ||
44 | } | ||
45 | return len; | ||
46 | } | 36 | } |
47 | 37 | ||
48 | const struct xattr_handler reiserfs_xattr_user_handler = { | 38 | const struct xattr_handler reiserfs_xattr_user_handler = { |
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c index 6a4cc344085c..1e9de96288d8 100644 --- a/fs/squashfs/xattr.c +++ b/fs/squashfs/xattr.c | |||
@@ -58,7 +58,7 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer, | |||
58 | struct squashfs_xattr_entry entry; | 58 | struct squashfs_xattr_entry entry; |
59 | struct squashfs_xattr_val val; | 59 | struct squashfs_xattr_val val; |
60 | const struct xattr_handler *handler; | 60 | const struct xattr_handler *handler; |
61 | int name_size, prefix_size = 0; | 61 | int name_size; |
62 | 62 | ||
63 | err = squashfs_read_metadata(sb, &entry, &start, &offset, | 63 | err = squashfs_read_metadata(sb, &entry, &start, &offset, |
64 | sizeof(entry)); | 64 | sizeof(entry)); |
@@ -67,15 +67,16 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer, | |||
67 | 67 | ||
68 | name_size = le16_to_cpu(entry.size); | 68 | name_size = le16_to_cpu(entry.size); |
69 | handler = squashfs_xattr_handler(le16_to_cpu(entry.type)); | 69 | handler = squashfs_xattr_handler(le16_to_cpu(entry.type)); |
70 | if (handler) | 70 | if (handler && (!handler->list || handler->list(d))) { |
71 | prefix_size = handler->list(handler, d, buffer, rest, | 71 | const char *prefix = handler->prefix ?: handler->name; |
72 | NULL, name_size); | 72 | size_t prefix_size = strlen(prefix); |
73 | if (prefix_size) { | 73 | |
74 | if (buffer) { | 74 | if (buffer) { |
75 | if (prefix_size + name_size + 1 > rest) { | 75 | if (prefix_size + name_size + 1 > rest) { |
76 | err = -ERANGE; | 76 | err = -ERANGE; |
77 | goto failed; | 77 | goto failed; |
78 | } | 78 | } |
79 | memcpy(buffer, prefix, prefix_size); | ||
79 | buffer += prefix_size; | 80 | buffer += prefix_size; |
80 | } | 81 | } |
81 | err = squashfs_read_metadata(sb, buffer, &start, | 82 | err = squashfs_read_metadata(sb, buffer, &start, |
@@ -212,25 +213,10 @@ failed: | |||
212 | } | 213 | } |
213 | 214 | ||
214 | 215 | ||
215 | static size_t squashfs_xattr_handler_list(const struct xattr_handler *handler, | ||
216 | struct dentry *d, char *list, | ||
217 | size_t list_size, const char *name, | ||
218 | size_t name_len) | ||
219 | { | ||
220 | int len = strlen(handler->prefix); | ||
221 | |||
222 | if (list && len <= list_size) | ||
223 | memcpy(list, handler->prefix, len); | ||
224 | return len; | ||
225 | } | ||
226 | |||
227 | static int squashfs_xattr_handler_get(const struct xattr_handler *handler, | 216 | static int squashfs_xattr_handler_get(const struct xattr_handler *handler, |
228 | struct dentry *d, const char *name, | 217 | struct dentry *d, const char *name, |
229 | void *buffer, size_t size) | 218 | void *buffer, size_t size) |
230 | { | 219 | { |
231 | if (name[0] == '\0') | ||
232 | return -EINVAL; | ||
233 | |||
234 | return squashfs_xattr_get(d_inode(d), handler->flags, name, | 220 | return squashfs_xattr_get(d_inode(d), handler->flags, name, |
235 | buffer, size); | 221 | buffer, size); |
236 | } | 222 | } |
@@ -241,22 +227,15 @@ static int squashfs_xattr_handler_get(const struct xattr_handler *handler, | |||
241 | static const struct xattr_handler squashfs_xattr_user_handler = { | 227 | static const struct xattr_handler squashfs_xattr_user_handler = { |
242 | .prefix = XATTR_USER_PREFIX, | 228 | .prefix = XATTR_USER_PREFIX, |
243 | .flags = SQUASHFS_XATTR_USER, | 229 | .flags = SQUASHFS_XATTR_USER, |
244 | .list = squashfs_xattr_handler_list, | ||
245 | .get = squashfs_xattr_handler_get | 230 | .get = squashfs_xattr_handler_get |
246 | }; | 231 | }; |
247 | 232 | ||
248 | /* | 233 | /* |
249 | * Trusted namespace support | 234 | * Trusted namespace support |
250 | */ | 235 | */ |
251 | static size_t squashfs_trusted_xattr_handler_list(const struct xattr_handler *handler, | 236 | static bool squashfs_trusted_xattr_handler_list(struct dentry *d) |
252 | struct dentry *d, char *list, | ||
253 | size_t list_size, const char *name, | ||
254 | size_t name_len) | ||
255 | { | 237 | { |
256 | if (!capable(CAP_SYS_ADMIN)) | 238 | return capable(CAP_SYS_ADMIN); |
257 | return 0; | ||
258 | return squashfs_xattr_handler_list(handler, d, list, list_size, name, | ||
259 | name_len); | ||
260 | } | 239 | } |
261 | 240 | ||
262 | static const struct xattr_handler squashfs_xattr_trusted_handler = { | 241 | static const struct xattr_handler squashfs_xattr_trusted_handler = { |
@@ -272,7 +251,6 @@ static const struct xattr_handler squashfs_xattr_trusted_handler = { | |||
272 | static const struct xattr_handler squashfs_xattr_security_handler = { | 251 | static const struct xattr_handler squashfs_xattr_security_handler = { |
273 | .prefix = XATTR_SECURITY_PREFIX, | 252 | .prefix = XATTR_SECURITY_PREFIX, |
274 | .flags = SQUASHFS_XATTR_SECURITY, | 253 | .flags = SQUASHFS_XATTR_SECURITY, |
275 | .list = squashfs_xattr_handler_list, | ||
276 | .get = squashfs_xattr_handler_get | 254 | .get = squashfs_xattr_handler_get |
277 | }; | 255 | }; |
278 | 256 | ||
diff --git a/fs/xattr.c b/fs/xattr.c index 9b932b95d74e..d7f5037a17b5 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -208,25 +208,6 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, | |||
208 | return error; | 208 | return error; |
209 | } | 209 | } |
210 | 210 | ||
211 | /* Compare an extended attribute value with the given value */ | ||
212 | int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, | ||
213 | const char *value, size_t size, gfp_t flags) | ||
214 | { | ||
215 | char *xattr_value = NULL; | ||
216 | int rc; | ||
217 | |||
218 | rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags); | ||
219 | if (rc < 0) | ||
220 | return rc; | ||
221 | |||
222 | if ((rc != size) || (memcmp(xattr_value, value, rc) != 0)) | ||
223 | rc = -EINVAL; | ||
224 | else | ||
225 | rc = 0; | ||
226 | kfree(xattr_value); | ||
227 | return rc; | ||
228 | } | ||
229 | |||
230 | ssize_t | 211 | ssize_t |
231 | vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) | 212 | vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) |
232 | { | 213 | { |
@@ -700,13 +681,20 @@ xattr_resolve_name(const struct xattr_handler **handlers, const char **name) | |||
700 | return NULL; | 681 | return NULL; |
701 | 682 | ||
702 | for_each_xattr_handler(handlers, handler) { | 683 | for_each_xattr_handler(handlers, handler) { |
703 | const char *n = strcmp_prefix(*name, handler->prefix); | 684 | const char *n; |
685 | |||
686 | n = strcmp_prefix(*name, xattr_prefix(handler)); | ||
704 | if (n) { | 687 | if (n) { |
688 | if (!handler->prefix ^ !*n) { | ||
689 | if (*n) | ||
690 | continue; | ||
691 | return ERR_PTR(-EINVAL); | ||
692 | } | ||
705 | *name = n; | 693 | *name = n; |
706 | break; | 694 | return handler; |
707 | } | 695 | } |
708 | } | 696 | } |
709 | return handler; | 697 | return ERR_PTR(-EOPNOTSUPP); |
710 | } | 698 | } |
711 | 699 | ||
712 | /* | 700 | /* |
@@ -718,8 +706,8 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s | |||
718 | const struct xattr_handler *handler; | 706 | const struct xattr_handler *handler; |
719 | 707 | ||
720 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); | 708 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); |
721 | if (!handler) | 709 | if (IS_ERR(handler)) |
722 | return -EOPNOTSUPP; | 710 | return PTR_ERR(handler); |
723 | return handler->get(handler, dentry, name, buffer, size); | 711 | return handler->get(handler, dentry, name, buffer, size); |
724 | } | 712 | } |
725 | 713 | ||
@@ -735,19 +723,25 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
735 | 723 | ||
736 | if (!buffer) { | 724 | if (!buffer) { |
737 | for_each_xattr_handler(handlers, handler) { | 725 | for_each_xattr_handler(handlers, handler) { |
738 | size += handler->list(handler, dentry, NULL, 0, | 726 | if (!handler->name || |
739 | NULL, 0); | 727 | (handler->list && !handler->list(dentry))) |
728 | continue; | ||
729 | size += strlen(handler->name) + 1; | ||
740 | } | 730 | } |
741 | } else { | 731 | } else { |
742 | char *buf = buffer; | 732 | char *buf = buffer; |
733 | size_t len; | ||
743 | 734 | ||
744 | for_each_xattr_handler(handlers, handler) { | 735 | for_each_xattr_handler(handlers, handler) { |
745 | size = handler->list(handler, dentry, buf, buffer_size, | 736 | if (!handler->name || |
746 | NULL, 0); | 737 | (handler->list && !handler->list(dentry))) |
747 | if (size > buffer_size) | 738 | continue; |
739 | len = strlen(handler->name); | ||
740 | if (len + 1 > buffer_size) | ||
748 | return -ERANGE; | 741 | return -ERANGE; |
749 | buf += size; | 742 | memcpy(buf, handler->name, len + 1); |
750 | buffer_size -= size; | 743 | buf += len + 1; |
744 | buffer_size -= len + 1; | ||
751 | } | 745 | } |
752 | size = buf - buffer; | 746 | size = buf - buffer; |
753 | } | 747 | } |
@@ -765,8 +759,8 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz | |||
765 | if (size == 0) | 759 | if (size == 0) |
766 | value = ""; /* empty EA, do not remove */ | 760 | value = ""; /* empty EA, do not remove */ |
767 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); | 761 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); |
768 | if (!handler) | 762 | if (IS_ERR(handler)) |
769 | return -EOPNOTSUPP; | 763 | return PTR_ERR(handler); |
770 | return handler->set(handler, dentry, name, value, size, flags); | 764 | return handler->set(handler, dentry, name, value, size, flags); |
771 | } | 765 | } |
772 | 766 | ||
@@ -780,8 +774,8 @@ generic_removexattr(struct dentry *dentry, const char *name) | |||
780 | const struct xattr_handler *handler; | 774 | const struct xattr_handler *handler; |
781 | 775 | ||
782 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); | 776 | handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name); |
783 | if (!handler) | 777 | if (IS_ERR(handler)) |
784 | return -EOPNOTSUPP; | 778 | return PTR_ERR(handler); |
785 | return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE); | 779 | return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE); |
786 | } | 780 | } |
787 | 781 | ||
@@ -808,7 +802,7 @@ EXPORT_SYMBOL(generic_removexattr); | |||
808 | const char *xattr_full_name(const struct xattr_handler *handler, | 802 | const char *xattr_full_name(const struct xattr_handler *handler, |
809 | const char *name) | 803 | const char *name) |
810 | { | 804 | { |
811 | size_t prefix_len = strlen(handler->prefix); | 805 | size_t prefix_len = strlen(xattr_prefix(handler)); |
812 | 806 | ||
813 | return name - prefix_len; | 807 | return name - prefix_len; |
814 | } | 808 | } |
@@ -863,8 +857,22 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name, | |||
863 | return ret; | 857 | return ret; |
864 | } | 858 | } |
865 | 859 | ||
866 | static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name, | 860 | /** |
867 | const void *value, size_t size, int flags) | 861 | * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems |
862 | * @xattrs: target simple_xattr list | ||
863 | * @name: name of the extended attribute | ||
864 | * @value: value of the xattr. If %NULL, will remove the attribute. | ||
865 | * @size: size of the new xattr | ||
866 | * @flags: %XATTR_{CREATE|REPLACE} | ||
867 | * | ||
868 | * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails | ||
869 | * with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist; | ||
870 | * otherwise, fails with -ENODATA. | ||
871 | * | ||
872 | * Returns 0 on success, -errno on failure. | ||
873 | */ | ||
874 | int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, | ||
875 | const void *value, size_t size, int flags) | ||
868 | { | 876 | { |
869 | struct simple_xattr *xattr; | 877 | struct simple_xattr *xattr; |
870 | struct simple_xattr *new_xattr = NULL; | 878 | struct simple_xattr *new_xattr = NULL; |
@@ -914,73 +922,64 @@ out: | |||
914 | 922 | ||
915 | } | 923 | } |
916 | 924 | ||
917 | /** | 925 | static bool xattr_is_trusted(const char *name) |
918 | * simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems | ||
919 | * @xattrs: target simple_xattr list | ||
920 | * @name: name of the new extended attribute | ||
921 | * @value: value of the new xattr. If %NULL, will remove the attribute | ||
922 | * @size: size of the new xattr | ||
923 | * @flags: %XATTR_{CREATE|REPLACE} | ||
924 | * | ||
925 | * %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails | ||
926 | * with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist; | ||
927 | * otherwise, fails with -ENODATA. | ||
928 | * | ||
929 | * Returns 0 on success, -errno on failure. | ||
930 | */ | ||
931 | int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, | ||
932 | const void *value, size_t size, int flags) | ||
933 | { | ||
934 | if (size == 0) | ||
935 | value = ""; /* empty EA, do not remove */ | ||
936 | return __simple_xattr_set(xattrs, name, value, size, flags); | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * xattr REMOVE operation for in-memory/pseudo filesystems | ||
941 | */ | ||
942 | int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name) | ||
943 | { | 926 | { |
944 | return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE); | 927 | return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); |
945 | } | 928 | } |
946 | 929 | ||
947 | static bool xattr_is_trusted(const char *name) | 930 | static int xattr_list_one(char **buffer, ssize_t *remaining_size, |
931 | const char *name) | ||
948 | { | 932 | { |
949 | return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); | 933 | size_t len = strlen(name) + 1; |
934 | if (*buffer) { | ||
935 | if (*remaining_size < len) | ||
936 | return -ERANGE; | ||
937 | memcpy(*buffer, name, len); | ||
938 | *buffer += len; | ||
939 | } | ||
940 | *remaining_size -= len; | ||
941 | return 0; | ||
950 | } | 942 | } |
951 | 943 | ||
952 | /* | 944 | /* |
953 | * xattr LIST operation for in-memory/pseudo filesystems | 945 | * xattr LIST operation for in-memory/pseudo filesystems |
954 | */ | 946 | */ |
955 | ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer, | 947 | ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, |
956 | size_t size) | 948 | char *buffer, size_t size) |
957 | { | 949 | { |
958 | bool trusted = capable(CAP_SYS_ADMIN); | 950 | bool trusted = capable(CAP_SYS_ADMIN); |
959 | struct simple_xattr *xattr; | 951 | struct simple_xattr *xattr; |
960 | size_t used = 0; | 952 | ssize_t remaining_size = size; |
953 | int err; | ||
954 | |||
955 | #ifdef CONFIG_FS_POSIX_ACL | ||
956 | if (inode->i_acl) { | ||
957 | err = xattr_list_one(&buffer, &remaining_size, | ||
958 | XATTR_NAME_POSIX_ACL_ACCESS); | ||
959 | if (err) | ||
960 | return err; | ||
961 | } | ||
962 | if (inode->i_default_acl) { | ||
963 | err = xattr_list_one(&buffer, &remaining_size, | ||
964 | XATTR_NAME_POSIX_ACL_DEFAULT); | ||
965 | if (err) | ||
966 | return err; | ||
967 | } | ||
968 | #endif | ||
961 | 969 | ||
962 | spin_lock(&xattrs->lock); | 970 | spin_lock(&xattrs->lock); |
963 | list_for_each_entry(xattr, &xattrs->head, list) { | 971 | list_for_each_entry(xattr, &xattrs->head, list) { |
964 | size_t len; | ||
965 | |||
966 | /* skip "trusted." attributes for unprivileged callers */ | 972 | /* skip "trusted." attributes for unprivileged callers */ |
967 | if (!trusted && xattr_is_trusted(xattr->name)) | 973 | if (!trusted && xattr_is_trusted(xattr->name)) |
968 | continue; | 974 | continue; |
969 | 975 | ||
970 | len = strlen(xattr->name) + 1; | 976 | err = xattr_list_one(&buffer, &remaining_size, xattr->name); |
971 | used += len; | 977 | if (err) |
972 | if (buffer) { | 978 | return err; |
973 | if (size < used) { | ||
974 | used = -ERANGE; | ||
975 | break; | ||
976 | } | ||
977 | memcpy(buffer, xattr->name, len); | ||
978 | buffer += len; | ||
979 | } | ||
980 | } | 979 | } |
981 | spin_unlock(&xattrs->lock); | 980 | spin_unlock(&xattrs->lock); |
982 | 981 | ||
983 | return used; | 982 | return size - remaining_size; |
984 | } | 983 | } |
985 | 984 | ||
986 | /* | 985 | /* |
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 6bb470fbb8e8..2d5df1f23bbc 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c | |||
@@ -252,29 +252,6 @@ xfs_set_mode(struct inode *inode, umode_t mode) | |||
252 | return error; | 252 | return error; |
253 | } | 253 | } |
254 | 254 | ||
255 | static int | ||
256 | xfs_acl_exists(struct inode *inode, unsigned char *name) | ||
257 | { | ||
258 | int len = XFS_ACL_MAX_SIZE(XFS_M(inode->i_sb)); | ||
259 | |||
260 | return (xfs_attr_get(XFS_I(inode), name, NULL, &len, | ||
261 | ATTR_ROOT|ATTR_KERNOVAL) == 0); | ||
262 | } | ||
263 | |||
264 | int | ||
265 | posix_acl_access_exists(struct inode *inode) | ||
266 | { | ||
267 | return xfs_acl_exists(inode, SGI_ACL_FILE); | ||
268 | } | ||
269 | |||
270 | int | ||
271 | posix_acl_default_exists(struct inode *inode) | ||
272 | { | ||
273 | if (!S_ISDIR(inode->i_mode)) | ||
274 | return 0; | ||
275 | return xfs_acl_exists(inode, SGI_ACL_DEFAULT); | ||
276 | } | ||
277 | |||
278 | int | 255 | int |
279 | xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) | 256 | xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) |
280 | { | 257 | { |
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 52f8255d6bdf..286fa89217f5 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h | |||
@@ -24,16 +24,12 @@ struct posix_acl; | |||
24 | #ifdef CONFIG_XFS_POSIX_ACL | 24 | #ifdef CONFIG_XFS_POSIX_ACL |
25 | extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); | 25 | extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); |
26 | extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type); | 26 | extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type); |
27 | extern int posix_acl_access_exists(struct inode *inode); | ||
28 | extern int posix_acl_default_exists(struct inode *inode); | ||
29 | #else | 27 | #else |
30 | static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) | 28 | static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) |
31 | { | 29 | { |
32 | return NULL; | 30 | return NULL; |
33 | } | 31 | } |
34 | # define xfs_set_acl NULL | 32 | # define xfs_set_acl NULL |
35 | # define posix_acl_access_exists(inode) 0 | ||
36 | # define posix_acl_default_exists(inode) 0 | ||
37 | #endif /* CONFIG_XFS_POSIX_ACL */ | 33 | #endif /* CONFIG_XFS_POSIX_ACL */ |
38 | 34 | ||
39 | extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags); | 35 | extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags); |
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 839b35ca21c6..110f1d7d86b0 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c | |||
@@ -39,9 +39,6 @@ xfs_xattr_get(const struct xattr_handler *handler, struct dentry *dentry, | |||
39 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | 39 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); |
40 | int error, asize = size; | 40 | int error, asize = size; |
41 | 41 | ||
42 | if (strcmp(name, "") == 0) | ||
43 | return -EINVAL; | ||
44 | |||
45 | /* Convert Linux syscall to XFS internal ATTR flags */ | 42 | /* Convert Linux syscall to XFS internal ATTR flags */ |
46 | if (!size) { | 43 | if (!size) { |
47 | xflags |= ATTR_KERNOVAL; | 44 | xflags |= ATTR_KERNOVAL; |
@@ -84,9 +81,6 @@ xfs_xattr_set(const struct xattr_handler *handler, struct dentry *dentry, | |||
84 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); | 81 | struct xfs_inode *ip = XFS_I(d_inode(dentry)); |
85 | int error; | 82 | int error; |
86 | 83 | ||
87 | if (strcmp(name, "") == 0) | ||
88 | return -EINVAL; | ||
89 | |||
90 | /* Convert Linux syscall to XFS internal ATTR flags */ | 84 | /* Convert Linux syscall to XFS internal ATTR flags */ |
91 | if (flags & XATTR_CREATE) | 85 | if (flags & XATTR_CREATE) |
92 | xflags |= ATTR_CREATE; | 86 | xflags |= ATTR_CREATE; |
@@ -135,47 +129,19 @@ const struct xattr_handler *xfs_xattr_handlers[] = { | |||
135 | NULL | 129 | NULL |
136 | }; | 130 | }; |
137 | 131 | ||
138 | static unsigned int xfs_xattr_prefix_len(int flags) | ||
139 | { | ||
140 | if (flags & XFS_ATTR_SECURE) | ||
141 | return sizeof("security"); | ||
142 | else if (flags & XFS_ATTR_ROOT) | ||
143 | return sizeof("trusted"); | ||
144 | else | ||
145 | return sizeof("user"); | ||
146 | } | ||
147 | |||
148 | static const char *xfs_xattr_prefix(int flags) | ||
149 | { | ||
150 | if (flags & XFS_ATTR_SECURE) | ||
151 | return xfs_xattr_security_handler.prefix; | ||
152 | else if (flags & XFS_ATTR_ROOT) | ||
153 | return xfs_xattr_trusted_handler.prefix; | ||
154 | else | ||
155 | return xfs_xattr_user_handler.prefix; | ||
156 | } | ||
157 | |||
158 | static int | 132 | static int |
159 | xfs_xattr_put_listent( | 133 | __xfs_xattr_put_listent( |
160 | struct xfs_attr_list_context *context, | 134 | struct xfs_attr_list_context *context, |
161 | int flags, | 135 | char *prefix, |
162 | unsigned char *name, | 136 | int prefix_len, |
163 | int namelen, | 137 | unsigned char *name, |
164 | int valuelen, | 138 | int namelen) |
165 | unsigned char *value) | ||
166 | { | 139 | { |
167 | unsigned int prefix_len = xfs_xattr_prefix_len(flags); | ||
168 | char *offset; | 140 | char *offset; |
169 | int arraytop; | 141 | int arraytop; |
170 | 142 | ||
171 | ASSERT(context->count >= 0); | 143 | if (!context->alist) |
172 | 144 | goto compute_size; | |
173 | /* | ||
174 | * Only show root namespace entries if we are actually allowed to | ||
175 | * see them. | ||
176 | */ | ||
177 | if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN)) | ||
178 | return 0; | ||
179 | 145 | ||
180 | arraytop = context->count + prefix_len + namelen + 1; | 146 | arraytop = context->count + prefix_len + namelen + 1; |
181 | if (arraytop > context->firstu) { | 147 | if (arraytop > context->firstu) { |
@@ -183,17 +149,19 @@ xfs_xattr_put_listent( | |||
183 | return 1; | 149 | return 1; |
184 | } | 150 | } |
185 | offset = (char *)context->alist + context->count; | 151 | offset = (char *)context->alist + context->count; |
186 | strncpy(offset, xfs_xattr_prefix(flags), prefix_len); | 152 | strncpy(offset, prefix, prefix_len); |
187 | offset += prefix_len; | 153 | offset += prefix_len; |
188 | strncpy(offset, (char *)name, namelen); /* real name */ | 154 | strncpy(offset, (char *)name, namelen); /* real name */ |
189 | offset += namelen; | 155 | offset += namelen; |
190 | *offset = '\0'; | 156 | *offset = '\0'; |
157 | |||
158 | compute_size: | ||
191 | context->count += prefix_len + namelen + 1; | 159 | context->count += prefix_len + namelen + 1; |
192 | return 0; | 160 | return 0; |
193 | } | 161 | } |
194 | 162 | ||
195 | static int | 163 | static int |
196 | xfs_xattr_put_listent_sizes( | 164 | xfs_xattr_put_listent( |
197 | struct xfs_attr_list_context *context, | 165 | struct xfs_attr_list_context *context, |
198 | int flags, | 166 | int flags, |
199 | unsigned char *name, | 167 | unsigned char *name, |
@@ -201,24 +169,55 @@ xfs_xattr_put_listent_sizes( | |||
201 | int valuelen, | 169 | int valuelen, |
202 | unsigned char *value) | 170 | unsigned char *value) |
203 | { | 171 | { |
204 | context->count += xfs_xattr_prefix_len(flags) + namelen + 1; | 172 | char *prefix; |
205 | return 0; | 173 | int prefix_len; |
206 | } | ||
207 | 174 | ||
208 | static int | 175 | ASSERT(context->count >= 0); |
209 | list_one_attr(const char *name, const size_t len, void *data, | ||
210 | size_t size, ssize_t *result) | ||
211 | { | ||
212 | char *p = data + *result; | ||
213 | 176 | ||
214 | *result += len; | 177 | if (flags & XFS_ATTR_ROOT) { |
215 | if (!size) | 178 | #ifdef CONFIG_XFS_POSIX_ACL |
216 | return 0; | 179 | if (namelen == SGI_ACL_FILE_SIZE && |
217 | if (*result > size) | 180 | strncmp(name, SGI_ACL_FILE, |
218 | return -ERANGE; | 181 | SGI_ACL_FILE_SIZE) == 0) { |
182 | int ret = __xfs_xattr_put_listent( | ||
183 | context, XATTR_SYSTEM_PREFIX, | ||
184 | XATTR_SYSTEM_PREFIX_LEN, | ||
185 | XATTR_POSIX_ACL_ACCESS, | ||
186 | strlen(XATTR_POSIX_ACL_ACCESS)); | ||
187 | if (ret) | ||
188 | return ret; | ||
189 | } else if (namelen == SGI_ACL_DEFAULT_SIZE && | ||
190 | strncmp(name, SGI_ACL_DEFAULT, | ||
191 | SGI_ACL_DEFAULT_SIZE) == 0) { | ||
192 | int ret = __xfs_xattr_put_listent( | ||
193 | context, XATTR_SYSTEM_PREFIX, | ||
194 | XATTR_SYSTEM_PREFIX_LEN, | ||
195 | XATTR_POSIX_ACL_DEFAULT, | ||
196 | strlen(XATTR_POSIX_ACL_DEFAULT)); | ||
197 | if (ret) | ||
198 | return ret; | ||
199 | } | ||
200 | #endif | ||
219 | 201 | ||
220 | strcpy(p, name); | 202 | /* |
221 | return 0; | 203 | * Only show root namespace entries if we are actually allowed to |
204 | * see them. | ||
205 | */ | ||
206 | if (!capable(CAP_SYS_ADMIN)) | ||
207 | return 0; | ||
208 | |||
209 | prefix = XATTR_TRUSTED_PREFIX; | ||
210 | prefix_len = XATTR_TRUSTED_PREFIX_LEN; | ||
211 | } else if (flags & XFS_ATTR_SECURE) { | ||
212 | prefix = XATTR_SECURITY_PREFIX; | ||
213 | prefix_len = XATTR_SECURITY_PREFIX_LEN; | ||
214 | } else { | ||
215 | prefix = XATTR_USER_PREFIX; | ||
216 | prefix_len = XATTR_USER_PREFIX_LEN; | ||
217 | } | ||
218 | |||
219 | return __xfs_xattr_put_listent(context, prefix, prefix_len, name, | ||
220 | namelen); | ||
222 | } | 221 | } |
223 | 222 | ||
224 | ssize_t | 223 | ssize_t |
@@ -227,7 +226,6 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) | |||
227 | struct xfs_attr_list_context context; | 226 | struct xfs_attr_list_context context; |
228 | struct attrlist_cursor_kern cursor = { 0 }; | 227 | struct attrlist_cursor_kern cursor = { 0 }; |
229 | struct inode *inode = d_inode(dentry); | 228 | struct inode *inode = d_inode(dentry); |
230 | int error; | ||
231 | 229 | ||
232 | /* | 230 | /* |
233 | * First read the regular on-disk attributes. | 231 | * First read the regular on-disk attributes. |
@@ -236,37 +234,14 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) | |||
236 | context.dp = XFS_I(inode); | 234 | context.dp = XFS_I(inode); |
237 | context.cursor = &cursor; | 235 | context.cursor = &cursor; |
238 | context.resynch = 1; | 236 | context.resynch = 1; |
239 | context.alist = data; | 237 | context.alist = size ? data : NULL; |
240 | context.bufsize = size; | 238 | context.bufsize = size; |
241 | context.firstu = context.bufsize; | 239 | context.firstu = context.bufsize; |
242 | 240 | context.put_listent = xfs_xattr_put_listent; | |
243 | if (size) | ||
244 | context.put_listent = xfs_xattr_put_listent; | ||
245 | else | ||
246 | context.put_listent = xfs_xattr_put_listent_sizes; | ||
247 | 241 | ||
248 | xfs_attr_list_int(&context); | 242 | xfs_attr_list_int(&context); |
249 | if (context.count < 0) | 243 | if (context.count < 0) |
250 | return -ERANGE; | 244 | return -ERANGE; |
251 | 245 | ||
252 | /* | ||
253 | * Then add the two synthetic ACL attributes. | ||
254 | */ | ||
255 | if (posix_acl_access_exists(inode)) { | ||
256 | error = list_one_attr(POSIX_ACL_XATTR_ACCESS, | ||
257 | strlen(POSIX_ACL_XATTR_ACCESS) + 1, | ||
258 | data, size, &context.count); | ||
259 | if (error) | ||
260 | return error; | ||
261 | } | ||
262 | |||
263 | if (posix_acl_default_exists(inode)) { | ||
264 | error = list_one_attr(POSIX_ACL_XATTR_DEFAULT, | ||
265 | strlen(POSIX_ACL_XATTR_DEFAULT) + 1, | ||
266 | data, size, &context.count); | ||
267 | if (error) | ||
268 | return error; | ||
269 | } | ||
270 | |||
271 | return context.count; | 246 | return context.count; |
272 | } | 247 | } |