From 44bf877e1a37edcb5784885dec0440a8a77ff82f Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 5 Mar 2014 18:39:27 +0000 Subject: [PATCH] - Temporary fix for race in RUN driver which can cause freed memory to be accessed. - Properly lock callout_reset()'s. MFC after: 1 week --- sys/dev/usb/wlan/if_run.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 55cea59a9546..221c0f1c2363 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -2508,9 +2508,7 @@ run_ratectl_cb(void *arg, int pending) if (vap == NULL) return; - if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA) - run_iter_func(sc, vap->iv_bss); - else { + if (sc->rvp_cnt > 1 || vap->iv_opmode != IEEE80211_M_STA) { /* * run_reset_livelock() doesn't do anything with AMRR, * but Ralink wants us to call it every 1 sec. So, we @@ -2523,9 +2521,10 @@ run_ratectl_cb(void *arg, int pending) /* just in case, there are some stats to drain */ run_drain_fifo(sc); RUN_UNLOCK(sc); - ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, sc); } + ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, sc); + RUN_LOCK(sc); if(sc->ratectl_run != RUN_RATECTL_OFF) usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); @@ -2605,6 +2604,11 @@ run_iter_func(void *arg, struct ieee80211_node *ni) RUN_LOCK(sc); + /* Check for special case */ + if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA && + ni != vap->iv_bss) + goto fail; + if (sc->rvp_cnt <= 1 && (vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_STA)) { /* read statistic counters (clear on read) and update AMRR state */ @@ -2733,7 +2737,10 @@ run_newassoc(struct ieee80211_node *ni, int isnew) rn->mgt_ridx = ridx; DPRINTF("rate=%d, mgmt_ridx=%d\n", rate, rn->mgt_ridx); - usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); + RUN_LOCK(sc); + if(sc->ratectl_run != RUN_RATECTL_OFF) + usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); + RUN_UNLOCK(sc); } /*