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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to