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

Commit 8020919a authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg
Browse files

mac80211: Properly handle SKB with radiotap only



The monitor interface Rx handling of SKBs that contain only
radiotap information was buggy as it tried to access the
SKB assuming it contains a frame.

To fix this, check the RX_FLAG_NO_PSDU flag in the Rx status
(indicting that the SKB contains only radiotap information),
and do not perform data path specific processing when the flag
is set.

Signed-off-by: default avatarIlan Peer <ilan.peer@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 925b5978
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -753,6 +753,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
	struct ieee80211_sub_if_data *monitor_sdata =
		rcu_dereference(local->monitor_sdata);
	bool only_monitor = false;
	unsigned int min_head_len;

	if (status->flag & RX_FLAG_RADIOTAP_HE)
		rtap_space += sizeof(struct ieee80211_radiotap_he);
@@ -766,6 +767,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
		rtap_space += sizeof(*rtap) + rtap->len + rtap->pad;
	}

	min_head_len = rtap_space;

	/*
	 * First, we may need to make a copy of the skb because
	 *  (1) we need to modify it for radiotap (if not present), and
@@ -775,8 +778,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
	 * the SKB because it has a bad FCS/PLCP checksum.
	 */

	if (!(status->flag & RX_FLAG_NO_PSDU)) {
		if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)) {
		if (unlikely(origskb->len <= FCS_LEN)) {
			if (unlikely(origskb->len <= FCS_LEN + rtap_space)) {
				/* driver bug */
				WARN_ON(1);
				dev_kfree_skb(origskb);
@@ -785,8 +789,12 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
			present_fcs_len = FCS_LEN;
		}

	/* ensure hdr->frame_control and vendor radiotap data are in skb head */
	if (!pskb_may_pull(origskb, 2 + rtap_space)) {
		/* also consider the hdr->frame_control */
		min_head_len += 2;
	}

	/* ensure that the expected data elements are in skb head */
	if (!pskb_may_pull(origskb, min_head_len)) {
		dev_kfree_skb(origskb);
		return NULL;
	}