Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Jun 2016 22:39:32 +0000 (UTC)
From:      Andriy Voskoboinyk <avos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r302034 - head/sys/dev/urtwn
Message-ID:  <201606202239.u5KMdWaa042731@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606202239.u5KMdWaa042731>