summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-06-23 01:35:01 +0000
committerAlex Elder <aelder@sgi.com>2011-06-23 22:13:51 -0500
commit4a33821236f2ef3af0081e8a5eec1301cbed3125 (patch)
tree4bb7c6f9e8ceb2b3e6cdd8bea7a76bb73676b58f
parentdf4368a146d2b350b8398babfe11e2088f741d67 (diff)
downloadlinux-stable-4a33821236f2ef3af0081e8a5eec1301cbed3125.tar.gz
linux-stable-4a33821236f2ef3af0081e8a5eec1301cbed3125.tar.bz2
linux-stable-4a33821236f2ef3af0081e8a5eec1301cbed3125.zip
xfs: prevent bogus assert when trying to remove non-existent attribute
If the attribute fork on an inode is in btree format and has multiple levels (i.e node format rather than leaf format), then a lookup failure will trigger an assert failure in xfs_da_path_shift if the flag XFS_DA_OP_OKNOENT is not set. This flag is used to indicate to the directory btree code that not finding an entry is not a fatal error. In the case of doing a lookup for a directory name removal, this is valid as a user cannot insert an arbitrary name to remove from the directory btree. However, in the case of the attribute tree, a user has direct control over the attribute name and can ask for any random name to be removed without any validation. In this case, fsstress is asking for a non-existent user.selinux attribute to be removed, and that is causing xfs_da_path_shift() to fall off the bottom of the tree where it asserts that a lookup failure is allowed. Because the flag is not set, we die a horrible death on a debug enable kernel. Prevent this assert from firing on attribute removes by adding the op_flag XFS_DA_OP_OKNOENT to atribute removal operations. Discovered when testing on a SELinux enabled system by fsstress in test 070 by trying to remove a non-existent user.selinux attribute. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
-rw-r--r--fs/xfs/xfs_attr.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index c86375378810..01d2072fb6d4 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -490,6 +490,13 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
args.whichfork = XFS_ATTR_FORK;
/*
+ * we have no control over the attribute names that userspace passes us
+ * to remove, so we have to allow the name lookup prior to attribute
+ * removal to fail.
+ */
+ args.op_flags = XFS_DA_OP_OKNOENT;
+
+ /*
* Attach the dquots to the inode.
*/
error = xfs_qm_dqattach(dp, 0);