git: a495e7f5c5c2 - stable/13 - msdosfs: fix potential inode collision on FAT12 and FAT16
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 23 Feb 2024 10:52:09 UTC
The branch stable/13 has been updated by se: URL: https://cgit.FreeBSD.org/src/commit/?id=a495e7f5c5c2088bf32cd7349e2ca344ee089552 commit a495e7f5c5c2088bf32cd7349e2ca344ee089552 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:50:31 +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 9ac5c2a2f5e1..881e27bc3874 100644 --- a/sys/fs/msdosfs/denode.h +++ b/sys/fs/msdosfs/denode.h @@ -161,7 +161,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) */ }; /* @@ -216,6 +216,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 e131d8f5eac3..2c44d49be197 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) { @@ -190,6 +193,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); @@ -587,8 +593,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); } @@ -606,6 +615,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 252f237af2d6..d34a670e2fc9 100644 --- a/sys/fs/msdosfs/msdosfs_lookup.c +++ b/sys/fs/msdosfs/msdosfs_lookup.c @@ -590,7 +590,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;