# DF-3132 verification

Kernel: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64

## Bottom line

A FAT32 BPB with bpbFATs=1 and bpbExtFlags=0x8F (mirror bit set, active FAT 15) mounts successfully: msdosfs_vfsops.c:409-410 sets pm_curfat=15 without ever checking it against pm_FATs, and every subsequent FAT read AND write is displaced 15*FATsecs sectors past the real FAT by fatblock (msdosfs_fat.c:87). After creating NEW.TXT on the RW mount and unmounting, the image shows the real FAT sector 32 unchanged (entry 7 still free) while the EOC chain write for cluster 7 landed at sector 152 inside CANARY.BIN data clusters - kernel-mediated writes outside the FAT region, silently corrupting file data. The landing zone had been pre-seeded with a copy of the real FAT so the displaced reads see a workable filesystem, proving the kernel operates consistently against the wrong blocks.

## Kernel references
- sys/vfs/msdosfs/msdosfs_vfsops.c:409-410
- sys/vfs/msdosfs/msdosfs_fat.c:87

## Exploit chain
(none: availability/correctness finding; no privilege chain)

## Fix

reject pm_curfat >= pm_FATs and pm_FATs == 0 at mount; combined fixed kernel: the crafted volume is refused with bad active FAT and no FAT byte is written anywhere

See fix.diff in this directory (git-apply-able against the read-only sys/
tree; applied only inside the disposable verification guest).

## Reproduction

build: host: python3 craft_curfat.py out.img (FATs=1 extflags=0x8F; landing zone seeded with a FAT copy)

run: guest: vnconfig -c -S 64m /dev/vn0 img && mount_msdos /dev/vn0 /mnt && echo hi > /mnt/NEW.TXT && umount, then hexdump sectors 32 and 152

expected: real FAT unchanged; NEW.TXT chain (entry 7 EOC) written at sector 152 inside CANARY.BIN clusters

## Notes on the PoC (what changed vs the finding sketch)

initial canary filled the landing zone with 0xAA, which made the displaced FAT census read all clusters as busy (ENOSPC before any write); the zone now carries a copy of the real FAT so the displaced reads work and the misplaced WRITE is observable

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
