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