summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-11 16:32:10 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-11 16:32:10 -0500
commitddf1d6238dd13a3bd948e8fcb1109798ef0af49b (patch)
treedaa25447e4b791b2868a0338f872975ec480862b /fs
parent32fb378437a1d716e72a442237d7ead1f435ecf0 (diff)
parent764a5c6b1fa4306dd7573c1d80914254909cd036 (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')
-rw-r--r--fs/9p/acl.c24
-rw-r--r--fs/9p/xattr.c4
-rw-r--r--fs/btrfs/acl.c8
-rw-r--r--fs/btrfs/inode.c16
-rw-r--r--fs/btrfs/xattr.c166
-rw-r--r--fs/btrfs/xattr.h2
-rw-r--r--fs/ceph/acl.c16
-rw-r--r--fs/cifs/xattr.c16
-rw-r--r--fs/ext2/xattr.c15
-rw-r--r--fs/ext2/xattr_security.c21
-rw-r--r--fs/ext2/xattr_trusted.c23
-rw-r--r--fs/ext2/xattr_user.c23
-rw-r--r--fs/ext4/xattr.c17
-rw-r--r--fs/ext4/xattr_security.c22
-rw-r--r--fs/ext4/xattr_trusted.c23
-rw-r--r--fs/ext4/xattr_user.c23
-rw-r--r--fs/f2fs/xattr.c92
-rw-r--r--fs/f2fs/xattr.h2
-rw-r--r--fs/gfs2/acl.c4
-rw-r--r--fs/gfs2/acl.h2
-rw-r--r--fs/gfs2/xattr.c50
-rw-r--r--fs/gfs2/xattr.h1
-rw-r--r--fs/hfsplus/posix_acl.c8
-rw-r--r--fs/hfsplus/xattr.c12
-rw-r--r--fs/jffs2/security.c22
-rw-r--r--fs/jffs2/xattr.c26
-rw-r--r--fs/jffs2/xattr_trusted.c21
-rw-r--r--fs/jffs2/xattr_user.c20
-rw-r--r--fs/jfs/acl.c8
-rw-r--r--fs/kernfs/inode.c4
-rw-r--r--fs/nfs/nfs3acl.c4
-rw-r--r--fs/nfs/nfs4proc.c75
-rw-r--r--fs/ocfs2/xattr.c168
-rw-r--r--fs/posix_acl.c25
-rw-r--r--fs/reiserfs/xattr.c16
-rw-r--r--fs/reiserfs/xattr_acl.c8
-rw-r--r--fs/reiserfs/xattr_security.c16
-rw-r--r--fs/reiserfs/xattr_trusted.c15
-rw-r--r--fs/reiserfs/xattr_user.c14
-rw-r--r--fs/squashfs/xattr.c38
-rw-r--r--fs/xattr.c165
-rw-r--r--fs/xfs/xfs_acl.c23
-rw-r--r--fs/xfs/xfs_acl.h4
-rw-r--r--fs/xfs/xfs_xattr.c143
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);
325err_out: 319err_out:
@@ -328,14 +322,14 @@ err_out:
328} 322}
329 323
330const struct xattr_handler v9fs_xattr_acl_access_handler = { 324const 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
337const struct xattr_handler v9fs_xattr_acl_default_handler = { 331const 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/* 354static 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 */
358const 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 */
372static 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
400ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, 364static 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); 375static 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
384static 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
390static 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
396static 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
402static 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
408const 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
419int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, 420int 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
455int btrfs_removexattr(struct dentry *dentry, const char *name) 430int 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
487static int btrfs_initxattrs(struct inode *inode, 439static 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,
28extern int __btrfs_setxattr(struct btrfs_trans_handle *trans, 28extern 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);
31extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
32 void *buffer, size_t size);
33extern int btrfs_setxattr(struct dentry *dentry, const char *name, 31extern 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);
35extern int btrfs_removexattr(struct dentry *dentry, const char *name); 33extern 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
10static size_t
11ext2_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
26static int 10static int
27ext2_xattr_security_get(const struct xattr_handler *handler, 11ext2_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
72const struct xattr_handler ext2_xattr_security_handler = { 52const 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
11static size_t 11static bool
12ext2_xattr_trusted_list(const struct xattr_handler *handler, 12ext2_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
30static int 17static 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
13static size_t 13static bool
14ext2_xattr_user_list(const struct xattr_handler *handler, 14ext2_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
32static int 19static 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
422static int 427static 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
14static size_t
15ext4_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
31static int 14static int
32ext4_xattr_security_get(const struct xattr_handler *handler, 15ext4_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
80const struct xattr_handler ext4_xattr_security_handler = { 59const 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
15static size_t 15static bool
16ext4_xattr_trusted_list(const struct xattr_handler *handler, 16ext4_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
34static int 21static 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
14static size_t 14static bool
15ext4_xattr_user_list(const struct xattr_handler *handler, 15ext4_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
33static int 20static 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
28static 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
60static int f2fs_xattr_generic_get(const struct xattr_handler *handler, 28static 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
113static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler, 76static 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; 83static bool f2fs_xattr_trusted_list(struct dentry *dentry)
84{
85 return capable(CAP_SYS_ADMIN);
124} 86}
125 87
126static int f2fs_xattr_advise_get(const struct xattr_handler *handler, 88static 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,
183const struct xattr_handler f2fs_xattr_user_handler = { 140const 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 = {
191const struct xattr_handler f2fs_xattr_trusted_handler = { 148const 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
199const struct xattr_handler f2fs_xattr_advise_handler = { 156const 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 = {
207const struct xattr_handler f2fs_xattr_security_handler = { 163const 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
19extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type); 17extern 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
1241static 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
1259int 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
1290static int ea_dealloc_indirect(struct gfs2_inode *ip) 1240static 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
64extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data); 64extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data);
65extern 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
73static 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
88const struct xattr_handler jffs2_security_xattr_handler = { 67const 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
39static size_t jffs2_trusted_listxattr(const struct xattr_handler *handler, 35static 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
57const struct xattr_handler jffs2_trusted_xattr_handler = { 40const 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
39static 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
54const struct xattr_handler jffs2_user_xattr_handler = { 35const 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
211ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, 211ssize_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
236static inline void set_default_inode_attr(struct inode *inode, umode_t mode) 236static 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
6272static size_t nfs4_xattr_list_nfs4_acl(const struct xattr_handler *handler, 6266static 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
6288static inline int nfs4_server_supports_labels(struct nfs_server *server)
6289{
6290 return server->caps & NFS_CAP_SECURITY_LABEL;
6291}
6292 6272
6293static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler, 6273static 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
6313static size_t nfs4_xattr_list_nfs4_label(const struct xattr_handler *handler, 6293static ssize_t
6314 struct dentry *dentry, char *list, 6294nfs4_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
6328static const struct xattr_handler nfs4_xattr_nfs4_label_handler = { 6306static 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
6314static ssize_t
6315nfs4_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
8737ssize_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
8752static const struct inode_operations nfs4_dir_inode_operations = { 8755static 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
8836static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { 8839static 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
551static u32 ocfs2_xattr_name_hash(struct inode *inode, 550static 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
887static int ocfs2_xattr_list_entry(char *buffer, size_t size, 886static 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,
7226leave: 7245leave:
7227 return ret; 7246 return ret;
7228} 7247}
7248
7229/* 7249/*
7230 * 'security' attributes support 7250 * 'security' attributes support
7231 */ 7251 */
7232static 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
7248static int ocfs2_xattr_security_get(const struct xattr_handler *handler, 7252static 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
7315const struct xattr_handler ocfs2_xattr_security_handler = { 7314const 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 */
7325static 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
7344static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler, 7323static 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
7365const struct xattr_handler ocfs2_xattr_trusted_handler = { 7339const 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 */
7375static 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
7395static int ocfs2_xattr_user_get(const struct xattr_handler *handler, 7348static 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
7424const struct xattr_handler ocfs2_xattr_user_handler = { 7373const 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
830static size_t 826static bool
831posix_acl_xattr_list(const struct xattr_handler *handler, 827posix_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
847const struct xattr_handler posix_acl_access_xattr_handler = { 832const 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 = {
854EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler); 839EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
855 840
856const struct xattr_handler posix_acl_default_xattr_handler = { 841const 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
37static size_t security_list(const struct xattr_handler *handler, 37static 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
36static size_t trusted_list(const struct xattr_handler *handler, 36static 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
52const struct xattr_handler reiserfs_xattr_trusted_handler = { 41const 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
33static size_t user_list(const struct xattr_handler *handler, 33static 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
48const struct xattr_handler reiserfs_xattr_user_handler = { 38const 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
215static 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
227static int squashfs_xattr_handler_get(const struct xattr_handler *handler, 216static 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,
241static const struct xattr_handler squashfs_xattr_user_handler = { 227static 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 */
251static size_t squashfs_trusted_xattr_handler_list(const struct xattr_handler *handler, 236static 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
262static const struct xattr_handler squashfs_xattr_trusted_handler = { 241static const struct xattr_handler squashfs_xattr_trusted_handler = {
@@ -272,7 +251,6 @@ static const struct xattr_handler squashfs_xattr_trusted_handler = {
272static const struct xattr_handler squashfs_xattr_security_handler = { 251static 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 */
212int 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
230ssize_t 211ssize_t
231vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) 212vfs_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);
808const char *xattr_full_name(const struct xattr_handler *handler, 802const 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
866static 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 */
874int 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/** 925static 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 */
931int 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 */
942int 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
947static bool xattr_is_trusted(const char *name) 930static 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 */
955ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer, 947ssize_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
255static int
256xfs_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
264int
265posix_acl_access_exists(struct inode *inode)
266{
267 return xfs_acl_exists(inode, SGI_ACL_FILE);
268}
269
270int
271posix_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
278int 255int
279xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 256xfs_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
25extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); 25extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
26extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type); 26extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
27extern int posix_acl_access_exists(struct inode *inode);
28extern int posix_acl_default_exists(struct inode *inode);
29#else 27#else
30static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) 28static 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
39extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags); 35extern 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
138static 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
148static 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
158static int 132static int
159xfs_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
158compute_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
195static int 163static int
196xfs_xattr_put_listent_sizes( 164xfs_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
208static int 175 ASSERT(context->count >= 0);
209list_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
224ssize_t 223ssize_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}