Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54297e4d authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

mac80211: fix some RX aggregation locking



A few places in mac80211 do not currently acquire
the sta lock for RX aggregation, but they should.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 098a6070
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -720,14 +720,16 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,

	tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;

	spin_lock(&sta->lock);

	if (!sta->ampdu_mlme.tid_active_rx[tid])
		goto dont_reorder;
		goto dont_reorder_unlock;

	tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];

	/* qos null data frames are excluded */
	if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
		goto dont_reorder;
		goto dont_reorder_unlock;

	/* new, potentially un-ordered, ampdu frame - process it */

@@ -739,15 +741,20 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
	/* if this mpdu is fragmented - terminate rx aggregation session */
	sc = le16_to_cpu(hdr->seq_ctrl);
	if (sc & IEEE80211_SCTL_FRAG) {
		spin_unlock(&sta->lock);
		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
					       WLAN_REASON_QSTA_REQUIRE_SETUP);
		dev_kfree_skb(skb);
		return;
	}

	if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames))
	if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) {
		spin_unlock(&sta->lock);
		return;
	}

 dont_reorder_unlock:
	spin_unlock(&sta->lock);
 dont_reorder:
	__skb_queue_tail(frames, skb);
}
@@ -1804,9 +1811,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
	if (ieee80211_is_back_req(bar->frame_control)) {
		if (!rx->sta)
			return RX_DROP_MONITOR;
		spin_lock(&rx->sta->lock);
		tid = le16_to_cpu(bar->control) >> 12;
		if (!rx->sta->ampdu_mlme.tid_active_rx[tid])
		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;
@@ -1820,6 +1830,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
		ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num,
						 frames);
		kfree_skb(skb);
		spin_unlock(&rx->sta->lock);
		return RX_QUEUED;
	}