Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Feb 2024 10:49:50 GMT
From:      Stefan =?utf-8?Q?E=C3=9Fer?= <se@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: fba1a994acfe - stable/14 - msdosfs: fix potential inode collision on FAT12 and FAT16
Message-ID:  <202402231049.41NAnoUf079580@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by se:

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

commit fba1a994acfe31d957e9e26a5f12a6fdd1689bd2
Author:     Stefan Eßer <se@FreeBSD.org>
AuthorDate: 2024-02-20 12:02:24 +0000
Commit:     Stefan Eßer <se@FreeBSD.org>
CommitDate: 2024-02-23 10:47:58 +0000

    msdosfs: fix potential inode collision on FAT12 and FAT16
    
    PR:             277239
    Approved by:    mckusick
    
    (cherry picked from commit 445d3d227e68f85157d0301d1706aa488e8423da)
---
 sys/fs/msdosfs/denode.h         |  8 +++++++-
 sys/fs/msdosfs/msdosfs_denode.c | 19 ++++++++++++++++---
 sys/fs/msdosfs/msdosfs_lookup.c |  2 +-
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/sys/fs/msdosfs/denode.h b/sys/fs/msdosfs/denode.h
index ad52a736592c..0d31b0583fa6 100644
--- a/sys/fs/msdosfs/denode.h
+++ b/sys/fs/msdosfs/denode.h
@@ -162,7 +162,7 @@ struct denode {
 	u_long de_FileSize;	/* size of file in bytes */
 	struct fatcache de_fc[FC_SIZE];	/* FAT cache */
 	u_quad_t de_modrev;	/* Revision level for lease. */
-	uint64_t de_inode;	/* Inode number (really byte offset of direntry) */
+	uint64_t de_inode;	/* Inode number (really index of DOS style direntry) */
 };
 
 /*
@@ -217,6 +217,12 @@ struct denode {
 #define	VTODE(vp)	((struct denode *)(vp)->v_data)
 #define	DETOV(de)	((de)->de_vnode)
 
+#define DETOI(pmp, cn, off)						\
+	((cn) == MSDOSFSROOT						\
+	    ? (((uint64_t)(off) >> 5))					\
+	    : (((((uint64_t)pmp->pm_bpcluster * ((cn) - 2) + (off))) >> 5) \
+		+ pmp->pm_RootDirEnts))
+
 #define	DETIMES(dep, acc, mod, cre) do {				\
 	if ((dep)->de_flag & DE_UPDATE) {				\
 		(dep)->de_flag |= DE_MODIFIED;				\
diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
index 612b318ce6e8..7f275d387a25 100644
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -133,10 +133,13 @@ deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
 	 * entry that represented the file happens to be reused while the
 	 * deleted file is still open.
 	 */
-	inode = (uint64_t)pmp->pm_bpcluster * dirclust + diroffset;
+	inode = DETOI(pmp, dirclust, diroffset);
 
 	error = vfs_hash_get(mntp, inode, lkflags, curthread, &nvp,
 	    de_vncmpf, &inode);
+#ifdef MSDOSFS_DEBUG
+	printf("vfs_hash_get(inode %lu) error %d\n", inode, error);
+#endif
 	if (error)
 		return (error);
 	if (nvp != NULL) {
@@ -191,6 +194,9 @@ badoff:
 	}
 	error = vfs_hash_insert(nvp, inode, lkflags, curthread, &xvp,
 	    de_vncmpf, &inode);
+#ifdef MSDOSFS_DEBUG
+	printf("vfs_hash_insert(inode %lu) error %d\n", inode, error);
+#endif
 	if (error) {
 		*depp = NULL;
 		return (error);
@@ -589,8 +595,11 @@ reinsert(struct denode *dep)
 		return;
 #endif
 	vp = DETOV(dep);
-	dep->de_inode = (uint64_t)dep->de_pmp->pm_bpcluster * dep->de_dirclust +
-	    dep->de_diroffset;
+	dep->de_inode = DETOI(dep->de_pmp, dep->de_dirclust, dep->de_diroffset);
+#ifdef MSDOSFS_DEBUG
+	printf("vfs_hash_rehash(inode %lu, refcnt %lu, vp %p)\n",
+	    dep->de_inode, dep->de_refcnt, vp);
+#endif
 	vfs_hash_rehash(vp, dep->de_inode);
 }
 
@@ -608,6 +617,10 @@ msdosfs_reclaim(struct vop_reclaim_args *ap)
 	/*
 	 * Remove the denode from its hash chain.
 	 */
+#ifdef MSDOSFS_DEBUG
+	printf("vfs_hash_remove(inode %lu, refcnt %lu, vp %p)\n",
+	    dep->de_inode, dep->de_refcnt, vp);
+#endif
 	vfs_hash_remove(vp);
 	/*
 	 * Purge old data structures associated with the denode.
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
index eb4cbaa21ab7..2a90339d0878 100644
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -586,7 +586,7 @@ foundroot:
 		}
 		if (FAT32(pmp) && scn == MSDOSFSROOT)
 			scn = pmp->pm_rootdirblk;
-		inode1 = scn * pmp->pm_bpcluster + blkoff;
+		inode1 = DETOI(pmp, scn, blkoff);
 		if (VTODE(*vpp)->de_inode != inode1) {
 			vput(*vpp);
 			goto restart;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202402231049.41NAnoUf079580>