DF-5032 / verdict.json
{ "finding_id": "DF-5032", "status": "untested", "verdict": "Bounds defect is certain: ar5212InvalidGainReadback (ar5212_rfgain.c:140) extracts gStep via ar5212GetRfField(bank7, 6, 37, 0), whose byte walk (ar5212_rfgain.c:102-117) reads rfBuf[4] and rfBuf[5], but the RF bank-7 shadow arrays of the 2413/2316/2317/5413/2425/2417 backends have only 3 words (ar5212.ini:1870,1878,1886,2158,2166; only 5111 has 8, 5112 has 13 and takes the other branch). Kernel-path execution was not possible: the probe is armed only on 5 GHz channels (ar5212_reset.c:1085-1094; driver polls ath_hal_getrfgain, if_ath.c:5401) and the audit guest has no Atheros hardware. Impact on the reachable path (ar5413, 5 GHz): the 8 bytes land in vpdTable_L inside the same ath_hal_mallocd priv struct (ar5413.c:35-57) - C-level array OOB / UB, no heap violation, value never exported nor used as an index - so the practical effect is miscalculated loTrig/hiTrig (ar5212_rfgain.c:143-149) and misfiring gain-ladder adjustments: RF performance degradation only. Dormant variant: ar2425/2417 where Bank7Data is the final struct member (ar2425.c:36-45) would make the same read an 8-byte heap OOB read, gated off because those radios are 2.4 GHz-only. Severity Low; verification skipped per contract (hardware-only trigger). The index-walk arithmetic demo (oob_demo.c, byte-for-byte replica of the walk) ran on the DragonFly guest and prints the OOB for all five 3-row radios (oob_demo.log, exit 1).", "reproduced": false, "impact": "none", "confidence": "certain", "exploit_chain": "", "evidence": "oob_demo.log: InvalidGainReadback/else GetRfField(bank7, 6, 37, 0) words touched: [4] [5] (max index 5) followed by ar5413 (else path) N(ar5212Bank7_5413) = 3 rows -> index 5 *** OUT OF BOUNDS (reads 2 words past) *** (x5 radios), exit 1; static refs ar5212_rfgain.c:140 + ar5212.ini bank7 row counts", "kernel_refs": [ "sys/dev/netif/ath/ath_hal/ar5212/ar5212_rfgain.c:140", "sys/dev/netif/ath/ath_hal/ar5212/ar5212_rfgain.c:102", "sys/dev/netif/ath/ath_hal/ar5212/ar5212.ini:1870", "sys/dev/netif/ath/ath_hal/ar5212/ar5212.ini:1886", "sys/dev/netif/ath/ath_hal/ar5212/ar5212.ini:2166", "sys/dev/netif/ath/ath_hal/ar5212/ar2425.c:36", "sys/dev/netif/ath/ath_hal/ar5212/ar5413.c:35", "sys/dev/netif/ath/ath_hal/ar5212/ar5212_reset.c:1090" ], "poc_changes": "No prior PoC; oob_demo.c authored this pass (pure-arithmetic replica of ar5212GetRfFields index walk vs the real bank-7 row counts).", "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": 15, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o oob_demo oob_demo.c", "run_cmd": "sh run.sh", "code_hash": "2a11dde5e4855d2994a7ae2fb5291f04ccec912a46a88e006338fc879384de25", "notes": "Verification skipped per contract (Low severity, hardware-only trigger; no ath device on guest). Guest scratch cleaned.", "recommended_fix": "Size Bank7Data[] >= 6 words in the 2413/2316/2317/5413/2425/2417 RF priv structs (keeps the generic byte-walk in bounds), or restrict the gStep extraction at ar5212_rfgain.c:140 to radios whose bank-7 layout actually holds bits 33-43 (RF5111).", "fix_status": "not_testable", "fix_baseline_reproduced": false, "fix_patched_reproduced": false, "fix_verdict": "Fix validation not applicable: memory-corruption reproduction did not occur (no hardware), and the finding is Low severity / functional RF impact only.", "fix_evidence": "n/a" } |