⬢ DragonFlyBSD Kernel Audit
DF-5294 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/u4b/wlan/if_rum.c
+++ b/sys/bus/u4b/wlan/if_rum.c
@@ -711,7 +711,13 @@
 {
 	struct rum_vap *rvp = RUM_VAP(vap);
 	struct ieee80211com *ic = vap->iv_ic;
+	struct rum_softc *sc = ic->ic_softc;
 
+	/* Stop the ratectl callout/task pair BEFORE draining it,
+	 * so the task cannot re-arm the callout after the drain. */
+	RUM_LOCK(sc);
+	sc->ratectl_run = 0;
+	RUM_UNLOCK(sc);
 	m_freem(rvp->bcn_mbuf);
 	usb_callout_drain(&rvp->ratectl_ch);
 	ieee80211_draintask(ic, &rvp->ratectl_task);
@@ -932,6 +938,7 @@
 	IEEE80211_UNLOCK(ic);
 	RUM_LOCK(sc);
 	usb_callout_stop(&rvp->ratectl_ch);
+	sc->ratectl_run = 0;
 
 	if (ostate == IEEE80211_S_SLEEP && vap->iv_opmode == IEEE80211_M_STA) {
 		rum_clrbits(sc, RT2573_TXRX_CSR4, RT2573_ACKCTS_PWRMGT);
@@ -3090,6 +3097,7 @@
 	/* clear statistic registers (STA_CSR0 to STA_CSR5) */
 	rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
 
+	sc->ratectl_run = 1;
 	usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
 }
 
@@ -3137,7 +3145,8 @@
 	/* count TX retry-fail as Tx errors */
 	if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, fail);
 
-	usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
+	if (sc->ratectl_run)
+		usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
 	RUM_UNLOCK(sc);
 }
 
--- a/sys/bus/u4b/wlan/if_rumvar.h
+++ b/sys/bus/u4b/wlan/if_rumvar.h
@@ -152,6 +152,7 @@
 
 	uint8_t				vap_key_count[1];
 	uint64_t			keys_bmap;
+	uint8_t				ratectl_run;
 
 	struct {
 		uint8_t	val;