public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: sandeen@sandeen.net
Cc: linux-xfs@vger.kernel.org, Christoph Hellwig <hch@infradead.org>
Subject: [PATCH v2 11/8] xfs_repair: don't corrupt a attr fork da3 node when clearing forw/back
Date: Thu, 30 Jan 2020 10:46:06 -0800	[thread overview]
Message-ID: <20200130184606.GC3447196@magnolia> (raw)
In-Reply-To: <20200130181512.GZ3447196@magnolia>

From: Darrick J. Wong <darrick.wong@oracle.com>

In process_longform_attr, we enforce that the root block of the
attribute index must have both forw or back pointers set to zero.
Unfortunately, the code that nulls out the pointers is not aware that
the root block could be in da3 node format.

This leads to corruption of da3 root node blocks because the functions
that convert attr3 leaf headers to and from the ondisk structures
perform some interpretation of firstused on what they think is an attr1
leaf block.

Found by using xfs/402 to fuzz hdr.info.hdr.forw.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
v2: split the da node code into a separate function since that code path
exits out the bottom of the case statement.
---
 repair/attr_repair.c |   98 +++++++++++++++++++++++++++++++++++---------------
 1 file changed, 68 insertions(+), 30 deletions(-)

diff --git a/repair/attr_repair.c b/repair/attr_repair.c
index 9a44f610..8b66a06d 100644
--- a/repair/attr_repair.c
+++ b/repair/attr_repair.c
@@ -952,6 +952,52 @@ _("wrong FS UUID, inode %" PRIu64 " attr block %" PRIu64 "\n"),
 	return 0;
 }
 
+static int
+process_longform_da_root(
+	struct xfs_mount	*mp,
+	xfs_ino_t		ino,
+	struct xfs_dinode	*dip,
+	struct blkmap		*blkmap,
+	int			*repair,
+	struct xfs_buf		*bp)
+{
+	struct xfs_da3_icnode_hdr	da3_hdr;
+	int			repairlinks = 0;
+	int			error;
+
+	xfs_da3_node_hdr_from_disk(mp, &da3_hdr, bp->b_addr);
+	/*
+	 * check sibling pointers in leaf block or root block 0 before
+	 * we have to release the btree block
+	 */
+	if (da3_hdr.forw != 0 || da3_hdr.back != 0)  {
+		if (!no_modify)  {
+			do_warn(
+_("clearing forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"),
+				ino);
+
+			repairlinks = 1;
+			da3_hdr.forw = 0;
+			da3_hdr.back = 0;
+			xfs_da3_node_hdr_to_disk(mp, bp->b_addr, &da3_hdr);
+		} else  {
+			do_warn(
+_("would clear forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"), ino);
+		}
+	}
+
+	/* must do this now, to release block 0 before the traversal */
+	if ((*repair || repairlinks) && !no_modify) {
+		*repair = 1;
+		libxfs_writebuf(bp, 0);
+	} else
+		libxfs_putbuf(bp);
+	error = process_node_attr(mp, ino, dip, blkmap); /* + repair */
+	if (error)
+		*repair = 0;
+	return error;
+}
+
 /*
  * Start processing for a leaf or fuller btree.
  * A leaf directory is one where the attribute fork is too big for
@@ -975,7 +1021,6 @@ process_longform_attr(
 	xfs_dahash_t	next_hashval;
 	int		repairlinks = 0;
 	struct xfs_attr3_icleaf_hdr leafhdr;
-	int		error;
 
 	*repair = 0;
 
@@ -1019,25 +1064,6 @@ process_longform_attr(
 	leaf = bp->b_addr;
 	xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
 
-	/* check sibling pointers in leaf block or root block 0 before
-	* we have to release the btree block
-	*/
-	if (leafhdr.forw != 0 || leafhdr.back != 0)  {
-		if (!no_modify)  {
-			do_warn(
-	_("clearing forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"),
-				ino);
-			repairlinks = 1;
-			leafhdr.forw = 0;
-			leafhdr.back = 0;
-			xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo,
-						   leaf, &leafhdr);
-		} else  {
-			do_warn(
-	_("would clear forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"), ino);
-		}
-	}
-
 	/*
 	 * use magic number to tell us what type of attribute this is.
 	 * it's possible to have a node or leaf attribute in either an
@@ -1046,6 +1072,26 @@ process_longform_attr(
 	switch (leafhdr.magic) {
 	case XFS_ATTR_LEAF_MAGIC:	/* leaf-form attribute */
 	case XFS_ATTR3_LEAF_MAGIC:
+		/*
+		 * check sibling pointers in leaf block or root block 0 before
+		 * we have to release the btree block
+		 */
+		if (leafhdr.forw != 0 || leafhdr.back != 0)  {
+			if (!no_modify)  {
+				do_warn(
+	_("clearing forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"),
+					ino);
+				repairlinks = 1;
+				leafhdr.forw = 0;
+				leafhdr.back = 0;
+				xfs_attr3_leaf_hdr_to_disk(mp->m_attr_geo,
+						leaf, &leafhdr);
+			} else  {
+				do_warn(
+	_("would clear forw/back pointers in block 0 for attributes in inode %" PRIu64 "\n"), ino);
+			}
+		}
+
 		if (process_leaf_attr_block(mp, leaf, 0, ino, blkmap,
 				0, &next_hashval, repair)) {
 			*repair = 0;
@@ -1058,16 +1104,8 @@ process_longform_attr(
 
 	case XFS_DA_NODE_MAGIC:		/* btree-form attribute */
 	case XFS_DA3_NODE_MAGIC:
-		/* must do this now, to release block 0 before the traversal */
-		if ((*repair || repairlinks) && !no_modify) {
-			*repair = 1;
-			libxfs_writebuf(bp, 0);
-		} else
-			libxfs_putbuf(bp);
-		error = process_node_attr(mp, ino, dip, blkmap); /* + repair */
-		if (error)
-			*repair = 0;
-		return error;
+		return process_longform_da_root(mp, ino, dip, blkmap, repair,
+				bp);
 	default:
 		do_warn(
 	_("bad attribute leaf magic # %#x for dir ino %" PRIu64 "\n"),

  parent reply	other threads:[~2020-01-30 18:48 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-24  0:16 [PATCH 0/8] xfsprogs: random fixes Darrick J. Wong
2020-01-24  0:16 ` [PATCH 1/8] man: list xfs_io lsattr inode flag letters Darrick J. Wong
2020-01-25 23:16   ` Christoph Hellwig
2020-01-24  0:16 ` [PATCH 2/8] man: document the xfs_db btheight command Darrick J. Wong
2020-01-25 23:16   ` Christoph Hellwig
2020-01-24  0:16 ` [PATCH 3/8] man: reformat xfs_quota commands in the manpage for testing Darrick J. Wong
2020-01-25 23:16   ` Christoph Hellwig
2020-01-24  0:16 ` [PATCH 4/8] man: document some missing xfs_db commands Darrick J. Wong
2020-01-25 23:16   ` Christoph Hellwig
2020-01-24  0:17 ` [PATCH 5/8] xfs_db: dump per-AG reservations Darrick J. Wong
2020-01-25 23:17   ` Christoph Hellwig
2020-01-24  0:17 ` [PATCH 6/8] xfs_io: fix copy_file_range length argument overflow Darrick J. Wong
2020-01-25 23:18   ` Christoph Hellwig
2020-01-24  0:17 ` [PATCH 7/8] xfs_io: fix pwrite/pread length truncation on 32-bit systems Darrick J. Wong
2020-01-25 23:18   ` Christoph Hellwig
2020-01-24  0:17 ` [PATCH 8/8] xfs_repair: fix totally broken unit conversion in directory invalidation Darrick J. Wong
2020-01-25 23:19   ` Christoph Hellwig
2020-01-26 22:11     ` Darrick J. Wong
2020-01-30 18:35       ` Eric Sandeen
2020-01-28 15:56 ` [PATCH 9/8] xfs_io: fix integer over/underflow handling in timespec_from_string Darrick J. Wong
2020-01-30 18:18   ` Christoph Hellwig
2020-01-30 18:13 ` [PATCH 10/8] libxfs: remove duplicate attr function declarations Darrick J. Wong
2020-01-30 18:17   ` Christoph Hellwig
2020-01-30 18:28   ` Eric Sandeen
2020-01-30 18:40     ` Darrick J. Wong
2020-01-30 18:48       ` Eric Sandeen
2020-01-30 18:15 ` [PATCH 11/8] xfs_repair: don't corrupt a attr fork da3 node when clearing forw/back Darrick J. Wong
2020-01-30 18:22   ` Christoph Hellwig
2020-01-30 18:31     ` Darrick J. Wong
2020-01-30 18:46   ` Darrick J. Wong [this message]
2020-01-31  6:03     ` [PATCH v2 " Christoph Hellwig
2020-02-04 23:14       ` Darrick J. Wong
2020-02-05  6:07         ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200130184606.GC3447196@magnolia \
    --to=darrick.wong@oracle.com \
    --cc=hch@infradead.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=sandeen@sandeen.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox