From f12ef8824174aaceea362052ac3a5b0164d75f9e Mon Sep 17 00:00:00 2001
From: Nathan Scott <nathans@sgi.com>
Date: Sat, 28 Feb 2004 15:57:48 +1100
Subject: [PATCH] [XFS] Fix the by-handle attr list interface (used by xfsdump)
 for security attrs.

SGI Modid: xfs-linux:xfs-kern:167038a
---
 fs/xfs/linux/xfs_iops.c |  3 +--
 fs/xfs/xfs_attr.h       |  6 +++++-
 fs/xfs/xfs_attr_leaf.c  | 22 +++++++++++++++++++---
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c
index 7cceb1252c50..25f7260482c4 100644
--- a/fs/xfs/linux/xfs_iops.c
+++ b/fs/xfs/linux/xfs_iops.c
@@ -630,8 +630,7 @@ linvfs_listxattr(
 
 	if (!size)
 		xflags |= ATTR_KERNOVAL;
-	if (capable(CAP_SYS_ADMIN))
-		xflags |= ATTR_KERNFULLS;
+	xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS;
 
 	error = attr_generic_list(vp, data, size, xflags, &result);
 	if (error < 0)
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index c83011f9706d..bd58615573a4 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -91,10 +91,14 @@ extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
 #define ATTR_CREATE	0x0010	/* pure create: fail if attr already exists */
 #define ATTR_REPLACE	0x0020	/* pure set: fail if attr does not exist */
 #define ATTR_SYSTEM	0x0100	/* use attrs in system (pseudo) namespace */
+
 #define ATTR_KERNOTIME	0x1000	/* [kernel] don't update inode timestamps */
 #define ATTR_KERNOVAL	0x2000	/* [kernel] get attr size only, not value */
 #define ATTR_KERNAMELS	0x4000	/* [kernel] list attr names (simple list) */
-#define ATTR_KERNFULLS	0x8000	/* [kernel] full attr list, ie. root+user */
+
+#define ATTR_KERNORMALS	0x0800	/* [kernel] normal attr list: user+secure */
+#define ATTR_KERNROOTLS	0x8000	/* [kernel] include root in the attr list */
+#define ATTR_KERNFULLS	(ATTR_KERNORMALS|ATTR_KERNROOTLS)
 
 /*
  * The maximum size (into the kernel or returned from the kernel) of an
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 22f38db4ee9a..20a859457ef9 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -460,9 +460,15 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
 				i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) {
 			attrnames_t	*namesp;
 
+			if (((context->flags & ATTR_SECURE) != 0) !=
+			    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
+			    !(context->flags & ATTR_KERNORMALS)) {
+				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
+				continue;
+			}
 			if (((context->flags & ATTR_ROOT) != 0) !=
 			    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-			    !(context->flags & ATTR_KERNFULLS)) {
+			    !(context->flags & ATTR_KERNROOTLS)) {
 				sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 				continue;
 			}
@@ -511,9 +517,15 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
 			kmem_free(sbuf, sbsize);
 			return XFS_ERROR(EFSCORRUPTED);
 		}
+		if (((context->flags & ATTR_SECURE) != 0) !=
+		    ((sfe->flags & XFS_ATTR_SECURE) != 0) &&
+		    !(context->flags & ATTR_KERNORMALS)) {
+			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
+			continue;
+		}
 		if (((context->flags & ATTR_ROOT) != 0) !=
 		    ((sfe->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNFULLS)) {
+		    !(context->flags & ATTR_KERNROOTLS)) {
 			sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
 			continue;
 		}
@@ -2309,9 +2321,13 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
 
 		if (entry->flags & XFS_ATTR_INCOMPLETE)
 			continue;		/* skip incomplete entries */
+		if (((context->flags & ATTR_SECURE) != 0) !=
+		    ((entry->flags & XFS_ATTR_SECURE) != 0) &&
+		    !(context->flags & ATTR_KERNORMALS))
+			continue;		/* skip non-matching entries */
 		if (((context->flags & ATTR_ROOT) != 0) !=
 		    ((entry->flags & XFS_ATTR_ROOT) != 0) &&
-		    !(context->flags & ATTR_KERNFULLS))
+		    !(context->flags & ATTR_KERNROOTLS))
 			continue;		/* skip non-matching entries */
 
 		namesp = (entry->flags & XFS_ATTR_SECURE) ? &attr_secure :
-- 
2.30.9