135 lines
3.7 KiB
Diff
135 lines
3.7 KiB
Diff
From 5008cbb4b0eaef22e5a0e13a5a2c17457671e34a Mon Sep 17 00:00:00 2001
|
|
From: "Darrick J. Wong" <djwong@kernel.org>
|
|
Date: Tue, 17 May 2022 22:48:13 -0400
|
|
Subject: [PATCH] xfs_repair: check the ftype of dot and dotdot directory
|
|
entries
|
|
|
|
The long-format directory block checking code skips the filetype check
|
|
for the '.' and '..' entries, even though they're part of the ondisk
|
|
format. This leads to repair failing to catch subtle corruption at the
|
|
start of a directory.
|
|
|
|
Found by fuzzing bu[0].filetype = zeroes in xfs/386.
|
|
|
|
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
|
|
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
|
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
|
---
|
|
repair/phase6.c | 79 +++++++++++++++++++++++++++++++++++++++------------------
|
|
1 file changed, 54 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/repair/phase6.c b/repair/phase6.c
|
|
index 696a642..06232fb 100644
|
|
--- a/repair/phase6.c
|
|
+++ b/repair/phase6.c
|
|
@@ -1412,6 +1412,48 @@ dir2_kill_block(
|
|
_("directory shrink failed (%d)\n"), error);
|
|
}
|
|
|
|
+static inline void
|
|
+check_longform_ftype(
|
|
+ struct xfs_mount *mp,
|
|
+ struct xfs_inode *ip,
|
|
+ xfs_dir2_data_entry_t *dep,
|
|
+ ino_tree_node_t *irec,
|
|
+ int ino_offset,
|
|
+ struct dir_hash_tab *hashtab,
|
|
+ xfs_dir2_dataptr_t addr,
|
|
+ struct xfs_da_args *da,
|
|
+ struct xfs_buf *bp)
|
|
+{
|
|
+ xfs_ino_t inum = be64_to_cpu(dep->inumber);
|
|
+ uint8_t dir_ftype;
|
|
+ uint8_t ino_ftype;
|
|
+
|
|
+ if (!xfs_sb_version_hasftype(&mp->m_sb))
|
|
+ return;
|
|
+
|
|
+ dir_ftype = libxfs_dir2_data_get_ftype(mp, dep);
|
|
+ ino_ftype = get_inode_ftype(irec, ino_offset);
|
|
+
|
|
+ if (dir_ftype == ino_ftype)
|
|
+ return;
|
|
+
|
|
+ if (no_modify) {
|
|
+ do_warn(
|
|
+_("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
|
|
+ dir_ftype, ino_ftype,
|
|
+ ip->i_ino, inum);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ do_warn(
|
|
+_("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
|
|
+ dir_ftype, ino_ftype,
|
|
+ ip->i_ino, inum);
|
|
+ libxfs_dir2_data_put_ftype(mp, dep, ino_ftype);
|
|
+ libxfs_dir2_data_log_entry(da, bp, dep);
|
|
+ dir_hash_update_ftype(hashtab, addr, ino_ftype);
|
|
+}
|
|
+
|
|
/*
|
|
* process a data block, also checks for .. entry
|
|
* and corrects it to match what we think .. should be
|
|
@@ -1749,6 +1791,11 @@ longform_dir2_entry_check_data(
|
|
libxfs_dir2_data_log_entry(&da, bp, dep);
|
|
}
|
|
}
|
|
+
|
|
+ if (!nbad)
|
|
+ check_longform_ftype(mp, ip, dep, irec,
|
|
+ ino_offset, hashtab, addr, &da,
|
|
+ bp);
|
|
continue;
|
|
}
|
|
ASSERT(no_modify || libxfs_verify_dir_ino(mp, inum));
|
|
@@ -1777,6 +1824,11 @@ longform_dir2_entry_check_data(
|
|
libxfs_dir2_data_log_entry(&da, bp, dep);
|
|
}
|
|
}
|
|
+
|
|
+ if (!nbad)
|
|
+ check_longform_ftype(mp, ip, dep, irec,
|
|
+ ino_offset, hashtab, addr, &da,
|
|
+ bp);
|
|
*need_dot = 0;
|
|
continue;
|
|
}
|
|
@@ -1787,31 +1839,8 @@ longform_dir2_entry_check_data(
|
|
continue;
|
|
|
|
/* validate ftype field if supported */
|
|
- if (xfs_sb_version_hasftype(&mp->m_sb)) {
|
|
- uint8_t dir_ftype;
|
|
- uint8_t ino_ftype;
|
|
-
|
|
- dir_ftype = libxfs_dir2_data_get_ftype(mp, dep);
|
|
- ino_ftype = get_inode_ftype(irec, ino_offset);
|
|
-
|
|
- if (dir_ftype != ino_ftype) {
|
|
- if (no_modify) {
|
|
- do_warn(
|
|
- _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
|
|
- dir_ftype, ino_ftype,
|
|
- ip->i_ino, inum);
|
|
- } else {
|
|
- do_warn(
|
|
- _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
|
|
- dir_ftype, ino_ftype,
|
|
- ip->i_ino, inum);
|
|
- libxfs_dir2_data_put_ftype(mp, dep, ino_ftype);
|
|
- libxfs_dir2_data_log_entry(&da, bp, dep);
|
|
- dir_hash_update_ftype(hashtab, addr,
|
|
- ino_ftype);
|
|
- }
|
|
- }
|
|
- }
|
|
+ check_longform_ftype(mp, ip, dep, irec, ino_offset, hashtab,
|
|
+ addr, &da, bp);
|
|
|
|
/*
|
|
* check easy case first, regular inode, just bump
|
|
--
|
|
1.8.3.1
|
|
|