mac80211: fix blockack-req processing
authorJohannes Berg <johannes@sipsolutions.net>
Sun, 30 May 2010 12:52:58 +0000 (14:52 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 1 Jun 2010 18:33:02 +0000 (14:33 -0400)
Daniel reported that the paged RX changes had
broken blockack request frame processing due
to using data that wasn't really part of the
skb data.

Fix this using skb_copy_bits() for the needed
data. As a side effect, this adds a check on
processing too short frames, which previously
this code could do.

Reported-by: Daniel Halperin <dhalperi@cs.washington.edu>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Daniel Halperin <dhalperi@cs.washington.edu>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/rx.c

index 6e2a7bcd8cb888ce24be03cc56cb2516ca95fade..5e0b65406c44a6787c6fbc5f5720d3c0337ad5b6 100644 (file)
@@ -1818,17 +1818,26 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
                return RX_CONTINUE;
 
        if (ieee80211_is_back_req(bar->frame_control)) {
+               struct {
+                       __le16 control, start_seq_num;
+               } __packed bar_data;
+
                if (!rx->sta)
                        return RX_DROP_MONITOR;
+
+               if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control),
+                                 &bar_data, sizeof(bar_data)))
+                       return RX_DROP_MONITOR;
+
                spin_lock(&rx->sta->lock);
-               tid = le16_to_cpu(bar->control) >> 12;
+               tid = le16_to_cpu(bar_data.control) >> 12;
                if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) {
                        spin_unlock(&rx->sta->lock);
                        return RX_DROP_MONITOR;
                }
                tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
 
-               start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
+               start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
 
                /* reset session timer */
                if (tid_agg_rx->timeout)