DF-3750 / verdict.json
{ "finding_id": "DF-3750", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "rt2860_tx (rt2860.c:1536) and rt2860_tx_raw (rt2860.c:1824) take SLIST_FIRST(&sc->data_pool) with only a comment claiming the pool is non-empty; the sole empty-guard is rt2860_starts dequeue loop (rt2860.c:2058). The raw-xmit path (rt2860_raw_xmit rt2860.c:1788/1794, driven by net80211 management frames incl. hostap probe responses) bypasses it. Pool capacity is 128 (rt2860var.h:23) while ring admission allows ~63 single-segment frames on each of 6 rings (~378 > 128) with qfullmsk tracking only per-ring fullness -- under downlink congestion or a power-save peer, a management frame at the wrong moment makes SLIST_FIRST return NULL and txwi = data->txwi (rt2860.c:1582/1848) NULL-write-panics the kernel. Deterministic panic (DoS), remotely assistable (probe requests keep the raw path busy), no corruption beyond the NULL write. Not reproduced: guest has no Ralink NIC (env.txt); the capacity arithmetic is exact.", "exploit_chain": "saturate >=2 Tx rings with unacknowledged frames (iperf / PS peer) -> pool (128) empties while rings still admit -> attackers probe request triggers ieee80211_send_mgmt -> ieee80211_raw_output -> rt2860_raw_xmit -> rt2860_tx with empty pool -> NULL->txwi deref -> Fatal trap 12 panic (DoS).", "evidence": "README.md (exact capacity math + recipe), VERDICT.md, fix.diff (raw_xmit guard, git apply --check passes)", "kernel_refs": [ "sys/dev/netif/ral/rt2860.c:1536", "sys/dev/netif/ral/rt2860.c:1582", "sys/dev/netif/ral/rt2860.c:1744", "sys/dev/netif/ral/rt2860.c:1788", "sys/dev/netif/ral/rt2860.c:1824", "sys/dev/netif/ral/rt2860.c:2058", "sys/dev/netif/ral/rt2860var.h:21", "sys/dev/netif/ral/rt2860var.h:23", "sys/netproto/802_11/wlan/ieee80211_output.c:635" ], "poc_changes": "No PoC source: needs the NIC + radio load. Recipe documented.", "attempts": 1, "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", "runtime_sec": 10, "guest_dirty": 0, "build_cmd": "", "run_cmd": "dfbsd-qemu/vm.sh run_root pciconf -lv | grep ralink", "code_hash": "", "notes": "Invariant comment the data pool contains at least one element (rt2860.c:1535) is provably violable across rings; FreeBSD ral shares the structure but this finding is filed against the DFBSD tree as audited.", "recommended_fix": "Guard rt2860_raw_xmit with SLIST_EMPTY(&sc->data_pool) (drop frame, ENOBUFS), matching rt2860_start:2058.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Minimal guard in the unguarded call path; compile-consistent; runtime validation needs hardware.", "fix_evidence": "fix.diff (git apply --check passes against pristine sys/)" } |