# DF-3159 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

On a FAT32 volume with 64-KiB clusters and 4.5 GiB capacity, ftruncate(0x100010000) (4 GiB + 64 KiB) SUCCEEDS - msdosfs_setattr has no upper bound, unlike msdosfs_write which enforces MSDOSFS_FILESIZE_MAX - and the in-memory size reads 4295032832. DE_EXTERNALIZE stores the dirent size field with putulong, so after unmount+remount the same file is 65536 bytes: 4 GiB of file silently vanished (silent data loss; POSIX expects EFBIG). The 4-GiB deextend zero-fill exceeds this 3.7-GiB-RAM guest when issued as a single syscall (two full-guest wedges recorded), so the trigger paces the growth in 64-MiB steps with sync. Own-file data loss on a volume the mounter chose; no cross-privilege impact.

## Kernel references
- sys/vfs/msdosfs/msdosfs_vnops.c:371-399
- sys/vfs/msdosfs/msdosfs_denode.c:509-511
- sys/vfs/msdosfs/msdosfs_denode.c:636
- sys/vfs/msdosfs/msdosfs_vnops.c:618

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

## Fix

reject va_size > MSDOSFS_FILESIZE_MAX with EFBIG in setattr; combined fixed kernel: the same ftruncate returns EFBIG and the file stays 4 GiB minus one step

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_fat32big.py head; guest: truncate -s 4831838208 img + dd head at 0; cc trunc.c / trunc_step.c

run: guest: vnconfig -c -S 4608m, mount_msdos, paced growth then final ftruncate 0x100010000, umount, remount, stat

expected: ftruncate succeeds; file shrinks to 65536 after remount (0x10000 = low 32 bits)

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

single-shot ftruncate of the full 4 GiB wedged the guest twice (deextend zero-fills every new cluster through the buffer cache; dirty backlog starves sshd); the pacing harness (trunc_step.c / 64-MiB shell steps with sync) completes in ~2 minutes

## 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.
