As of xfsprogs-4.17 we started testing whether the di_next_unlinked field on an inode is valid in the inode verifiers. However, this field is never tested or repaired during inode processing. So if, for example, we had a completely zeroed-out inode, we'd detect and fix the broken magic and version, but the invalid di_next_unlinked field would not be touched, fail the write verifier, and prevent the inode from being properly repaired or even written out. Fix this by checking the di_next_unlinked inode field for validity and clearing it if it is invalid. Reported-by: John Jore <john@xxxxxxx> Fixes: 2949b4677 ("xfs: don't accept inode buffers with suspicious unlinked chains") Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> --- diff --git a/repair/dinode.c b/repair/dinode.c index 8af2cb25..c5d2f350 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2272,6 +2272,7 @@ process_dinode_int(xfs_mount_t *mp, const int is_free = 0; const int is_used = 1; blkmap_t *dblkmap = NULL; + xfs_agino_t unlinked_ino; *dirty = *isa_dir = 0; *used = is_used; @@ -2351,6 +2352,23 @@ process_dinode_int(xfs_mount_t *mp, } } + unlinked_ino = be32_to_cpu(dino->di_next_unlinked); + if (!xfs_verify_agino_or_null(mp, agno, unlinked_ino)) { + retval = 1; + if (!uncertain) + do_warn(_("bad next_unlinked 0x%x on inode %" PRIu64 "%c"), + (__s32)dino->di_next_unlinked, lino, + verify_mode ? '\n' : ','); + if (!verify_mode) { + if (!no_modify) { + do_warn(_(" resetting next_unlinked\n")); + clear_dinode_unlinked(mp, dino); + *dirty = 1; + } else + do_warn(_(" would reset next_unlinked\n")); + } + } + /* * We don't bother checking the CRC here - we cannot guarantee that when * we are called here that the inode has not already been modified in