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

Commit 191c2686 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: check integrity of received AMSDU packets"

parents 7d641f25 b2c81339
Loading
Loading
Loading
Loading
+9 −1
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: ISC
// SPDX-License-Identifier: ISC
/*
/*
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
 */
 */


#include <linux/moduleparam.h>
#include <linux/moduleparam.h>
@@ -310,6 +310,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
	/* statistics */
	/* statistics */
	memset(&sta->stats, 0, sizeof(sta->stats));
	memset(&sta->stats, 0, sizeof(sta->stats));
	sta->stats.tx_latency_min_us = U32_MAX;
	sta->stats.tx_latency_min_us = U32_MAX;
	wil_sta_info_amsdu_init(sta);
}
}


static void _wil6210_disconnect_complete(struct wil6210_vif *vif,
static void _wil6210_disconnect_complete(struct wil6210_vif *vif,
@@ -712,6 +713,13 @@ void wil_bcast_fini_all(struct wil6210_priv *wil)
	}
	}
}
}


void wil_sta_info_amsdu_init(struct wil_sta_info *sta)
{
	sta->amsdu_drop_sn = -1;
	sta->amsdu_drop_tid = -1;
	sta->amsdu_drop = 0;
}

int wil_priv_init(struct wil6210_priv *wil)
int wil_priv_init(struct wil6210_priv *wil)
{
{
	uint i;
	uint i;
+1 −2
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: ISC
// SPDX-License-Identifier: ISC
/*
/*
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
 */
 */


#include <linux/module.h>
#include <linux/module.h>
@@ -98,7 +98,6 @@ int wil_set_capabilities(struct wil6210_priv *wil)
		set_bit(hw_capa_no_flash, wil->hw_capa);
		set_bit(hw_capa_no_flash, wil->hw_capa);
		wil->use_enhanced_dma_hw = true;
		wil->use_enhanced_dma_hw = true;
		wil->use_rx_hw_reordering = true;
		wil->use_rx_hw_reordering = true;
		wil->use_compressed_rx_status = true;
		if (wil_ipa_offload())
		if (wil_ipa_offload())
			/* IPA offload must use single MSI */
			/* IPA offload must use single MSI */
			n_msi = 1;
			n_msi = 1;
+17 −2
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: ISC
// SPDX-License-Identifier: ISC
/*
/*
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
 */
 */


#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
@@ -942,7 +942,9 @@ void wil_netif_rx(struct sk_buff *skb, struct net_device *ndev, int cid,
			wil_dbg_txrx(wil, "Rx drop %d bytes\n", len);
			wil_dbg_txrx(wil, "Rx drop %d bytes\n", len);
			return;
			return;
		}
		}
	} else if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) {
	} else if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate &&
		   /* pass EAPOL packets to local net stack only */
		   (wil_skb_get_protocol(skb) != htons(ETH_P_PAE))) {
		if (mcast) {
		if (mcast) {
			/* send multicast frames both to higher layers in
			/* send multicast frames both to higher layers in
			 * local net stack and back to the wireless medium
			 * local net stack and back to the wireless medium
@@ -1000,6 +1002,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
{
{
	int cid, security;
	int cid, security;
	struct wil6210_priv *wil = ndev_to_wil(ndev);
	struct wil6210_priv *wil = ndev_to_wil(ndev);
	struct wil6210_vif *vif = ndev_to_vif(ndev);
	struct wil_net_stats *stats;
	struct wil_net_stats *stats;


	wil->txrx_ops.get_netif_rx_params(skb, &cid, &security);
	wil->txrx_ops.get_netif_rx_params(skb, &cid, &security);
@@ -1008,6 +1011,18 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)


	skb_orphan(skb);
	skb_orphan(skb);


	/* pass only EAPOL packets as plaintext */
	if (vif->privacy && !security &&
	    wil_skb_get_protocol(skb) != htons(ETH_P_PAE)) {
		wil_dbg_txrx(wil,
			     "Rx drop plaintext frame with %d bytes in secure network\n",
			     skb->len);
		dev_kfree_skb(skb);
		ndev->stats.rx_dropped++;
		stats->rx_dropped++;
		return;
	}

	if (security && (wil->txrx_ops.rx_crypto_check(wil, skb) != 0)) {
	if (security && (wil->txrx_ops.rx_crypto_check(wil, skb) != 0)) {
		wil_dbg_txrx(wil, "Rx drop %d bytes\n", skb->len);
		wil_dbg_txrx(wil, "Rx drop %d bytes\n", skb->len);
		dev_kfree_skb(skb);
		dev_kfree_skb(skb);
+8 −1
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: ISC */
/* SPDX-License-Identifier: ISC */
/*
/*
 * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
 * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
 */
 */


#ifndef WIL6210_TXRX_H
#ifndef WIL6210_TXRX_H
@@ -610,6 +610,13 @@ static inline u8 *wil_skb_get_sa(struct sk_buff *skb)
	return eth->h_source;
	return eth->h_source;
}
}


static inline __be16 wil_skb_get_protocol(struct sk_buff *skb)
{
	struct ethhdr *eth = (void *)skb->data;

	return eth->h_proto;
}

static inline bool wil_need_txstat(struct sk_buff *skb)
static inline bool wil_need_txstat(struct sk_buff *skb)
{
{
	const u8 *da = wil_skb_get_da(skb);
	const u8 *da = wil_skb_get_da(skb);
+93 −1
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: ISC
// SPDX-License-Identifier: ISC
/*
/*
 * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
 */
 */


#include <linux/etherdevice.h>
#include <linux/etherdevice.h>
@@ -806,6 +806,92 @@ static int wil_tx_ring_modify_edma(struct wil6210_vif *vif, int ring_id,
	return -EOPNOTSUPP;
	return -EOPNOTSUPP;
}
}


static int wil_check_amsdu(struct wil6210_priv *wil, void *msg, int cid,
			   struct wil_ring_rx_data *rxdata,
			   struct sk_buff *skb)
{
	u8 *sa, *da;
	int mid, tid;
	u16 seq;
	struct wil6210_vif *vif;
	struct net_device *ndev;
	struct wil_sta_info *sta;

	/* drop all WDS packets - not supported */
	if (wil_rx_status_get_ds_type(wil, msg) == WIL_RX_EDMA_DS_TYPE_WDS) {
		wil_dbg_txrx(wil, "WDS is not supported");
		return -EAGAIN;
	}

	/* check amsdu packets */
	sta = &wil->sta[cid];
	if (!wil_rx_status_is_basic_amsdu(msg)) {
		if (sta->amsdu_drop_sn != -1)
			wil_sta_info_amsdu_init(sta);
		return 0;
	}

	mid = wil_rx_status_get_mid(msg);
	tid = wil_rx_status_get_tid(msg);
	seq = le16_to_cpu(wil_rx_status_get_seq(wil, msg));
	vif = wil->vifs[mid];

	if (unlikely(!vif)) {
		wil_dbg_txrx(wil, "amsdu with invalid mid %d", mid);
		return -EAGAIN;
	}

	if (unlikely(sta->amsdu_drop)) {
		if (sta->amsdu_drop_sn == seq && sta->amsdu_drop_tid == tid) {
			wil_dbg_txrx(wil, "Drop AMSDU sub frame, sn=%d\n",
				     seq);
			return -EAGAIN;
		}

		/* previous AMSDU finished - clear drop amsdu flag */
		sta->amsdu_drop = 0;
	}

	da = wil_skb_get_da(skb);
	/* for all sub frame of the AMSDU, check that the SA or DA are valid
	 * compared with client/AP mac addresses
	 */
	switch (vif->wdev.iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
		if (is_multicast_ether_addr(da))
			return 0;

		/* On client side, DA should be the client mac address */
		ndev = vif_to_ndev(vif);
		if (ether_addr_equal(ndev->dev_addr, da))
			return 0;
		break;

	case NL80211_IFTYPE_P2P_GO:
	case NL80211_IFTYPE_AP:
		sa = wil_skb_get_sa(skb);
		/* On AP side, the packet SA should be the client mac address.
		 * check also the DA is not rfc 1042 header
		 */
		if (ether_addr_equal(sta->addr, sa) &&
		    !ether_addr_equal(rfc1042_header, da))
			return 0;
		break;
	default:
		return 0;
	}

	sta->amsdu_drop_sn = seq;
	sta->amsdu_drop_tid = tid;
	sta->amsdu_drop = 1;
	wil_dbg_txrx(wil,
		     "Drop AMSDU frame, sn=%d. Drop this and all next sub frames\n",
		     seq);

	return -EAGAIN;
}

/* This function is used only for RX SW reorder */
/* This function is used only for RX SW reorder */
static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
			 struct sk_buff *skb, struct wil_net_stats *stats)
			 struct sk_buff *skb, struct wil_net_stats *stats)
@@ -1107,6 +1193,12 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
	wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
	wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
			  skb->data, skb_headlen(skb), false);
			  skb->data, skb_headlen(skb), false);


	if (!wil->use_compressed_rx_status &&
	    wil_check_amsdu(wil, msg, cid, rxdata, skb)) {
		kfree_skb(skb);
		goto again;
	}

	/* Has to be done after dma_unmap_single as skb->cb is also
	/* Has to be done after dma_unmap_single as skb->cb is also
	 * used for holding the pa
	 * used for holding the pa
	 */
	 */
Loading