summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2015-12-02 08:44:43 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-12-13 19:46:12 -0500
commit764a5c6b1fa4306dd7573c1d80914254909cd036 (patch)
tree6e5ceb636c3b53cdc0994cf8c2415656e2b12e82
parent1046cb119521b5e1881f380dc99729fc84c96661 (diff)
xattr handlers: Simplify list operation
Change the list operation to only return whether or not an attribute should be listed. Copying the attribute names into the buffer is moved to the callers. Since the result only depends on the dentry and not on the attribute name, we do not pass the attribute name to list operations. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/ext2/xattr.c15
-rw-r--r--fs/ext2/xattr_security.c17
-rw-r--r--fs/ext2/xattr_trusted.c19
-rw-r--r--fs/ext2/xattr_user.c19
-rw-r--r--fs/ext4/xattr.c17
-rw-r--r--fs/ext4/xattr_security.c18
-rw-r--r--fs/ext4/xattr_trusted.c19
-rw-r--r--fs/ext4/xattr_user.c19
-rw-r--r--fs/f2fs/xattr.c82
-rw-r--r--fs/jffs2/security.c16
-rw-r--r--fs/jffs2/xattr.c26
-rw-r--r--fs/jffs2/xattr_trusted.c17
-rw-r--r--fs/jffs2/xattr_user.c16
-rw-r--r--fs/nfs/nfs4proc.c14
-rw-r--r--fs/posix_acl.c17
-rw-r--r--fs/reiserfs/xattr.c13
-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.c35
-rw-r--r--fs/xattr.c20
-rw-r--r--include/linux/xattr.h4
22 files changed, 113 insertions, 335 deletions
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 118bf231bc7f..ba97f243b050 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -7,22 +7,6 @@
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,
@@ -67,7 +51,6 @@ ext2_init_security(struct inode *inode, struct inode *dir,
67 51
68const struct xattr_handler ext2_xattr_security_handler = { 52const struct xattr_handler ext2_xattr_security_handler = {
69 .prefix = XATTR_SECURITY_PREFIX, 53 .prefix = XATTR_SECURITY_PREFIX,
70 .list = ext2_xattr_security_list,
71 .get = ext2_xattr_security_get, 54 .get = ext2_xattr_security_get,
72 .set = ext2_xattr_security_set, 55 .set = ext2_xattr_security_set,
73}; 56};
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 3f8f2bc6539e..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
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index afd45ab1218c..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
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 195abc4a88bb..3e81bdca071a 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -11,23 +11,6 @@
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,
@@ -75,7 +58,6 @@ ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
75 58
76const struct xattr_handler ext4_xattr_security_handler = { 59const struct xattr_handler ext4_xattr_security_handler = {
77 .prefix = XATTR_SECURITY_PREFIX, 60 .prefix = XATTR_SECURITY_PREFIX,
78 .list = ext4_xattr_security_list,
79 .get = ext4_xattr_security_get, 61 .get = ext4_xattr_security_get,
80 .set = ext4_xattr_security_set, 62 .set = ext4_xattr_security_set,
81}; 63};
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
index 121fdf9fdc02..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
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
index 577fc122d884..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
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 21cfe516034f..036952a945fa 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -25,40 +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 const char *prefix;
34 int total_len, prefix_len;
35
36 switch (handler->flags) {
37 case F2FS_XATTR_INDEX_USER:
38 if (!test_opt(sbi, XATTR_USER))
39 return -EOPNOTSUPP;
40 break;
41 case F2FS_XATTR_INDEX_TRUSTED:
42 if (!capable(CAP_SYS_ADMIN))
43 return -EPERM;
44 break;
45 case F2FS_XATTR_INDEX_SECURITY:
46 break;
47 default:
48 return -EINVAL;
49 }
50
51 prefix = xattr_prefix(handler);
52 prefix_len = strlen(prefix);
53 total_len = prefix_len + len + 1;
54 if (list && total_len <= list_size) {
55 memcpy(list, prefix, prefix_len);
56 memcpy(list + prefix_len, name, len);
57 list[prefix_len + len] = '\0';
58 }
59 return total_len;
60}
61
62static int f2fs_xattr_generic_get(const struct xattr_handler *handler, 28static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
63 struct dentry *dentry, const char *name, void *buffer, 29 struct dentry *dentry, const char *name, void *buffer,
64 size_t size) 30 size_t size)
@@ -107,17 +73,16 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
107 value, size, NULL, flags); 73 value, size, NULL, flags);
108} 74}
109 75
110static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler, 76static bool f2fs_xattr_user_list(struct dentry *dentry)
111 struct dentry *dentry, char *list, size_t list_size,
112 const char *name, size_t len)
113{ 77{
114 const char *xname = F2FS_SYSTEM_ADVISE_NAME; 78 struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
115 size_t size; 79
80 return test_opt(sbi, XATTR_USER);
81}
116 82
117 size = strlen(xname) + 1; 83static bool f2fs_xattr_trusted_list(struct dentry *dentry)
118 if (list && size <= list_size) 84{
119 memcpy(list, xname, size); 85 return capable(CAP_SYS_ADMIN);
120 return size;
121} 86}
122 87
123static int f2fs_xattr_advise_get(const struct xattr_handler *handler, 88static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
@@ -175,7 +140,7 @@ int f2fs_init_security(struct inode *inode, struct inode *dir,
175const struct xattr_handler f2fs_xattr_user_handler = { 140const struct xattr_handler f2fs_xattr_user_handler = {
176 .prefix = XATTR_USER_PREFIX, 141 .prefix = XATTR_USER_PREFIX,
177 .flags = F2FS_XATTR_INDEX_USER, 142 .flags = F2FS_XATTR_INDEX_USER,
178 .list = f2fs_xattr_generic_list, 143 .list = f2fs_xattr_user_list,
179 .get = f2fs_xattr_generic_get, 144 .get = f2fs_xattr_generic_get,
180 .set = f2fs_xattr_generic_set, 145 .set = f2fs_xattr_generic_set,
181}; 146};
@@ -183,7 +148,7 @@ const struct xattr_handler f2fs_xattr_user_handler = {
183const struct xattr_handler f2fs_xattr_trusted_handler = { 148const struct xattr_handler f2fs_xattr_trusted_handler = {
184 .prefix = XATTR_TRUSTED_PREFIX, 149 .prefix = XATTR_TRUSTED_PREFIX,
185 .flags = F2FS_XATTR_INDEX_TRUSTED, 150 .flags = F2FS_XATTR_INDEX_TRUSTED,
186 .list = f2fs_xattr_generic_list, 151 .list = f2fs_xattr_trusted_list,
187 .get = f2fs_xattr_generic_get, 152 .get = f2fs_xattr_generic_get,
188 .set = f2fs_xattr_generic_set, 153 .set = f2fs_xattr_generic_set,
189}; 154};
@@ -191,7 +156,6 @@ const struct xattr_handler f2fs_xattr_trusted_handler = {
191const struct xattr_handler f2fs_xattr_advise_handler = { 156const struct xattr_handler f2fs_xattr_advise_handler = {
192 .name = F2FS_SYSTEM_ADVISE_NAME, 157 .name = F2FS_SYSTEM_ADVISE_NAME,
193 .flags = F2FS_XATTR_INDEX_ADVISE, 158 .flags = F2FS_XATTR_INDEX_ADVISE,
194 .list = f2fs_xattr_advise_list,
195 .get = f2fs_xattr_advise_get, 159 .get = f2fs_xattr_advise_get,
196 .set = f2fs_xattr_advise_set, 160 .set = f2fs_xattr_advise_set,
197}; 161};
@@ -199,7 +163,6 @@ const struct xattr_handler f2fs_xattr_advise_handler = {
199const struct xattr_handler f2fs_xattr_security_handler = { 163const struct xattr_handler f2fs_xattr_security_handler = {
200 .prefix = XATTR_SECURITY_PREFIX, 164 .prefix = XATTR_SECURITY_PREFIX,
201 .flags = F2FS_XATTR_INDEX_SECURITY, 165 .flags = F2FS_XATTR_INDEX_SECURITY,
202 .list = f2fs_xattr_generic_list,
203 .get = f2fs_xattr_generic_get, 166 .get = f2fs_xattr_generic_get,
204 .set = f2fs_xattr_generic_set, 167 .set = f2fs_xattr_generic_set,
205}; 168};
@@ -447,20 +410,27 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
447 list_for_each_xattr(entry, base_addr) { 410 list_for_each_xattr(entry, base_addr) {
448 const struct xattr_handler *handler = 411 const struct xattr_handler *handler =
449 f2fs_xattr_handler(entry->e_name_index); 412 f2fs_xattr_handler(entry->e_name_index);
413 const char *prefix;
414 size_t prefix_len;
450 size_t size; 415 size_t size;
451 416
452 if (!handler) 417 if (!handler || (handler->list && !handler->list(dentry)))
453 continue; 418 continue;
454 419
455 size = handler->list(handler, dentry, buffer, rest, 420 prefix = handler->prefix ?: handler->name;
456 entry->e_name, entry->e_name_len); 421 prefix_len = strlen(prefix);
457 if (buffer && size > rest) { 422 size = prefix_len + entry->e_name_len + 1;
458 error = -ERANGE; 423 if (buffer) {
459 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;
460 } 433 }
461
462 if (buffer)
463 buffer += size;
464 rest -= size; 434 rest -= size;
465 } 435 }
466 error = buffer_size - rest; 436 error = buffer_size - rest;
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index ea79932cd665..7a28facd7175 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -64,24 +64,8 @@ static int jffs2_security_setxattr(const struct xattr_handler *handler,
64 name, buffer, size, flags); 64 name, buffer, size, flags);
65} 65}
66 66
67static size_t jffs2_security_listxattr(const struct xattr_handler *handler,
68 struct dentry *dentry, char *list,
69 size_t list_size, const char *name,
70 size_t name_len)
71{
72 size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
73
74 if (list && retlen <= list_size) {
75 strcpy(list, XATTR_SECURITY_PREFIX);
76 strcpy(list + XATTR_SECURITY_PREFIX_LEN, name);
77 }
78
79 return retlen;
80}
81
82const struct xattr_handler jffs2_security_xattr_handler = { 67const struct xattr_handler jffs2_security_xattr_handler = {
83 .prefix = XATTR_SECURITY_PREFIX, 68 .prefix = XATTR_SECURITY_PREFIX,
84 .list = jffs2_security_listxattr,
85 .set = jffs2_security_setxattr, 69 .set = jffs2_security_setxattr,
86 .get = jffs2_security_getxattr 70 .get = jffs2_security_getxattr
87}; 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 8b55fe44c777..b2555ef07a12 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -32,22 +32,9 @@ static int jffs2_trusted_setxattr(const struct xattr_handler *handler,
32 name, buffer, size, flags); 32 name, buffer, size, flags);
33} 33}
34 34
35static size_t jffs2_trusted_listxattr(const struct xattr_handler *handler, 35static bool jffs2_trusted_listxattr(struct dentry *dentry)
36 struct dentry *dentry, char *list,
37 size_t list_size, const char *name,
38 size_t name_len)
39{ 36{
40 size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1; 37 return capable(CAP_SYS_ADMIN);
41
42 if (!capable(CAP_SYS_ADMIN))
43 return 0;
44
45 if (list && retlen<=list_size) {
46 strcpy(list, XATTR_TRUSTED_PREFIX);
47 strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
48 }
49
50 return retlen;
51} 38}
52 39
53const 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 b04335b84833..539bd630b5e4 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -32,24 +32,8 @@ static int jffs2_user_setxattr(const struct xattr_handler *handler,
32 name, buffer, size, flags); 32 name, buffer, size, flags);
33} 33}
34 34
35static size_t jffs2_user_listxattr(const struct xattr_handler *handler,
36 struct dentry *dentry, char *list,
37 size_t list_size, const char *name,
38 size_t name_len)
39{
40 size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
41
42 if (list && retlen <= list_size) {
43 strcpy(list, XATTR_USER_PREFIX);
44 strcpy(list + XATTR_USER_PREFIX_LEN, name);
45 }
46
47 return retlen;
48}
49
50const struct xattr_handler jffs2_user_xattr_handler = { 35const struct xattr_handler jffs2_user_xattr_handler = {
51 .prefix = XATTR_USER_PREFIX, 36 .prefix = XATTR_USER_PREFIX,
52 .list = jffs2_user_listxattr,
53 .set = jffs2_user_setxattr, 37 .set = jffs2_user_setxattr,
54 .get = jffs2_user_getxattr 38 .get = jffs2_user_getxattr
55}; 39};
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index dbfade2602c9..c57d1332c1c8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6263,19 +6263,9 @@ static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
6263 return nfs4_proc_get_acl(d_inode(dentry), buf, buflen); 6263 return nfs4_proc_get_acl(d_inode(dentry), buf, buflen);
6264} 6264}
6265 6265
6266static size_t nfs4_xattr_list_nfs4_acl(const struct xattr_handler *handler, 6266static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
6267 struct dentry *dentry, char *list,
6268 size_t list_len, const char *name,
6269 size_t name_len)
6270{ 6267{
6271 size_t len = sizeof(XATTR_NAME_NFSV4_ACL); 6268 return nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry)));
6272
6273 if (!nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry))))
6274 return 0;
6275
6276 if (list && len <= list_len)
6277 memcpy(list, XATTR_NAME_NFSV4_ACL, len);
6278 return len;
6279} 6269}
6280 6270
6281#ifdef CONFIG_NFS_V4_SECURITY_LABEL 6271#ifdef CONFIG_NFS_V4_SECURITY_LABEL
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 17efd76978c8..711dd5170376 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -823,21 +823,10 @@ out:
823 return ret; 823 return ret;
824} 824}
825 825
826static size_t 826static bool
827posix_acl_xattr_list(const struct xattr_handler *handler, 827posix_acl_xattr_list(struct dentry *dentry)
828 struct dentry *dentry, char *list, size_t list_size,
829 const char *name, size_t name_len)
830{ 828{
831 const char *xname = handler->name; 829 return IS_POSIXACL(d_backing_inode(dentry));
832 size_t size;
833
834 if (!IS_POSIXACL(d_backing_inode(dentry)))
835 return 0;
836
837 size = strlen(xname) + 1;
838 if (list && size <= list_size)
839 memcpy(list, xname, size);
840 return size;
841} 830}
842 831
843const struct xattr_handler posix_acl_access_xattr_handler = { 832const struct xattr_handler posix_acl_access_xattr_handler = {
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index efe2ed3c13c5..e5ddb4e5ea94 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -840,19 +840,16 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
840 840
841 handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr, 841 handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
842 name); 842 name);
843 if (!handler) /* Unsupported xattr name */ 843 if (!handler /* Unsupported xattr name */ ||
844 (handler->list && !handler->list(b->dentry)))
844 return 0; 845 return 0;
846 size = namelen + 1;
845 if (b->buf) { 847 if (b->buf) {
846 size = handler->list(handler, b->dentry,
847 b->buf + b->pos, b->size, name,
848 namelen);
849 if (size > b->size) 848 if (size > b->size)
850 return -ERANGE; 849 return -ERANGE;
851 } else { 850 memcpy(b->buf + b->pos, name, namelen);
852 size = handler->list(handler, b->dentry, 851 b->buf[b->pos + namelen] = 0;
853 NULL, 0, name, namelen);
854 } 852 }
855
856 b->pos += size; 853 b->pos += size;
857 } 854 }
858 return 0; 855 return 0;
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 2f0ccbaa2d92..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,18 +213,6 @@ 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)
@@ -238,22 +227,15 @@ static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
238static const struct xattr_handler squashfs_xattr_user_handler = { 227static const struct xattr_handler squashfs_xattr_user_handler = {
239 .prefix = XATTR_USER_PREFIX, 228 .prefix = XATTR_USER_PREFIX,
240 .flags = SQUASHFS_XATTR_USER, 229 .flags = SQUASHFS_XATTR_USER,
241 .list = squashfs_xattr_handler_list,
242 .get = squashfs_xattr_handler_get 230 .get = squashfs_xattr_handler_get
243}; 231};
244 232
245/* 233/*
246 * Trusted namespace support 234 * Trusted namespace support
247 */ 235 */
248static size_t squashfs_trusted_xattr_handler_list(const struct xattr_handler *handler, 236static bool squashfs_trusted_xattr_handler_list(struct dentry *d)
249 struct dentry *d, char *list,
250 size_t list_size, const char *name,
251 size_t name_len)
252{ 237{
253 if (!capable(CAP_SYS_ADMIN)) 238 return capable(CAP_SYS_ADMIN);
254 return 0;
255 return squashfs_xattr_handler_list(handler, d, list, list_size, name,
256 name_len);
257} 239}
258 240
259static const struct xattr_handler squashfs_xattr_trusted_handler = { 241static const struct xattr_handler squashfs_xattr_trusted_handler = {
@@ -269,7 +251,6 @@ static const struct xattr_handler squashfs_xattr_trusted_handler = {
269static const struct xattr_handler squashfs_xattr_security_handler = { 251static const struct xattr_handler squashfs_xattr_security_handler = {
270 .prefix = XATTR_SECURITY_PREFIX, 252 .prefix = XATTR_SECURITY_PREFIX,
271 .flags = SQUASHFS_XATTR_SECURITY, 253 .flags = SQUASHFS_XATTR_SECURITY,
272 .list = squashfs_xattr_handler_list,
273 .get = squashfs_xattr_handler_get 254 .get = squashfs_xattr_handler_get
274}; 255};
275 256
diff --git a/fs/xattr.c b/fs/xattr.c
index 2c7776403aba..d7f5037a17b5 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -723,23 +723,25 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
723 723
724 if (!buffer) { 724 if (!buffer) {
725 for_each_xattr_handler(handlers, handler) { 725 for_each_xattr_handler(handlers, handler) {
726 if (!handler->list) 726 if (!handler->name ||
727 (handler->list && !handler->list(dentry)))
727 continue; 728 continue;
728 size += handler->list(handler, dentry, NULL, 0, 729 size += strlen(handler->name) + 1;
729 NULL, 0);
730 } 730 }
731 } else { 731 } else {
732 char *buf = buffer; 732 char *buf = buffer;
733 size_t len;
733 734
734 for_each_xattr_handler(handlers, handler) { 735 for_each_xattr_handler(handlers, handler) {
735 if (!handler->list) 736 if (!handler->name ||
737 (handler->list && !handler->list(dentry)))
736 continue; 738 continue;
737 size = handler->list(handler, dentry, buf, buffer_size, 739 len = strlen(handler->name);
738 NULL, 0); 740 if (len + 1 > buffer_size)
739 if (size > buffer_size)
740 return -ERANGE; 741 return -ERANGE;
741 buf += size; 742 memcpy(buf, handler->name, len + 1);
742 buffer_size -= size; 743 buf += len + 1;
744 buffer_size -= len + 1;
743 } 745 }
744 size = buf - buffer; 746 size = buf - buffer;
745 } 747 }
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index d23ce8e9af6f..4457541de3c9 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -28,9 +28,7 @@ struct xattr_handler {
28 const char *name; 28 const char *name;
29 const char *prefix; 29 const char *prefix;
30 int flags; /* fs private flags */ 30 int flags; /* fs private flags */
31 size_t (*list)(const struct xattr_handler *, struct dentry *dentry, 31 bool (*list)(struct dentry *dentry);
32 char *list, size_t list_size, const char *name,
33 size_t name_len);
34 int (*get)(const struct xattr_handler *, struct dentry *dentry, 32 int (*get)(const struct xattr_handler *, struct dentry *dentry,
35 const char *name, void *buffer, size_t size); 33 const char *name, void *buffer, size_t size);
36 int (*set)(const struct xattr_handler *, struct dentry *dentry, 34 int (*set)(const struct xattr_handler *, struct dentry *dentry,