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

Commit 77a980dc authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

mac80211: fix RX skb leaks



In mac80211's RX path some of the warnings that
warn about drivers passing invalid status values
leak the skb, fix that by refactoring the code.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0448b5fc
Loading
Loading
Loading
Loading
+15 −19
Original line number Diff line number Diff line
@@ -2447,17 +2447,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
	struct ieee80211_supported_band *sband;
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);

	if (status->band < 0 ||
	    status->band >= IEEE80211_NUM_BANDS) {
		WARN_ON(1);
		return;
	}
	if (WARN_ON(status->band < 0 ||
		    status->band >= IEEE80211_NUM_BANDS))
		goto drop;

	sband = local->hw.wiphy->bands[status->band];
	if (!sband) {
		WARN_ON(1);
		return;
	}
	if (WARN_ON(!sband))
		goto drop;

	/*
	 * If we're suspending, it is possible although not too likely
@@ -2466,25 +2462,21 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
	 * that might, for example, cause stations to be added or other
	 * driver callbacks be invoked.
	 */
	if (unlikely(local->quiescing || local->suspended)) {
		kfree_skb(skb);
		return;
	}
	if (unlikely(local->quiescing || local->suspended))
		goto drop;

	/*
	 * The same happens when we're not even started,
	 * but that's worth a warning.
	 */
	if (WARN_ON(!local->started)) {
		kfree_skb(skb);
		return;
	}
	if (WARN_ON(!local->started))
		goto drop;

	if (status->flag & RX_FLAG_HT) {
		/* rate_idx is MCS index */
		if (WARN_ON(status->rate_idx < 0 ||
			    status->rate_idx >= 76))
			return;
			goto drop;
		/* HT rates are not in the table - use the highest legacy rate
		 * for now since other parts of mac80211 may not yet be fully
		 * MCS aware. */
@@ -2492,7 +2484,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
	} else {
		if (WARN_ON(status->rate_idx < 0 ||
			    status->rate_idx >= sband->n_bitrates))
			return;
			goto drop;
		rate = &sband->bitrates[status->rate_idx];
	}

@@ -2531,6 +2523,10 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
		__ieee80211_rx_handle_packet(hw, skb, rate);

	rcu_read_unlock();

	return;
 drop:
	kfree_skb(skb);
}
EXPORT_SYMBOL(ieee80211_rx);