{
  "finding_id": "DF-5825",
  "status": "reproduced",
  "verdict": "Peer-triggered kernel UAF reproduced on the live guest. Three wire messages from the far end of an iocom link (established here via the xdisk socketpair rig) make kdmsg_state_msgrx() accept REPLY|CREATE against a peer-initiated staterd_tree state (lookup direction chosen solely by the attacker-cleared REVTRANS bit, kern_dmsg.c:807-816) and overwrite rxcmd including the REPLY bit (kern_dmsg.c:986); the subsequent REPLY|DELETE then executes RB_REMOVE() against statewr_tree for a state linked in staterd_tree (kern_dmsg.c:1080-1084), nulling statewr_trees root (orphaning the live LNK_CONN state) and leaving staterd_tree.rbh_root dangling at the state that cleanuprx frees a moment later. Proven three ways: (1) pure-peer INVARIANTS kernel panic assertion msg->any.head.cmd & DMSGF_REPLY failed at kern_dmsg.c:1082 (deterministic, 3 messages); (2) /dev/kmem forensics showing statewr.root=0 with conn_state live, staterd.root= freed state refs=0, injected rxcmd=0xe0300101 visible in the freed object, and subsequent peer messages reading/writing through the freed chunk; (3) with controlled content in the freed chunk (simulated groom via /dev/kmem because aux allocations are 64-byte aligned and cannot land in the 160-byte state zone), a fatal trap 9 in kdmsg_state_tree_RB_FIND at cmpq 0x58(%rax),%rdx with rax=0x4242424242424242 - a fully attacker-chosen kernel pointer dereference. Also observed: the poisoned tree wedges the writer-thread teardown loop (still terminating warnings). fix.diff (reject REPLY|CREATE/REPLY|DELETE on KDMSG_STATE_OPPOSITE states + select the DELETE-time tree by OPPOSITE flag) was built into a guest kernel: both attack rigs then completed with no panic, violations rejected with EINVAL, trees consistent (statewr.root intact), clean teardown.",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "exploit_chain": "1) Be/become the peer of any kernel dmsg iocom (hammer2 cluster node, dmaster/xdisk daemon, or a node on the link). 2) XX3|CREATE -> half-closed staterd state S (txcmd DELETE, rxcmd no DELETE, RBINSERTED). 3) XX3|REPLY|CREATE same msgid, REVTRANS=0 -> REPLY bit injected into S->rxcmd. 4) XX3|REPLY|DELETE -> RB_REMOVE from the WRONG tree; S freed; staterd_tree.rbh_root dangles at freed 160-byte chunk (slab zone 160/16+7). 5) Peer-driven RB_FIND/RB_INSERT/RB_REMOVE read+write through the freed chunk (proven). 6) Groom the 160-zone with peer-created states (msgid field attacker-controlled) to place fake rbnode content in the freed chunk (PoC simulates this step deterministically via /dev/kmem); RB_FIND then follows fully attacker-chosen rbe_left/rbe_right pointers -> arbitrary-address kernel dereference (fatal #GP at 0x4242424242424242 demonstrated). 7) RB_INSERT/RB_REMOVE rotations through fake nodes write kernel heap pointers at attacker-chosen addresses (arbitrary write primitive); combined with the DF-2708 msgid->state-address disclosure for target discovery and the guests absent KASLR/SMAP/SMEP this reaches credential overwrite / code execution. Steps 1-6 guest-proven; weaponizing step 7 into a uid=0 shell was not completed within this runs budget.",
  "evidence": "panic.txt (fatal trap 9, kdmsg_state_tree_RB_FIND+0x2a, cmpq 0x58(%rax),%rdx at attacker address); run.log (serial trace: dangling root confirmed refs=0 then trap); panic.oracle.txt (pure-peer 3-message INVARIANTS panic at kern_dmsg.c:1082); VERDICT.md (kmem forensics: statewr.root=0 with conn_state live, freed-state rxcmd=0xe0300101); fix_runs.log + build.log (patched kernel: no panic, EINVAL rejections, clean teardown)",
  "kernel_refs": [
    "sys/kern/kern_dmsg.c:807",
    "sys/kern/kern_dmsg.c:810",
    "sys/kern/kern_dmsg.c:971",
    "sys/kern/kern_dmsg.c:986",
    "sys/kern/kern_dmsg.c:1075",
    "sys/kern/kern_dmsg.c:1080",
    "sys/kern/kern_dmsg.c:1083",
    "sys/kern/kern_dmsg.c:1263",
    "sys/kern/kern_dmsg.c:1754",
    "sys/sys/tree.h:585",
    "sys/sys/tree.h:651"
  ],
  "poc_changes": "Original sketch had no rig: built the full xdisk socketpair rig (XDISKIOCATTACH passes one end of a userland socketpair into the kernel iocom; the rig speaks raw dmsg wire protocol as the peer). Key corrections during bring-up: (1) msg1 must be CREATE-only via an unsupported base command (0x00300101) so the xaio default handler replies kdmsg_msg_reply() leaving the staterd state half-closed (rxcmd without DELETE); a CREATE|DELETE one-shot makes line 1077 set rxcmd DELETE immediately and the state closes cleanly. (2) aux spray can never reclaim the state chunk: aux sizes are 64-byte aligned (DOALIGN) so they land in 128/192-byte slab zones while sizeof(kdmsg_state)=160 (zone 160/16+7); controlled-content step therefore uses /dev/kmem write standing in for the groom. (3) fake-state field offsets taken from a _KERNEL_STRUCTURES probe (iocom@88, msgid@120, refs@104).",
  "attempts": 8,
  "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 (INVARIANTS kernel)",
  "runtime_sec": 7200,
  "guest_dirty": 0,
  "build_cmd": "cc -O -o /root/escalate /root/escalate.c && cc -O -o /root/oracle /root/oracle_inject.c && cc -O -D_KERNEL_STRUCTURES -I/usr/src/sys -o /root/probe_state /root/probe_state.c",
  "run_cmd": "kldload xdisk; /root/oracle; /root/escalate",
  "code_hash": "006fbad51a2f75530eb2d0ea4bb446bf610852955f3dcb370948eec64ffd9889",
  "notes": "Guest-live evidence class: loopback iocom socketpair rig driving the real kernel transport (xdisk module, /dev/xdisk XDISKIOCATTACH). Root used only for rig plumbing (device open, ioctl, /dev/kmem introspection); the attack itself is pure peer wire input. Baseline panics reproduced across >=3 independent boots; patched-kernel validation ran both rigs to completion (fix_status fixed). The freed-chunk reclaim-by-groom (step 6) was demonstrated via /dev/kmem content injection; pure-peer reclaim uses state allocations whose msgid field is attacker-controlled. Secondary peer-triggered effect observed: writer-thread teardown loop never terminates on the poisoned tree.",
  "recommended_fix": "Reject REPLY|CREATE / REPLY|DELETE received against KDMSG_STATE_OPPOSITE (staterd_tree) states in kdmsg_state_msgrx(); select the DELETE-time RB_REMOVE tree by the states OPPOSITE side instead of the peer-smearable rxcmd REPLY bit (see fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff applied to a rebuilt X86_64_GENERIC kernel: baseline panics (assertion at kern_dmsg.c:1082; fatal trap 9 in kdmsg_state_tree_RB_FIND) no longer occur; the oracle injection test completes without panic and the plain DELETE then closes the state from the correct tree; the full escalate chain aborts at its own safety guard because the wrong-tree removal never happens (statewr.root remains the live conn_state, matching an intact tree); serial shows the violations rejected with msgrx: REPLY on received state / msgrx: REPLY|DELETE on received state (EINVAL) and clean xaio_exit teardown. First fix revision was caught by validation leaving a pre-existing else-branch assert reachable via un-injected REPLY|DELETE; the final fix closes both REPLY cases.",
  "fix_evidence": "fix_runs.log (both rigs full output on patched kernel), build.log (nativekernel build DONE_RC=0), serial in run.sh output captured in VERDICT.md"
}