⬢ DragonFlyBSD Kernel Audit
DF-3554 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3554",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "v1 ng_tee admits the same pure-topology forwarding cycle as its ng7 twin (DF-3553): two tees cross-wired T1.left<->T2.left / T1.right<->T2.right with the sockets tap hook on T1.left2right as entry edge. v1 ng_send_data forwards synchronously with no hop bound, and ngt_rcvdata adds a per-hop m_dup/m_freem; one root-injected 1-byte sendto deterministically (4/4) wedges the whole machine: ssh/ICMP dead, console silent, no banner or dump, terminal states observed = kernel-debugger-entry polling an unservicable console (siocngetc, IF=0, Xcpustop on other CPUs), all-CPU catatonia, and a cross-CPU memmove/DELAY deadlock. QEMU-monitor stack walk proves the sendto->ngd_send->ng_send_data->ngt_rcvdata->m_dup chain live on the wedged thread. Root-gated (v1 ngc_attach caps_priv_check).",
  "exploit_chain": "root builds graph with 3 control messages + 1-byte sendto -> unbounded synchronous v1 forwarding recursion interleaved with mbuf churn -> unrecoverable whole-machine deadlock (worse than a clean panic: no dump, no auto-reboot). No uid=0 path: no memory corruption; trigger requires root.",
  "evidence": "run.log (graph built, injection hangs); wedge_forensics.txt (RIP samples symbolized to m_free/m_dup_pkthdr/netgraph.ko/ng_tee.ko, CPU terminal states, the symbolized kstack walk ending at ngd_send + tap sockaddr residue); boot_tail.txt (no panic output); fix1_cycle.log (patched: sendto errno=62 ELOOP, survives)",
  "kernel_refs": [
    "sys/netgraph/tee/ng_tee.c:277",
    "sys/netgraph/tee/ng_tee.c:311",
    "sys/netgraph/tee/ng_tee.c:339",
    "sys/netgraph/netgraph/ng_base.c:1678"
  ],
  "poc_changes": "Authored fresh (no seed); same source as DF-3553 without -DNG7 (v1 NG_VERSION 2 ABI).",
  "attempts": 5,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:52 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 3300,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o /root/poc/tee_cycle_v1 /root/poc/tee_cycle.c",
  "run_cmd": "kldload netgraph ng_socket ng_tee && /root/poc/tee_cycle_v1",
  "code_hash": "d2fcdce4fbe488ca122665b7f4bc77e29181a82ee05c2874d52ebfa5ac31da5b",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fixed",
  "fix_evidence": "fix.diff adds NG_SEND_DEPTH_MAX=16 nesting bound (atomic counter, ELOOP + data free) to v1 ng_send_data; netgraph.ko rebuilt -Werror clean in guest /usr/src, loaded with stock ng_socket/ng_tee: same graph + injection -> STEP sendto errno=62 (ELOOP), RESULT no-panic survived 30s, RUN_RC=0, guest healthy (fix1_cycle.log). Stock wedges 4/4.",
  "notes": "v1 twin of DF-3553; same class as DF-3546 (v1 ng_bpf cycle) but terminal state is a hard wedge rather than a clean double fault (per-hop m_dup churn changes the resource profile). v1 has no FLOW_COOKIE (DF-0727 has no v1 twin).",
  "recommended_fix": "Depth-bound nested synchronous forwarding in v1 ng_send_data (fix.diff); upstream may prefer queueing instead of recursion."
}