DF-5261 / verdict.json
{ "finding_id": "DF-5261", "status": "inconclusive", "reproduced": false, "impact": "none", "confidence": "certain", "verdict": "mtw_drain_fifo() (if_mtw.c:2162-2224) loops for(;;) breaking only when !(stat & MTW_TXQ_VLD); the return value of mtw_read() is ignored and on USB error mtw_read() stores 0xffffffff (if_mtw.c:1284-1285), and MTW_TXQ_VLD=(1<<0) (if_mtwreg.h:702) is set in that value - so once the device stops answering reads (unplug, permanent stall, or a hostile device simply keeping the bit set), the loop never exits. It runs in the net80211 taskqueue thread via the cmdq (queued from mtw_tx() at 3206-3216 once per 11 frames in HOSTAP/MBSS/multi-vap modes) holding MTW_LOCK, wedging that taskqueue thread and the driver lock permanently - every subsequent wlan operation on the box hangs (system-wide wlan DoS), and mtw_detachs usbd_transfer_drain deadlocks the unplug path. Simulated on the guest with the exact control flow: healthy device exits after 16 iterations; failing device diverges to the 1e8 harness cap (kernel loop has no cap). Twin of DF-5248 (if_run).", "exploit_chain": "hostap/multi-vap + 11 TX frames -> cmdq queues mtw_drain_fifo -> device unplugged/stalled -> every mtw_read returns 0xffffffff (VLD set) -> infinite loop with sc_lock held -> taskqueue thread + driver lock wedged forever -> all wlan ops hang; device unplug deadlocks in usbd_transfer_drain", "evidence": "run.log: device healthy: exits after 16 iterations vs device failing: iterations = 100000000 (hit harness cap - KERNEL LOOP WOULD NEVER EXIT); drain_fifo_sim.c", "kernel_refs": [ "sys/bus/u4b/wlan/if_mtw.c:2173", "sys/bus/u4b/wlan/if_mtw.c:2177", "sys/bus/u4b/wlan/if_mtw.c:1284", "sys/bus/u4b/wlan/if_mtwreg.h:702", "sys/bus/u4b/wlan/if_mtw.c:3206" ], "poc_changes": "Sim written from scratch modelling mtw_reads error store of 0xffffffff and the exact loop condition", "attempts": 2, "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": 12, "guest_dirty": 0, "build_cmd": "cc -O2 -o /tmp/drain_fifo_sim /tmp/drain_fifo_sim.c", "run_cmd": "/tmp/drain_fifo_sim", "code_hash": "ae7603c3183fa424e8182f96a1b7ac98bea6c8c9af58370e2d8aa2443a23f191", "notes": "All mtw(4) paths are hardware-gated on the QEMU guest (no USB controller is passed through and no MT7601U device model exists); evidence is in-kernel structural (DF-5258: kld probe against the real if_mtwvar.h) or userland interleaving simulation mirroring the exact code regions/lock domains, per the wlan-trio pass-2 methodology (cf. DF-5246..DF-5257).", "recommended_fix": "Bound the loop (FIFO depth is 16) and break on mtw_read() error", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored and verified with git apply --check against the pristine sys/ tree, but cannot be kernel-tested: the guest has no USB controller and no MT7601U device model, so neither baseline nor patched kernel behavior is exercisable. Hardware-gated: not_testable.", "fix_evidence": "fix.diff (git-apply clean); VERDICT.md" } |