svn commit: r300910 - head/sys/net80211

Andriy Voskoboinyk avos at FreeBSD.org
Sat May 28 18:49:18 UTC 2016


Author: avos
Date: Sat May 28 18:49:17 2016
New Revision: 300910
URL: https://svnweb.freebsd.org/changeset/base/300910

Log:
  net80211: fix use-after-free in frame defragmentation procedure.
  
  - Assign frame sequence/fragment number before frame concatenation;
  otherwise, frame header pointer (wh) will be invalid.
  - Move this code block upper and eliminate duplicate 'lwh = mtod()'
  assignment.
  
  Tested with wpi(4) (transmitter) (STA mode) and urtwn(4) (receiver)
  (HOSTAP mode).

Modified:
  head/sys/net80211/ieee80211_input.c

Modified: head/sys/net80211/ieee80211_input.c
==============================================================================
--- head/sys/net80211/ieee80211_input.c	Sat May 28 18:47:25 2016	(r300909)
+++ head/sys/net80211/ieee80211_input.c	Sat May 28 18:49:17 2016	(r300910)
@@ -227,9 +227,16 @@ ieee80211_defrag(struct ieee80211_node *
 		lwh = mtod(mfrag, struct ieee80211_frame *);
 		last_rxseq = le16toh(*(uint16_t *)lwh->i_seq);
 		/* NB: check seq # and frag together */
-		if (rxseq != last_rxseq+1 ||
-		    !IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
-		    !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
+		if (rxseq == last_rxseq+1 &&
+		    IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) &&
+		    IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
+			/* XXX clear MORE_FRAG bit? */
+			/* track last seqnum and fragno */
+			*(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq;
+
+			m_adj(m, hdrspace);		/* strip header */
+			m_catpkt(mfrag, m);		/* concatenate */
+		} else {
 			/*
 			 * Unrelated fragment or no space for it,
 			 * clear current fragments.
@@ -247,12 +254,6 @@ ieee80211_defrag(struct ieee80211_node *
 			return NULL;
 		}
 		mfrag = m;
-	} else {				/* concatenate */
-		m_adj(m, hdrspace);		/* strip header */
-		m_catpkt(mfrag, m);
-		/* track last seqnum and fragno */
-		lwh = mtod(mfrag, struct ieee80211_frame *);
-		*(uint16_t *) lwh->i_seq = *(uint16_t *) wh->i_seq;
 	}
 	if (more_frag) {			/* more to come, save */
 		ni->ni_rxfragstamp = ticks;


More information about the svn-src-head mailing list