From nobody Fri Feb 23 17:36:57 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ThHJB0zRzz5B9W4; Fri, 23 Feb 2024 17:36:58 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ThHJB0Pvjz4hf9; Fri, 23 Feb 2024 17:36:58 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708709818; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=o9C9Rrsm7uiB7opKpL7M53smV4dx0n1+AWg63uqftJM=; b=Lo+oA+M6ny39x41sCH70NnKJMKkuhgZp/+bCCyTYTJdzoy0Zf3/mQHMuxRpgeKHEGJLGvA rlNF+XLF/Wi6uB5rlGt2f3y5RP+YjKw0zsVzV+aIqCPHMiSM1L315x4i/RUsnnr0xya4th oq0lDY944Dyz4CR6KUzxkvRLNe7aw+s0EJgk7t0MtaHO/F6jKhndKU1lerVLF6JFuhAvng CKWQwtSg/Y2VI+R2DUzt+LOpE7qLCEd5yHRLeghpvc5ZIyJNq8L5GM6+24sH7dYoJBAZ0l 6MUbyEWE90DCJLgMYP704OptvMMC30tN8tl4qhaFH/IDV65jbSr7B4TakWKXMA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1708709818; a=rsa-sha256; cv=none; b=ECnHj5GuqunobemZeJ5O8KXBrEZDzfq7yRoGhULGmUYo0JzwrmZzOHCoy8H8sKmFrE3Qc7 sbgKwuXhDeqt/RYYMHsaDiy6y36k9Pj3r8AdR6Szoot0iBzq+hjB9IVaC2ZcpZgLdtJEB8 AbfzIMWqkyL0bu30sfJzMAZjgOUH/YBBNGDWoowyWbaLwNtr14lxI5rLm4CAlC7QLvpmfP 9WbaCiYf6Us1dS4d99yvlx9BhYgumQdaZAQo9BNqdAZGd9CTc9XlJgm82qVrDK7XaN1+mF V5vmEu8EoAKbM0uV+5UGikEUyzKIQJqIEW3jV3KopP/f2hqlIBTzjisllzNS+Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708709818; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=o9C9Rrsm7uiB7opKpL7M53smV4dx0n1+AWg63uqftJM=; b=xRc18MSbG4cSIsLSBdvL2qutvb0pMv5iteVeWU+jePw9M9cNCqF9h4VzhqWvimsqUF37G4 VgO3fFylD0wKMMi9yQivhKWbw5DLEfedXYhW5KX8fwla4TjkyFvBsARcIewEyilShhB1sc tlJdpMFWLmUmgwgscqjscWmLzhK2qWgs+zWeNUqwhUu4JiuyrrA2NjKTBfGQ1UXDC3whzl UVNdiclxEcfVPwprLHsg4vjOvjnOiF1HiCYyHNdrNOq7y7zkXjCfQCoHOLoUZKLnuDz5gf lnPyji0CtTK8sJtccnpxfz8GCi8uW12Crj9XmtUIlhSXRGStRraIjnfMzFKJdQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ThHJ96GqrzQ8c; Fri, 23 Feb 2024 17:36:57 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 41NHavXV083775; Fri, 23 Feb 2024 17:36:57 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 41NHav16083772; Fri, 23 Feb 2024 17:36:57 GMT (envelope-from git) Date: Fri, 23 Feb 2024 17:36:57 GMT Message-Id: <202402231736.41NHav16083772@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Stefan =?utf-8?Q?E=C3=9Fer?= Subject: git: 6831288c8c40 - releng/13.3 - msdosfs: fix potential inode collision on FAT12 and FAT16 List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: se X-Git-Repository: src X-Git-Refname: refs/heads/releng/13.3 X-Git-Reftype: branch X-Git-Commit: 6831288c8c4091c533c590d2d3cbb07459f2d28b Auto-Submitted: auto-generated The branch releng/13.3 has been updated by se: URL: https://cgit.FreeBSD.org/src/commit/?id=6831288c8c4091c533c590d2d3cbb07459f2d28b commit 6831288c8c4091c533c590d2d3cbb07459f2d28b Author: Stefan Eßer AuthorDate: 2024-02-20 12:02:24 +0000 Commit: Stefan Eßer CommitDate: 2024-02-23 12:42:34 +0000 msdosfs: fix potential inode collision on FAT12 and FAT16 FAT file systems do not use inodes, instead all file meta-information is stored in directory entries. FAT12 and FAT16 use a fixed size area for root directories, with typically 512 entries of 32 bytes each (for a total of 16 KB) on hard disk formats. The file system data is stored in clusters of typically 512 to 4096 bytes, depending on the size of the file system. The current code uses the offset of a DOS 8.3 style directory entry as a pseudo-inode, which leads to inode values of 0 to 16368 for typical root directories with 512 entries. Sub-directories use 2 cluster length plus the byte offset of the directory entry in the data area for the pseudo-inode, which may be as low as 1024 in case of 512 byte clusters. A sub-directory in cluster 2 and with 512 byte clusters will therefore lead to a re-use of inode 1024 when there are at least 32 DOS 8.3 style filenames in the root directory (or 11 14-character Windows long file names, each of which takes up 3 directory entries). FAT32 file systems are not affected by this issue and FAT12/FAT16 file systems with larger cluster sizes are unlikely to have as many directory entries in the root directory as are required to cause the collision. This commit leads to inode numbers that are guaranteed to not collide for all valid FAT12 and FAT16 file system parameters. It does also provide a small speed-up due to more efficient use of the vnode cache. PR: 277239 Reviewed by: mckusick Approved by: re (cperciva) (cherry picked from commit 445d3d227e68f85157d0301d1706aa488e8423da) (cherry picked from commit a495e7f5c5c2088bf32cd7349e2ca344ee089552) --- 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;