⬢ DragonFlyBSD Kernel Audit
DF-5624 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5624",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "hard_sniff()s frame-chain guard (mp_flame.c:136 rbp > top - 8) admits rbp == top-8, and the return-address load at rbp+8 (mp_flame.c:138) then reads [top, top+8) -- 8 bytes past the interrupted threads kernel stack. Reproduced twice on the stock guest kernel as a fatal trap 12 page fault inside hard_sniff (hard_sniff+0x9e: movq 0x8(%rdx),%rax) with the faulting VA exactly == kstack top and the neighbour page recorded UNMAPPED by the instrumented rig; mapped neighbours silently copy an adjacent kernel-heap qword into the flame entry (observed 0x203a343236354644 = kprintf scratch DF5624: ). One-line guard fix (top-8 -> top-16) built via nativekernel, installed, rebooted: identical 150-iteration loop completes with >=111 unmapped-neighbour survivals, zero panics, and zero entries with rips[1] != 0. Local DoS ceiling: read-only sink, root-gated arming (SYSCAP_NOSYSCTL_WR), so no uid=0 chain exists from this bug.",
  "exploit_chain": "No escalation chain: primitive is an 8-byte read-only overshoot whose sink (debug.flame_graph_data) requires SYSCAP_RESTRICTEDROOT; no write primitive, no register control, fault address not attacker-chosen. Ceiling = panic (DoS) once an admin arms debug.flame_graph_enable; unprivileged users then supply triggers via kern.cputime polling (kern_clock.c:161-174) or the automatic ipiq-stall sniff (lwkt_ipiq.c:264,272).",
  "evidence": "panic.txt (v2 rig: NEIGHBOR UNMAPPED for top=0xfffff801185da000 then Fatal trap 12, fault VA == top, Stopped at hard_sniff+0x9e); panic-v1-module.txt (first incidental panic, same signature, 1-in-43 loads); run_fixed.log (patched kernel: survived UNMAPPED-neighbour sniffs, 0 nonzero rips[1]); build.log (kmod build); fix_build_tail.log (nativekernel RC=0); flame_dump.c output in transcripts (entry windex=1 rips[0]=magic rips[1]=OOB qword); VERDICT.md for the full narrative.",
  "kernel_refs": [
    "sys/platform/pc64/x86_64/mp_flame.c:136",
    "sys/platform/pc64/x86_64/mp_flame.c:138",
    "sys/platform/pc64/x86_64/mp_flame.c:124-129",
    "sys/platform/pc64/x86_64/mp_flame.c:182-195",
    "sys/kern/kern_sysctl.c:1446-1448",
    "sys/kern/kern_clock.c:161-174",
    "sys/kern/lwkt_ipiq.c:264-272",
    "sys/platform/pc64/x86_64/machdep.c:3656"
  ],
  "poc_changes": "Rewrote the seed concept into a KLD that calls the exported production hard_sniff() with a crafted trapframe (tf_rbp == kstack-top-8, magic tf_rip) instead of relying on probabilistic natural sampling; v2 added a safe read-only 4-level page-table walk via PHYS_TO_DMAP (present-bit checked each level, never dereferences a non-present target) so the console records NEIGHBOR MAPPED|UNMAPPED before the call, plus a userland flame_dump.c observer that parses debug.flame_graph_data to read back the recorded OOB qword. Module writes no kernel memory.",
  "attempts": 5,
  "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 (baseline); fix validated on #1: Thu Oct 8 22:24:57 UTC 2026",
  "runtime_sec": 3400,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df5624 && sh build.sh (cc -O flame_dump.c; in-tree kmod: make in /usr/src/sys/platform/pc64/x86_64/df5624)",
  "run_cmd": "cd /root/df5624 && ITERS=150 sh decisive2.sh",
  "code_hash": "bcba951badf25709c0d6bf692519691b9ea69f3605458d489fee721dc937e0ad",
  "notes": "Twin guard bug exists in pcpu_timer_always() at sys/platform/pc64/x86_64/machdep.c:3656 (manual-debug path gated by flame_poll_debug) -- out of this files scope, flagged for that files audit. ebytes header at mp_flame.c:161-162 is wrong-but-harmless (only consumer usr.bin/flame_graph/collect.c ignores it). Task briefs description of this file (tsc/PIPT framebuffer, mp relay/barriers, mptable) does not match its contents; audited as-found.",
  "recommended_fix": "Change the hard_sniff() chain-walk guard from rbp > top - 8 to rbp > top - 16 (frame spans [rbp, rbp+16)); same one-liner for the twin in machdep.c pcpu_timer_always().",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff applied to guest /usr/src; make -j8 nativekernel KERNCONF=X86_64_GENERIC RC=0; make installkernel RC=0; rebooted into #1 Thu Oct 8 22:24:57 UTC 2026. Baseline (stock kernel): fatal trap 12 in hard_sniff+0x9e at first unmapped-neighbour load (panic.txt). Patched: identical 150-iteration loop, >=111 unmapped-neighbour loads survived, no panic, flame dump 0 entries with rips[1]!=0 -- bad behavior gone.",
  "fix_evidence": "run_fixed.log; fix_build_tail.log (nativekernel RC=0); panic.txt (baseline); VERDICT.md sections 3-4"
}