DF-3159 / verdict.json
{ "finding_id": "DF-3159", "status": "reproduced", "reproduced": 1, "impact": "corruption", "confidence": "certain", "verdict": "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.", "exploit_chain": "", "evidence": "run.log: ftruncate OK, in-memory size 0x100010000, size-after-remount=65536", "kernel_refs": [ "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" ], "poc_changes": "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", "attempts": 3, "guest_uname": "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", "runtime_sec": 300, "guest_dirty": 0, "build_cmd": "host: python3 craft_fat32big.py head; guest: truncate -s 4831838208 img + dd head at 0; cc trunc.c / trunc_step.c", "run_cmd": "guest: vnconfig -c -S 4608m, mount_msdos, paced growth then final ftruncate 0x100010000, umount, remount, stat", "code_hash": "b1b71fa3ef4deac878f94fce41633b315aec42f911fdfe4f33e2ba7c9e60b5fa", "notes": "A/B on fixed kernel: ftruncate(0x100010000) returns EFBIG instantly (errno 27) with zero allocation; legal sizes still succeed.", "recommended_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" } |