โฌข DragonFlyBSD Kernel Audit
DF-2614 / verdict.json
โ† back to finding โ†“ download raw
{
  "finding_id": "DF-2614",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "REPRODUCED on the stock INVARIANTS kernel and FIX VALIDATED on a rebuilt kernel. (1) Heap-pointer leak: mounting a hammer2 volume with cluster_fd = our socketpair end (hammer2_vfsops.c:1350-1357) and issuing HAMMER2IOC_REMOTE_ADD (hammer2_ioctl.c:308) as root prints 'volconf update 0xfffff801177797c0' (hammer2_iocom.c:376, %p of the kmalloc'd conn_state kdmsg_state_t set at kern_dmsg.c:189-190) to the console/msgbuf twice (ioctl + unmount-teardown via hammer2_autodmsg); a second unprivileged local user reads the pointer with plain 'dmesg | grep \"volconf update\"' (live-captured; msgbuf world-readable, lines also in /var/log/messages). Related ungated prints confirmed live: VOLDATA DUMP/INITIATE SPANs (:220/:236) fire at ordinary root-fs boot and unmount teardown, and vfsops prints 'hammer2_mount: hmp=%p pmp=%p' per mount (adjacent same-class sites, for the record). (2) Peer-driven console/msgbuf flood: 1000 one-way LNK_PAD frames from the cluster-socket peer produce exactly 1000 ungated 'RCVMSG %08x' kprintf lines (hammer2_iocom.c:135 via kern_dmsg.c:1220 default branch; rx validates only magic+size, no CRC, kern_dmsg.c:343-352) โ€” one console-lock+serial line per peer message, no flag, no rate limit. After fix.diff (drop the %p print, drop RCVMSG print, gate the four remaining prints behind hammer2_debug & 0x0100): identical trigger yields DELTA_volconf=0, DELTA_rcvmsg=0, REMOTE_ADD_OK, 1000 frames accepted per protocol, UNMOUNT_OK โ€” no functional regression. Low severity confirmed: local trigger paths are root-gated; exposure is (unprivileged) msgbuf/log read of a heap pointer and a cluster-peer-driven console/log flood; KASLR-defeat value applies to KASLR-enabled kernels (audit guest has none).",
  "exploit_chain": "root mounts hammer2 w/ cluster_fd (or any cluster CONN/remote-add history) -> kprintf volconf update %p (heap kdmsg_state_t) -> msgbuf + /var/log/messages -> unprivileged 'dmesg' read yields live kernel heap address (KASLR defeat material); cluster peer streams one-way unknown/LNK_PAD frames -> one RCVMSG kprintf per frame -> console-lock monopolization + msgbuf ring eviction",
  "evidence": [
    "findings/poc/DF-2614/run.log โ€” FULL untrimmed stock-kernel run: 'volconf update 0xfffff801177797c0' x2, AFTER_rcvmsg=1000, TRANSMIT=2, sample RCVMSG lines",
    "findings/poc/DF-2614/unpriv_read.log โ€” live capture: user maxx reads the pointer via dmesg (count=2 + values) and /var/log/messages (count=2)",
    "findings/poc/DF-2614/run.fix.log โ€” same trigger on fix kernel: DELTA_volconf=0, DELTA_rcvmsg=0, REMOTE_ADD_OK, UNMOUNT_OK",
    "findings/poc/DF-2614/fix.diff โ€” pointer print removed, message-path prints gated behind hammer2_debug & 0x0100"
  ],
  "kernel_refs": [
    "sys/vfs/hammer2/hammer2_iocom.c:135",
    "sys/vfs/hammer2/hammer2_iocom.c:220",
    "sys/vfs/hammer2/hammer2_iocom.c:236",
    "sys/vfs/hammer2/hammer2_iocom.c:241",
    "sys/vfs/hammer2/hammer2_iocom.c:376",
    "sys/vfs/hammer2/hammer2_iocom.c:378",
    "sys/vfs/hammer2/hammer2_vfsops.c:1350",
    "sys/vfs/hammer2/hammer2_ioctl.c:308",
    "sys/kern/kern_dmsg.c:189",
    "sys/kern/kern_dmsg.c:343",
    "sys/kern/kern_dmsg.c:1220"
  ],
  "poc_changes": "no seed existed; trigger written fresh (had to add errno.h include on first compile). Cluster connectivity obtained without the userland service daemon by passing a socketpair end as info.cluster_fd directly to mount(2), making the PoC process the cluster peer for the PAD-frame flood; REMOTE_ADD issued via ioctl on a file of the mounted volume.",
  "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": 2400,
  "guest_dirty": 0,
  "build_cmd": "cc -O -I/usr/src/sys -o df2614_trigger df2614_trigger.c   (in guest, /root/poc/df2614/)",
  "run_cmd": "dfbsd-qemu/vm.sh run_root 'sh /root/poc/df2614/run_df2614.sh'   (image prep + build + run + dmesg deltas)",
  "code_hash": "b053a74e1ef1990953cacb08bc0b8bccae5644983bf3943d88f8ce7ec9b13804",
  "notes": "Fix validated on rebuilt X86_64_GENERIC (nativekernel) kernels #3 and #5. Write-side absorbs 1000 frames in ~4ms (socket buffer); kernel emits one console+msgbuf line per frame โ€” the flood cost is per-message console/serial output, unbounded by any flag. Extra same-class ungated pointer prints observed live and left for the record (not part of this finding's lines): 'hammer2_mount: hmp=%p pmp=%p' (hammer2_vfsops.c) fires on every device mount.",
  "recommended_fix": "remove the %p kprintf at hammer2_iocom.c:376 and the per-message RCVMSG print at :135; gate the remaining message-path debug prints behind (hammer2_debug & 0x0100) as fix.diff does",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #5: Sat Aug 29 11:12:52 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "baseline (stock #0): 2 volconf pointer lines + 1000 RCVMSG lines; patched (#3 and #5, fix.diff applied, nativekernel rebuild + reboot): 0 and 0 with REMOTE_ADD_OK/UNMOUNT_OK and all 1000 peer frames still accepted โ€” leak and flood eliminated, no functional regression",
  "fix_evidence": "findings/poc/DF-2614/run.fix.log; findings/poc/DF-2614/run.log (baseline contrast)"
}