[Bug 277239] Potential inode collision on FAT12 and FAT16 causes directory corruption

From: <bugzilla-noreply_at_freebsd.org>
Date: Fri, 23 Feb 2024 10:43:44 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=277239

            Bug ID: 277239
           Summary: Potential inode collision on FAT12 and FAT16 causes
                    directory corruption
           Product: Base System
           Version: Unspecified
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: se@FreeBSD.org

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 (max.
supported is 32 KB)
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
directory 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, 8192 in case of 4 KB clusters.

This issue is demonstrated by the following test script:

#!/bin/sh

FS=/mnt/MSDOSFS-TEST
MDUNIT=0

cleanup () {
        cd /
        umount /dev/md$MDUNIT
        rm -rf $FS
        fsck_msdosfs -n /dev/md$MDUNIT
        mdconfig -u $MDUNIT -d
}

mdconfig -u $MDUNIT -t malloc -s 4m
newfs_msdos -F 16 -c 1 /dev/md$MDUNIT
mkdir -p $FS
mount -t msdos /dev/md$MDUNIT $FS

trap "cleanup" EXIT

cd $FS
mkdir TESTDIR
touch TESTDIR/TEST

for i in $(jot 33)
do
        touch TEST.$i
done

This script reports an error when writing the 32nd entry and the file system
will have been remounted r/o when the 33rd file is to be written:

touch: TEST.32: Bad file descriptor
touch: TEST.33: Read-only file system

The 32th file gets a pseudo-inode value of 1024, the same value already
assigned to TESTDIR, leading to a directory and a file with identical inode
numbers.

The patch in review D43978 changes the calculation of pseudo-inodes to account
for the actual number of directory entries in the root file system and avoids
the collision for all supported file-system parameters.

-- 
You are receiving this mail because:
You are the assignee for the bug.