⬢ DragonFlyBSD Kernel Audit
DF-4881 / fix.diff
← back to finding ↓ download raw
Fix DF-4881: onoe caches HW rate codes into index-typed fields.
Cache the rate-table indices alongside the codes (onoe.h) and populate
ath_rc_series.rix with indices and .ratecode with codes (onoe.c), instead
of storing codes in both. Without this, every downstream
rt->info[rc[i].rix] deref (if_ath_tx.c:1073/1133/1298, if_ath_tx_ht.c:588)
is a wrong-entry access, OOB on 11n HALs (HT codes 0x80-0x8f vs
HAL_RATE_TABLE.info[64]), and the correct series-0 index set by the caller
at if_ath_tx.c:1392 is clobbered.

--- a/sys/dev/netif/ath/ath_rate/onoe/onoe.h
+++ b/sys/dev/netif/ath/ath_rate/onoe/onoe.h
@@ -63,9 +63,13 @@ struct onoe_node {
 	u_int8_t	on_tx_rix0;	/* series 0 rate index */
 	u_int8_t	on_tx_try0;	/* series 0 try count */
 	u_int8_t	on_tx_rate0;	/* series 0 h/w rate */
+	u_int8_t	on_tx_rix1;	/* series 1 rate index */
 	u_int8_t	on_tx_rate1;	/* series 1 h/w rate */
+	u_int8_t	on_tx_rix2;	/* series 2 rate index */
 	u_int8_t	on_tx_rate2;	/* series 2 h/w rate */
+	u_int8_t	on_tx_rix3;	/* series 3 rate index */
 	u_int8_t	on_tx_rate3;	/* series 3 h/w rate */
 	u_int8_t	on_tx_rate0sp;	/* series 0 short preamble h/w rate */
 	u_int8_t	on_tx_rate1sp;	/* series 1 short preamble h/w rate */
--- a/sys/dev/netif/ath/ath_rate/onoe/onoe.c
+++ b/sys/dev/netif/ath/ath_rate/onoe/onoe.c
@@ -141,12 +141,14 @@ ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an,
 	struct onoe_node *on = ATH_NODE_ONOE(an);
 
 	rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
 
-	rc[0].rix = on->on_tx_rate0;
-	rc[1].rix = on->on_tx_rate1;
-	rc[2].rix = on->on_tx_rate2;
-	rc[3].rix = on->on_tx_rate3;
+	/* .rix is a rate-table INDEX (if_athrate.h); codes go to .ratecode */
+	rc[0].rix = on->on_tx_rix0;
+	rc[1].rix = on->on_tx_rix1;
+	rc[2].rix = on->on_tx_rix2;
+	rc[3].rix = on->on_tx_rix3;
+	rc[0].ratecode = on->on_tx_rate0;
+	rc[1].ratecode = on->on_tx_rate1;
+	rc[2].ratecode = on->on_tx_rate2;
+	rc[3].ratecode = on->on_tx_rate3;
 
 	rc[0].tries = on->on_tx_try0;
 	rc[1].tries = 2;
@@ -234,21 +236,27 @@ ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
 		on->on_tx_try0 = 1 + 3;		/* 4 tries at rate 0 */
 		if (--rate >= 0) {
 			rix = sc->sc_rixmap[
 				ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
+			on->on_tx_rix1 = rix;
 			on->on_tx_rate1 = rt->info[rix].rateCode;
 			on->on_tx_rate1sp = on->on_tx_rate1 |
 				rt->info[rix].shortPreamble;
 		} else {
+			on->on_tx_rix1 = 0;
 			on->on_tx_rate1 = on->on_tx_rate1sp = 0;
 		}
 		if (--rate >= 0) {
 			rix = sc->sc_rixmap[
 				ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
+			on->on_tx_rix2 = rix;
 			on->on_tx_rate2 = rt->info[rix].rateCode;
 			on->on_tx_rate2sp = on->on_tx_rate2 |
 				rt->info[rix].shortPreamble;
 		} else {
+			on->on_tx_rix2 = 0;
 			on->on_tx_rate2 = on->on_tx_rate2sp = 0;
 		}
 		if (rate > 0) {
 			/* NB: only do this if we didn't already do it above */
+			on->on_tx_rix3 = 0;
 			on->on_tx_rate3 = rt->info[0].rateCode;
 			on->on_tx_rate3sp =
 				on->on_tx_rate3 | rt->info[0].shortPreamble;
 		} else {
+			on->on_tx_rix3 = 0;
 			on->on_tx_rate3 = on->on_tx_rate3sp = 0;
 		}
 	} else {
 		on->on_tx_try0 = ATH_TXMAXTRY;	/* max tries at rate 0 */
+		on->on_tx_rix1 = on->on_tx_rix2 = on->on_tx_rix3 = 0;
 		on->on_tx_rate1 = on->on_tx_rate1sp = 0;
 		on->on_tx_rate2 = on->on_tx_rate2sp = 0;
 		on->on_tx_rate3 = on->on_tx_rate3sp = 0;