svn commit: r302034 - head/sys/dev/urtwn
Andriy Voskoboinyk
avos at FreeBSD.org
Mon Jun 20 22:39:34 UTC 2016
Author: avos
Date: Mon Jun 20 22:39:32 2016
New Revision: 302034
URL: https://svnweb.freebsd.org/changeset/base/302034
Log:
urtwn: fix panic on device detach.
Remove frames from active/pending Tx queues and free related node
references when vap is destroyed to prevent various use-after-free
scenarios.
Reported and tested by: Aleksander Alekseev <afiskon at devzen.ru>
PR: 208632
Approved by: re (gjb)
Modified:
head/sys/dev/urtwn/if_urtwn.c
Modified: head/sys/dev/urtwn/if_urtwn.c
==============================================================================
--- head/sys/dev/urtwn/if_urtwn.c Mon Jun 20 22:05:59 2016 (r302033)
+++ head/sys/dev/urtwn/if_urtwn.c Mon Jun 20 22:39:32 2016 (r302034)
@@ -208,6 +208,10 @@ static struct ieee80211vap *urtwn_vap_cr
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void urtwn_vap_delete(struct ieee80211vap *);
+static void urtwn_vap_clear_tx(struct urtwn_softc *,
+ struct ieee80211vap *);
+static void urtwn_vap_clear_tx_queue(struct urtwn_softc *,
+ urtwn_datahead *, struct ieee80211vap *);
static struct mbuf * urtwn_rx_copy_to_mbuf(struct urtwn_softc *,
struct r92c_rx_stat *, int);
static struct mbuf * urtwn_report_intr(struct usb_xfer *,
@@ -824,8 +828,16 @@ urtwn_vap_delete(struct ieee80211vap *va
struct urtwn_softc *sc = ic->ic_softc;
struct urtwn_vap *uvp = URTWN_VAP(vap);
+ /* Guarantee that nothing will go through this vap. */
+ ieee80211_new_state(vap, IEEE80211_S_INIT, -1);
+ ieee80211_draintask(ic, &vap->iv_nstate_task);
+
+ URTWN_LOCK(sc);
if (uvp->bcn_mbuf != NULL)
m_freem(uvp->bcn_mbuf);
+ /* Cancel any unfinished Tx. */
+ urtwn_vap_clear_tx(sc, vap);
+ URTWN_UNLOCK(sc);
if (vap->iv_opmode == IEEE80211_M_IBSS)
ieee80211_draintask(ic, &uvp->tsf_task_adhoc);
if (URTWN_CHIP_HAS_RATECTL(sc))
@@ -834,6 +846,41 @@ urtwn_vap_delete(struct ieee80211vap *va
free(uvp, M_80211_VAP);
}
+static void
+urtwn_vap_clear_tx(struct urtwn_softc *sc, struct ieee80211vap *vap)
+{
+
+ URTWN_ASSERT_LOCKED(sc);
+
+ urtwn_vap_clear_tx_queue(sc, &sc->sc_tx_active, vap);
+ urtwn_vap_clear_tx_queue(sc, &sc->sc_tx_pending, vap);
+}
+
+static void
+urtwn_vap_clear_tx_queue(struct urtwn_softc *sc, urtwn_datahead *head,
+ struct ieee80211vap *vap)
+{
+ struct urtwn_data *dp, *tmp;
+
+ STAILQ_FOREACH_SAFE(dp, head, next, tmp) {
+ if (dp->ni != NULL) {
+ if (dp->ni->ni_vap == vap) {
+ ieee80211_free_node(dp->ni);
+ dp->ni = NULL;
+
+ if (dp->m != NULL) {
+ m_freem(dp->m);
+ dp->m = NULL;
+ }
+
+ STAILQ_REMOVE(head, dp, urtwn_data, next);
+ STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, dp,
+ next);
+ }
+ }
+ }
+}
+
static struct mbuf *
urtwn_rx_copy_to_mbuf(struct urtwn_softc *sc, struct r92c_rx_stat *stat,
int totlen)
More information about the svn-src-head
mailing list