DF-5624 / verdict.json
{ "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" } |