DF-3152 / verdict.json
{ "finding_id": "DF-3152", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "Single privileged HAMMERIOC_ADD_VOLUME ioctl with vol_size claiming 2 GiB on a 2 MiB vn device panics the stock INVARIANTS kernel deterministically (twice, identical signature): hammer_format_volume_header derives vol_buf_end from the unchecked user value, hammer_install_volume never compares it against the devices real size, and hammer_format_freemaps layer2 breads walk past the device end -> panic: cluster_callback: unexpected EOF. On non-INVARIANTS kernels the same failure is worse silently: KKASSERTs compile out and hammer_update_volumes_headers unconditional return 0 overwrites the error, so the ioctl returns SUCCESS with a half-formatted volume installed and vol_count bumped on every member. Privileged (SYSCAP_NOVFS_IOCTL) trigger; also reachable as operator bad luck via transient device I/O error mid-add. Distinct from DF-0869 (integer overflow of the beg/end arithmetic); this is the missing device-size cross-check plus broken error-path discipline.", "exploit_chain": "n/a - privileged kernel panic/DoS + silent filesystem corruption primitive; no unprivileged route (ioctl double-gated on SYSCAP_NOVFS_IOCTL at hammer_ioctl.c:72,197)", "evidence": [ "run.log:45-55 Initialize freemap volume 1 -> panic: cluster_callback: unexpected EOF with cluster_callback/vnstrategy stack, guest at db>", "run.2.log identical signature from a clean vm.sh reset (deterministic)", "VERDICT.md line-accurate trace incl. the production-kernel error-overwrite analysis (hammer_volume.c:117-130, hammer_volume.c:673-739)", "build.log full compiler output" ], "kernel_refs": [ "sys/vfs/hammer/hammer_volume.c:662", "sys/vfs/hammer/hammer_volume.c:117-130", "sys/vfs/hammer/hammer_volume.c:415-476", "sys/vfs/hammer/hammer_volume.c:673-739", "sys/vfs/hammer/hammer_ondisk.c:109-272", "sys/vfs/hammer/hammer_ondisk.c:212", "sys/vfs/hammer/hammer_ondisk.c:709", "sys/vfs/hammer/hammer_ioctl.c:193-201" ], "poc_changes": "Seed sketch did not exist; authored from scratch. Notes: struct hammer_ioc_volume layout taken from /usr/src/vfs/hammer/hammer_ioctl.h in-guest (device_name is char[MAXPATHLEN], vol_size int64); include path is <vfs/hammer/hammer_ioctl.h> with -I/usr/src; ioctl issued on an O_RDONLY fd of the HAMMER1 mountpoint root.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 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": 30, "guest_dirty": 0, "build_cmd": "cc -O -I/usr/src -o voladd_lie voladd_lie.c", "run_cmd": "./voladd_lie /mnt/h1 /dev/vn1 2147483648 (vn0=12G sparse HAMMER1 fs rw at /mnt/h1, vn1=2MB)", "code_hash": "38ab12f7cc3d8c6a193ba1ad664d925e525b08a2f2e78cce6598036bdf29f212", "notes": "Panic manifests in cluster_callback (clustered read past EOF) rather than the predicted hammer_volume.c:118 KKASSERT - same root cause (unvalidated vol_size), the EOF-residual path fires first. Production-kernel variant (KKASSERT compiled out + error overwritten by hammer_update_volumes_headers unconditional 0 -> ioctl returns 0 with half-formatted volume) reasoned from source (hammer_volume.c:117-130 vs 673-739), not executable on the INVARIANTS guest. Also deletes cleanly: volume-del of a silently half-added volume later trips KKASSERT at hammer_volume.c:541/232.", "recommended_fix": "Validate the formatted vol_buf_end against the devices real size via DIOCGPART in hammer_install_volume (mirror HAMMER2 hammer2_ondisk.c:283-291), and replace the add paths KKASSERT/error-overwrite with real unwinding that uninstalls the volume and returns the error", "fix_status": "not_testable", "fix_kernel_uname": "", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored and verified to apply cleanly (patch -p1 --dry-run) but kernel rebuild validation not performed: Low-severity privileged DoS, not a reproduced memory-corruption finding (mandatory fix-build class)", "fix_evidence": [ "fix.diff" ] } |