Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 May 2016 18:49:17 +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: r300910 - head/sys/net80211
Message-ID:  <201605281849.u4SInHqo042429@repo.freebsd.org>

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



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