⬢ DragonFlyBSD Kernel Audit
DF-3040 / verdict.json
← back to finding ↓ download raw
{
 "finding_id": "DF-3040",
 "status": "reproduced",
 "reproduced": 1,
 "impact": "panic",
 "confidence": "certain",
 "verdict": "REPRODUCED twice on the stock INVARIANTS kernel (fresh vm.sh reset with-src between runs): mounting a newfs_hammer image whose vol0_blockmap[3] undo map was patched to zone3 short offset 0x400000000 (idx 2048, bp+17288) resp. 0x4000000000 (idx 32768, bp+263048) panics in hammer_undo_lookup+0x84 \u2014 the faulting instruction addq 0x388(%rcx,%rdx,8),%rbx is exactly the unbounded vol0_undo_array[HAMMER_UNDO_INDEX(zone3)] load (0x388=904=offsetof), reading past the 16KB rootvol bp at attacker-chosen distance (up to ~4GB reach, idx<2^29). The only undo-path bounds (hammer_recover.c:232 first/next vs alloc_offset; hammer_undo.c:70 KKASSERT vs the same alloc_offset) are all derived from the attacker-crafted vol0_blockmap[3], so none constrains the index against HAMMER_MAX_UNDO_BIGBLOCKS=128 (constant unreferenced in sys/). Impact ceiling: deterministic mount-time kernel panic on INVARIANTS (guest wedged at db> both runs); on non-INVARIANTS kernels an attacker-aimed OOB kernel read whose value steers a zone-2 offset (no userspace disclosure of the OOB bytes demonstrated; the in-bounds idx 128..1792 variant additionally yields a fully attacker-known zone-2 offset from the attackers own image bytes past the header struct). Fixed and validated: fix.diff bounds zone3_off to the formats 128-bigblock undo range in hammer_undo_lookup (EIO); on the rebuilt kernel #1 the identical PoC fails the mount cleanly with I/O error and the guest stays up; stock-image mount/create/rm/sync/umount regression passes.",
 "exploit_chain": "",
 "evidence": [
  "panic_idx32768.txt: Stopped at hammer_undo_lookup+0x84: addq 0x388(%rcx,%rdx,8),%rbx with fault VA 0xfffff800641f6380 (page not present) \u2014 the vol0_undo_array[idx] load faulted 240KB past the 16KB bp",
  "panic_idx2048.txt: same instruction, fault VA 0xfffff80060cea380 for idx 2048 (bp+17288) \u2014 distance tracks the crafted index exactly",
  "run.log: craft output undo AFTER first=3000004000000000 \u2026 idx(first)=32768 -> read at bp+263048 followed by the trap; both baseline runs wedged the guest (ssh timeout 124, vm.sh status down)",
  "fix_run.log (kernel #1 + fix.diff): same PoC -> mount: Input/output error, console Unable to read UNDO TAIL at 3000003ffffffff8 / recovery failure during seqno backscan / Failed to recover HAMMER filesystem on mount, guest stays up",
  "fix_build.log: make nativekernel KERNCONF=X86_64_GENERIC completed; uname DragonFly 6.5-DEVELOPMENT #1 Sat Sep 5 16:07:13 UTC 2026",
  "run.log tail: freemap_probe on stock newfs image clean \u2014 DF-3011s blockmap.c:832 layer2 artifact is NOT a stock-kernel bug (deepforge grafting artifact)"
 ],
 "kernel_refs": [
  "sys/vfs/hammer/hammer_ondisk.c:688-689",
  "sys/vfs/hammer/hammer_ondisk.c:703",
  "sys/vfs/hammer/hammer_undo.c:58-76",
  "sys/vfs/hammer/hammer_disk.h:512",
  "sys/vfs/hammer/hammer_disk.h:789",
  "sys/vfs/hammer/hammer_disk.h:824-829",
  "sys/vfs/hammer/hammer_recover.c:232",
  "sys/vfs/hammer/hammer_recover.c:257-263",
  "sys/vfs/hammer/hammer_recover.c:798",
  "sys/vfs/hammer/hammer_vfsops.c:671"
 ],
 "poc_changes": "Pass-2 author wrote the PoC from scratch (no seed): undo_craft.c patches only vol0_blockmap[3] of a real newfs_hammer image (no CRC fixup needed \u2014 vol_crc is never verified, see DF-3042). One iteration: the first constant 0x400000000 is 2^34 (idx 2048), kept as default because it already faults 904B past the bp; the parametrized run at 0x4000000000 (idx 32768) demonstrates the far reach. Fixed an argv-check bug found during run 2.",
 "attempts": 3,
 "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": 3240,
 "guest_dirty": 1,
 "build_cmd": "sh build.sh (cc -O -o undo_craft undo_craft.c -I/usr/src/sys/vfs/hammer; truncate 12G + vnconfig + newfs_hammer -L uabase + vnconfig -u)",
 "run_cmd": "sh run.sh 0x4000000000",
 "code_hash": "d69bc7a3943abffd117d4cb53df26cf8e46f415661747d9d6a7775c6a6f889a1",
 "notes": "Memory-corruption class: impact honestly classified as panic (deterministic DoS from crafted image) \u2014 the OOB read value is not returned to userspace; on non-INVARIANTS kernels the primitive is an attacker-aimed kernel read (CWE-125) with idx up to 2^29. Mount of crafted image needs root (or vfs.usermount=1), same precondition family as DF-0797/DF-0798. Priority-7 freemap off-by-8 investigated and refuted (freemap_probe.sh clean on stock and fixed kernels). DF-0776s proposed count/type validation is still NOT in-tree (only KKASSERTs in hammer_btree.c); DF-0797/DF-0798 also remain unfixed in-tree.",
 "recommended_fix": "In hammer_undo_lookup(), reject zone3_off >= HAMMER_ENCODE_UNDO(HAMMER_MAX_UNDO_BIGBLOCKS * HAMMER_BIGBLOCK_SIZE64) with EIO before calling hammer_xlate_to_undo() (see fix.diff)",
 "fix_status": "fixed",
 "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Sat Sep 5 16:07:13 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
 "fix_baseline_reproduced": 1,
 "fix_patched_reproduced": 0,
 "fix_verdict": "fix.diff applied to the guests /usr/src copy only (audit tree untouched; git apply --check clean against sys/), make nativekernel KERNCONF=X86_64_GENERIC + installkernel, reboot into kernel #1. Identical PoC (run.sh 0x4000000000) now fails cleanly: mount: Input/output error via EIO from hammer_undo_lookup -> recovery failure during seqno backscan -> Failed to recover HAMMER filesystem on mount; no panic, guest stays up. Regression on fixed kernel: stock newfs_hammer image mount + file create/rm/sync/umount cycle clean.",
 "fix_evidence": [
  "fix_run.log: mount: Input/output error (SSH_RC=1, guest up)",
  "run.log console section (fixed kernel): HAMMER(uabase) Unable to read UNDO TAIL at 3000003ffffffff8 / recovery failure during seqno backscan / Failed to recover HAMMER filesystem on mount",
  "fix_build.log: kernel build + install completed; uname #1 Sat Sep 5 16:07:13 UTC 2026"
 ]
}