59 lines
2.0 KiB
Diff
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
|
|
|