DF-4881 / verdict.json
{ "finding_id": "DF-4881", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Type confusion proven statically (DF-4850/amrr twin): onoe ath_rate_getxtxrates (onoe.c:143-146) stores cached hardware rate codes (on_tx_rate0..3, assigned rt->info[...].rateCode at onoe.c:221/237/246/254) into struct ath_rc_series.rix fields whose contract is ratetable index, not rate code (if_athrate.h:91), clobbering the correct series-0 index the caller installed at if_ath_tx.c:1392. Downstream rt->info[rc[i].rix] derefs confirmed at if_ath_tx.c:1073, 1133-1135, 1298 and if_ath_tx_ht.c:588 (11n rate scenario programming). On 11n HALs HT rate codes are 0x80-0x8f (128-143) vs HAL_RATE_TABLE.info[64] (ah.h:681) => heap OOB read up to ~80 entries past the table; garbage .rateCode/.phy/.durations then program TX descriptors. Triggered by ordinary mrr-frame transmission (if_ath_tx.c:1396-1397, try0=4 != ATH_TXMAXTRY on sc_mrretry parts). Not exercisable on this guest: no Atheros NIC, no onoe module (env.txt). Low severity: read-only OOB feeding HW registers, no confidentiality impact.", "exploit_chain": "802.11 peer exchanges traffic with an ath+onoe+mrr station -> every multi-rate-retry frame takes ath_tx_do_ratelookup -> onoe getxtxrates poisons bfs_rc[0..3].rix with rate codes -> rt->info[rateCode] wrong-entry/OOB reads (if_ath_tx.c:1073/1133/1298; if_ath_tx_ht.c:588) -> garbage durations/protection/rates programmed to hardware. No path to memory write or info leak to userspace; impact is mis-programmed transmission.", "evidence": "README.md (sink-by-sink citations), VERDICT.md, env.txt (no ath hardware). Decisive lines: onoe.c:143-146 (.rix = rate codes), onoe.c:221 (rate0 = rt->info[].rateCode), if_athrate.h:91 (.rix contract), if_ath_tx.c:1392 (clobbered index), if_ath_tx_ht.c:588 (series Rate = rt->info[rix].rateCode), ar5416_phy.c:80-90 (HT codes 0x80-0x8f), ah.h:681 (info[64]).", "kernel_refs": [ "sys/dev/netif/ath/ath_rate/onoe/onoe.c:143", "sys/dev/netif/ath/ath_rate/onoe/onoe.c:221", "sys/dev/netif/ath/ath/if_athrate.h:91", "sys/dev/netif/ath/ath/if_ath_tx.c:1392", "sys/dev/netif/ath/ath/if_ath_tx.c:1396", "sys/dev/netif/ath/ath/if_ath_tx.c:1073", "sys/dev/netif/ath/ath/if_ath_tx.c:1133", "sys/dev/netif/ath/ath/if_ath_tx.c:1298", "sys/dev/netif/ath/ath/if_ath_tx_ht.c:588", "sys/dev/netif/ath/ath_hal/ah.h:681", "sys/dev/netif/ath/ath_hal/ar5416/ar5416_phy.c:80" ], "poc_changes": "n/a - no runnable PoC without ath hardware; evidence is the fully-cited static chain", "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": 20, "guest_dirty": 0, "fix_status": "not_applicable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored (cache per-series indices in onoe.h, populate .rix with indices and .ratecode with codes) but not kernel-buildable-testable here - the ath TX path needs Atheros hardware the guest lacks.", "fix_evidence": "findings/poc/DF-4881/fix.diff", "notes": "Independent instance of DF-4850 (amrr.c:128) in the onoe twin; do not merge the two records. DF-1948 (sc_rixmap sentinel rt->info OOB in ath_rate_update) is a separate, already-known issue in the same file and is NOT re-reported.", "recommended_fix": "Cache rate-table indices per series in onoe_node and write them to rc[].rix (codes to rc[].ratecode), mirroring the amrr DF-4850 fix", "build_cmd": "n/a (no hardware)", "run_cmd": "n/a (no hardware)", "code_hash": "" } |