# DF-4733 — ar5210_xmit: signed q<0 bypasses >=-only checks in ar5210Set/GetTxQueueProps; five exported xmit ops gate q only via inert HALASSERT

**File**: `sys/dev/netif/ath/ath_hal/ar5210/ar5210_xmit.c`
**Family**: ar5210 twin of DF-4519 (ar5212, verified) and DF-4712 (ar5211) — signed-q + inert-HALASSERT.
**Severity**: Low (latent; all in-tree callers pass validated 0..2) — **certain** on the code shape.

## TL;DR
`ar5210SetTxQueueProps`/`ar5210GetTxQueueProps` take **signed** `int q` and check only
`q >= HAL_NUM_TX_QUEUES`, so a negative q indexes `ahp->ah_txq[q]` **below** the 3-element
array (`ar5210.h:112`, `HAL_NUM_TX_QUEUES == 3` for 5210 at `ar5210.h:96`);
`ath_hal_setTxQProps` (`ah.c:951`) then reads `qi->tqi_type` and writes ~15 fields through
the OOB pointer. The five exported tx ops (`ar5210GetTxDP:262`, `ar5210SetTxDP:287`,
`ar5210StartTxDma:372`, `ar5210NumTxPending:406`, `ar5210StopTxDma:433`) gate `u_int q`
only via `HALASSERT`, which expands to nothing in production (`ah_internal.h:669-676`;
`AH_ASSERT` is opt-in — `sys/conf/options:549`, absent from X86_64_GENERIC, verified on guest),
leaving `&ahp->ah_txq[q]` OOB reads unvalidated.

No unprivileged trigger exists today: every in-tree caller passes driver-validated
indices (`if_ath.c:4013-4032` checks `qnum == -1` and `qnum >= nitems(sc->sc_txq)`;
`sc_bhalq` likewise comes from `ath_hal_setuptxqueue`). Latent primitive for future/buggy
HAL callers — same class the project already accepted fixes for in DF-4519/DF-4712.

Notable ar5210-specific deltas vs the 5211/5212 twins (why this is *weaker* than theirs):
- No computed per-queue MMIO (`AR_QTXDP(q)` etc.) — 5210 uses fixed `AR_TXDP0`/`AR_TXDP1`
  registers, so the assert-only ops expose only an `ah_txq[q]` struct OOB **read**, not OOB MMIO.
- No DF-4520-style EEPROM-driven queue count: `ar5210_attach.c:368` sets
  `pCap->halTotalQueues = HAL_NUM_TX_QUEUES` (constant 3), and `ar5210SetupTxQueue`
  picks fixed q ∈ {0,1,2}.
- The `1 << q` mask updates in `ar5210ReleaseTxQueue:143-147` / `ar5210ResetTxQueue:228-247`
  sit behind *real* runtime `q >= HAL_NUM_TX_QUEUES` checks — no UB shift.

## Reproduce
Hardware-gated (no Atheros NIC on the guest — verified, `pciconf -l` shows zero ath
devices; kld module compiled into `kernel` per `kldstat -v`). Source-only confirmation
plus **fix build-validation**:

```
# on the guest (from this pack):
scp fix.diff guest:/tmp/df4733.diff
vm.sh run_root 'cd /usr/src && patch -p1 < /tmp/df4733.diff && make nativekernel KERNCONF=X86_64_GENERIC'
# expected: BUILD_RC=0, ar5210_xmit.c compiled -Werror (see build.log)
```

## Fix
`fix.diff` (7 runtime q-checks: `q < 0 ||` in the two signed props ops; runtime
`q >= HAL_NUM_TX_QUEUES` checks returning `0xffffffff`/`AH_FALSE`/`0` in the five ops).
Mirrors the accepted DF-4519/DF-4712 fix shape.
