Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Dec 2013 19:22:02 +0000 (UTC)
From:      Gavin Atkinson <gavin@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org
Subject:   svn commit: r259188 - releng/10.0/sys/net80211
Message-ID:  <201312101922.rBAJM2BJ080958@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gavin
Date: Tue Dec 10 19:22:02 2013
New Revision: 259188
URL: http://svnweb.freebsd.org/changeset/base/259188

Log:
  Merge r259175 from stable/10 (head r257065 by adrian):
  
      Fix a use-after-free node reference issue when waiting for a return
      from a management frame transmission.
  
  Approved by:	re (glebius)

Modified:
  releng/10.0/sys/net80211/ieee80211_output.c
  releng/10.0/sys/net80211/ieee80211_proto.c
  releng/10.0/sys/net80211/ieee80211_proto.h
Directory Properties:
  releng/10.0/   (props changed)

Modified: releng/10.0/sys/net80211/ieee80211_output.c
==============================================================================
--- releng/10.0/sys/net80211/ieee80211_output.c	Tue Dec 10 19:17:31 2013	(r259187)
+++ releng/10.0/sys/net80211/ieee80211_output.c	Tue Dec 10 19:22:02 2013	(r259188)
@@ -2736,20 +2736,35 @@ ieee80211_alloc_cts(struct ieee80211com 
 static void
 ieee80211_tx_mgt_timeout(void *arg)
 {
-	struct ieee80211_node *ni = arg;
-	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211vap *vap = arg;
 
+	IEEE80211_LOCK(vap->iv_ic);
 	if (vap->iv_state != IEEE80211_S_INIT &&
 	    (vap->iv_ic->ic_flags & IEEE80211_F_SCAN) == 0) {
 		/*
 		 * NB: it's safe to specify a timeout as the reason here;
 		 *     it'll only be used in the right state.
 		 */
-		ieee80211_new_state(vap, IEEE80211_S_SCAN,
+		ieee80211_new_state_locked(vap, IEEE80211_S_SCAN,
 			IEEE80211_SCAN_FAIL_TIMEOUT);
 	}
+	IEEE80211_UNLOCK(vap->iv_ic);
 }
 
+/*
+ * This is the callback set on net80211-sourced transmitted
+ * authentication request frames.
+ *
+ * This does a couple of things:
+ *
+ * + If the frame transmitted was a success, it schedules a future
+ *   event which will transition the interface to scan.
+ *   If a state transition _then_ occurs before that event occurs,
+ *   said state transition will cancel this callout.
+ *
+ * + If the frame transmit was a failure, it immediately schedules
+ *   the transition back to scan.
+ */
 static void
 ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status)
 {
@@ -2767,10 +2782,11 @@ ieee80211_tx_mgt_cb(struct ieee80211_nod
 	 *
 	 * XXX what happens if !acked but response shows up before callback?
 	 */
-	if (vap->iv_state == ostate)
+	if (vap->iv_state == ostate) {
 		callout_reset(&vap->iv_mgtsend,
 			status == 0 ? IEEE80211_TRANS_WAIT*hz : 0,
-			ieee80211_tx_mgt_timeout, ni);
+			ieee80211_tx_mgt_timeout, vap);
+	}
 }
 
 static void

Modified: releng/10.0/sys/net80211/ieee80211_proto.c
==============================================================================
--- releng/10.0/sys/net80211/ieee80211_proto.c	Tue Dec 10 19:17:31 2013	(r259187)
+++ releng/10.0/sys/net80211/ieee80211_proto.c	Tue Dec 10 19:22:02 2013	(r259188)
@@ -107,8 +107,6 @@ static void update_promisc(void *, int);
 static void update_channel(void *, int);
 static void update_chw(void *, int);
 static void ieee80211_newstate_cb(void *, int);
-static int ieee80211_new_state_locked(struct ieee80211vap *,
-	enum ieee80211_state, int);
 
 static int
 null_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
@@ -1834,7 +1832,7 @@ done:
  * is usually a mistake and indicates lack of proper integration
  * with the net80211 layer.
  */
-static int
+int
 ieee80211_new_state_locked(struct ieee80211vap *vap,
 	enum ieee80211_state nstate, int arg)
 {

Modified: releng/10.0/sys/net80211/ieee80211_proto.h
==============================================================================
--- releng/10.0/sys/net80211/ieee80211_proto.h	Tue Dec 10 19:17:31 2013	(r259187)
+++ releng/10.0/sys/net80211/ieee80211_proto.h	Tue Dec 10 19:22:02 2013	(r259188)
@@ -332,6 +332,8 @@ void	ieee80211_dturbo_switch(struct ieee
 void	ieee80211_swbmiss(void *arg);
 void	ieee80211_beacon_miss(struct ieee80211com *);
 int	ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int);
+int	ieee80211_new_state_locked(struct ieee80211vap *, enum ieee80211_state,
+		int);
 void	ieee80211_print_essid(const uint8_t *, int);
 void	ieee80211_dump_pkt(struct ieee80211com *,
 		const uint8_t *, int, int, int);



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