DF-3836 / verdict.json
{ "finding_id": "DF-3836", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "bwn_phy_lp_b2063_switch_channel declares its lookup result as a static local: static const struct bwn_b206x_chan *bc = NULL; (sys/dev/netif/bwn/bwn/if_bwn_phy_lp.c:794). After any successful call, bc permanently holds the last matched table entry; on a later call with a channel absent from bwn_b2063_chantable the search loop (801-806) leaves bc unchanged, the if (bc == NULL) return (EINVAL); failure check (807-808) is defeated, and the function programs the PREVIOUS channels RF values (810-921) and returns 0. The caller bwn_phy_lp_switch_channel (567-581) then records plp->plp_chan = chan and writes the bogus channel to BWN_CHANNEL \u2014 net80211 believes the radio moved while the RF stayed on the old frequency (regulatory/interference and association-failure hazard, not memory corruption). The intended non-static form is proven by the sibling bwn_phy_lp_b2062_switch_channel which uses a plain const struct bwn_b206x_chan *bc = NULL; (line 926). Source defect is certain; practical reachability today is constrained because all callers pass net80211-validated channel numbers that exist in the table (if_bwn.c:1911 chan2ieee / if_bwn.c:4434), so no guest reproduction is possible (no Broadcom hardware, env.txt) and real-world triggering needs a channel outside the 58-entry table (e.g. future half/quarter-channel or exotic-regdomain additions). Upstream FreeBSD has the identical static at their line 815.", "exploit_chain": "none (correctness/regulatory): unsupported channel request -> silently stays on previous RF frequency while the stacks channel state says otherwise; may transmit on a regulated band the operator did not select.", "evidence": "README.md (static-vs-non-static comparison 794 vs 926; caller 567-581); env.txt; fix.diff (drop static, git-apply --check passes)", "kernel_refs": [ "sys/dev/netif/bwn/bwn/if_bwn_phy_lp.c:794", "sys/dev/netif/bwn/bwn/if_bwn_phy_lp.c:801", "sys/dev/netif/bwn/bwn/if_bwn_phy_lp.c:807", "sys/dev/netif/bwn/bwn/if_bwn_phy_lp.c:926", "sys/dev/netif/bwn/bwn/if_bwn.c:4434", "sys/dev/netif/bwn/bwn/if_bwn.c:1911" ], "poc_changes": "No PoC \u2014 would require LP PHY hardware and a channel outside the chantable.", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 X86_64_GENERIC x86_64", "runtime_sec": 0, "guest_dirty": 0, "build_cmd": null, "run_cmd": null, "code_hash": null, "notes": "Pass-2 hunt item (a): the const-table channel-index walks. Pass 1s bwn findings DF-3593..3596 covered if_bwn.c only; this files table walks were fresh territory.", "recommended_fix": "Remove static from the bc local in bwn_phy_lp_b2063_switch_channel (fix.diff); mirror upstream.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Requires LP PHY hardware and an out-of-table channel; absent on the audit guest (env.txt). fix.diff is git-apply-able (verified).", "fix_evidence": "fix.diff" } |