git: 595ed4d76713 - main - msdosfs: handle inconsistently hashed denodes

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 08 Jan 2022 04:29:29 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=595ed4d76713c1e9cab7d8a160ed59f8f4e5ecb4

commit 595ed4d76713c1e9cab7d8a160ed59f8f4e5ecb4
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-12-23 23:21:53 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-01-08 03:41:44 +0000

    msdosfs: handle inconsistently hashed denodes
    
    It is possible, on the corrupted msdosfs volume, to have file which
    denode inode number does not match the one calculated using directory
    cluster.  Instead of asserting the condition as impossible, handle it
    and return error, after reclaiming the aliased vnode.
    
    In collaboration with:  pho
    Reviewed by:    markj, mckusick
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D33721
---
 sys/fs/msdosfs/msdosfs_denode.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
index 64f75c267959..8ca9fa38b1cf 100644
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -142,9 +142,23 @@ deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
 		return (error);
 	if (nvp != NULL) {
 		*depp = VTODE(nvp);
-		KASSERT((*depp)->de_dirclust == dirclust, ("wrong dirclust"));
-		KASSERT((*depp)->de_diroffset == diroffset, ("wrong diroffset"));
+		if ((*depp)->de_dirclust != dirclust) {
+			printf("%s: wrong dir cluster %lu %lu\n",
+			    pmp->pm_mountp->mnt_stat.f_mntonname,
+			    (*depp)->de_dirclust, dirclust);
+			goto badoff;
+		}
+		if ((*depp)->de_diroffset != diroffset) {
+			printf("%s: wrong dir offset %lu %lu\n",
+			    pmp->pm_mountp->mnt_stat.f_mntonname,
+			    (*depp)->de_diroffset,  diroffset);
+			goto badoff;
+		}
 		return (0);
+badoff:
+		vgone(nvp);
+		vput(nvp);
+		return (EBADF);
 	}
 	ldep = malloc(sizeof(struct denode), M_MSDOSFSNODE, M_WAITOK | M_ZERO);