xfsprogs/0042-xfs_repair-don-t-crash-on-unknown-inode-parents-in-d.patch
wguanghao 7fbd36818a backport patches from community
(cherry picked from commit cc60985a665f17f23031c03f1021e886d63b990f)
2023-12-27 16:29:57 +08:00

59 lines
2.0 KiB
Diff

From 978c3087b6afa56986ac3e5a52131d73d28253ca Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Wed, 23 Nov 2022 09:09:28 -0800
Subject: [PATCH] xfs_repair: don't crash on unknown inode parents in dry run
mode
Fuzz testing of directory block headers exposed a debug assertion vector
in xfs_repair. In normal (aka fixit) mode, if a single-block directory
has a totally trashed block, repair will zap the entire directory.
Phase 4 ignores any dirents pointing to the zapped directory, phase 6
ignores the freed directory, and everything is good.
However, in dry run mode, we don't actually free the inode. Phase 4
still ignores any dirents pointing to the zapped directory, but phase 6
thinks the inode is still live and tries to walk it. xfs_repair doesn't
know of any parents for the zapped directory and so trips the assertion.
The assertion is critical for fixit mode because we need all the parent
information to ensure consistency of the directory tree. In dry run
mode we don't care, because we only have to print inconsistencies and
return 1. Worse yet, (our) customers file bugs when xfs_repair crashes
during a -n scan, so this will generate support calls.
Make everyone's life easier by downgrading the assertion to a warning if
we're running in dry run mode.
Found by fuzzing bhdr.hdr.bno = zeroes in xfs/471.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
repair/phase6.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/repair/phase6.c b/repair/phase6.c
index 1f9f8de..0be2c9c 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1836,7 +1836,14 @@ longform_dir2_entry_check_data(
continue;
}
parent = get_inode_parent(irec, ino_offset);
- ASSERT(parent != 0);
+ if (parent == 0) {
+ if (no_modify)
+ do_warn(
+ _("unknown parent for inode %" PRIu64 "\n"),
+ inum);
+ else
+ ASSERT(parent != 0);
+ }
junkit = 0;
/*
* bump up the link counts in parent and child
--
1.8.3.1