summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/xattr.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 87b85f3403d4..ec09ea5c4f07 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -657,23 +657,30 @@ list_xattr:
657 vir_namelen = ceph_vxattrs_name_size(vxattrs); 657 vir_namelen = ceph_vxattrs_name_size(vxattrs);
658 658
659 /* adding 1 byte per each variable due to the null termination */ 659 /* adding 1 byte per each variable due to the null termination */
660 namelen = vir_namelen + ci->i_xattrs.names_size + ci->i_xattrs.count; 660 namelen = ci->i_xattrs.names_size + ci->i_xattrs.count;
661 err = -ERANGE; 661 err = -ERANGE;
662 if (size && namelen > size) 662 if (size && vir_namelen + namelen > size)
663 goto out; 663 goto out;
664 664
665 err = namelen; 665 err = namelen + vir_namelen;
666 if (size == 0) 666 if (size == 0)
667 goto out; 667 goto out;
668 668
669 names = __copy_xattr_names(ci, names); 669 names = __copy_xattr_names(ci, names);
670 670
671 /* virtual xattr names, too */ 671 /* virtual xattr names, too */
672 if (vxattrs) 672 err = namelen;
673 if (vxattrs) {
673 for (i = 0; vxattrs[i].name; i++) { 674 for (i = 0; vxattrs[i].name; i++) {
674 len = sprintf(names, "%s", vxattrs[i].name); 675 if (!vxattrs[i].hidden &&
675 names += len + 1; 676 !(vxattrs[i].exists_cb &&
677 !vxattrs[i].exists_cb(ci))) {
678 len = sprintf(names, "%s", vxattrs[i].name);
679 names += len + 1;
680 err += len + 1;
681 }
676 } 682 }
683 }
677 684
678out: 685out:
679 spin_unlock(&ci->i_ceph_lock); 686 spin_unlock(&ci->i_ceph_lock);