Merge "wil6210: check integrity of received AMSDU packets"

This commit is contained in:
qctecmdr 2021-05-22 10:31:07 -07:00 • committed by Gerrit - the friendly Code Review server
commit 191c26868f
8 changed files with 156 additions and 10 deletions

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: ISC
/*
* 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>
@ -310,6 +310,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
/* statistics */
memset(&sta->stats, 0, sizeof(sta->stats));
sta->stats.tx_latency_min_us = U32_MAX;
wil_sta_info_amsdu_init(sta);
}
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)
{
uint i;

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: ISC
/*
* 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>
@ -98,7 +98,6 @@ int wil_set_capabilities(struct wil6210_priv *wil)
set_bit(hw_capa_no_flash, wil->hw_capa);
wil->use_enhanced_dma_hw = true;
wil->use_rx_hw_reordering = true;
wil->use_compressed_rx_status = true;
if (wil_ipa_offload())
/* IPA offload must use single MSI */
n_msi = 1;

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: ISC
/*
* 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>
@ -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);
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) {
/* send multicast frames both to higher layers in
* 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;
struct wil6210_priv *wil = ndev_to_wil(ndev);
struct wil6210_vif *vif = ndev_to_vif(ndev);
struct wil_net_stats *stats;
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);
/* 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)) {
wil_dbg_txrx(wil, "Rx drop %d bytes\n", skb->len);
dev_kfree_skb(skb);

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: ISC */
/*
* 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
@ -610,6 +610,13 @@ static inline u8 *wil_skb_get_sa(struct sk_buff *skb)
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)
{
const u8 *da = wil_skb_get_da(skb);

View file

@ -1,6 +1,6 @@
// 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>
@ -806,6 +806,92 @@ static int wil_tx_ring_modify_edma(struct wil6210_vif *vif, int ring_id,
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 */
static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
struct sk_buff *skb, struct wil_net_stats *stats)
@ -1107,6 +1193,12 @@ skipping:
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
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
* used for holding the pa
*/

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2012-2016,2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2016,2018-2021, The Linux Foundation. All rights reserved.
*/
#ifndef WIL6210_TXRX_EDMA_H
@ -47,6 +47,9 @@
#define WIL_RX_EDMA_MID_VALID_BIT BIT(22)
#define WIL_RX_EDMA_AMSDU_BASIC_MASK 0x1
#define WIL_RX_EDMA_DS_TYPE_WDS 0x3
#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_POS 16
#define WIL_EDMA_DESC_TX_MAC_CFG_0_QID_LEN 6
@ -457,6 +460,21 @@ static inline int wil_rx_status_get_fc1(struct wil6210_priv *wil, void *msg)
0, 5) << 2;
}
static inline int wil_rx_status_get_ds_type(struct wil6210_priv *wil, void *msg)
{
if (wil->use_compressed_rx_status)
return 0;
return WIL_GET_BITS(((struct wil_rx_status_extended *)msg)->ext.d0,
19, 20);
}
static inline int wil_rx_status_is_basic_amsdu(void *msg)
{
return (WIL_GET_BITS(((struct wil_rx_status_compressed *)msg)->d1,
28, 29) == WIL_RX_EDMA_AMSDU_BASIC_MASK);
}
static inline __le16 wil_rx_status_get_seq(struct wil6210_priv *wil, void *msg)
{
if (wil->use_compressed_rx_status)

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
*/
#ifndef __WIL6210_H__
@ -783,6 +783,11 @@ struct wil_sta_info {
struct wil_tid_crypto_rx group_crypto_rx;
u8 aid; /* 1-254; 0 if unknown/not reported */
u8 fst_link_loss;
/* amsdu frame related info to check if the frame is valid */
int amsdu_drop_sn;
int amsdu_drop_tid;
u8 amsdu_drop;
};
enum {
@ -1563,4 +1568,5 @@ void update_supported_bands(struct wil6210_priv *wil);
int wmi_reset_spi_slave(struct wil6210_priv *wil);
void wil_clear_fw_log_addr(struct wil6210_priv *wil);
void wil_sta_info_amsdu_init(struct wil_sta_info *sta);
#endif /* __WIL6210_H__ */

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: ISC
/*
* 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>
@ -1092,6 +1092,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
wil->sta[evt->cid].mid = vif->mid;
wil->sta[evt->cid].status = wil_sta_conn_pending;
wil_sta_info_amsdu_init(&wil->sta[evt->cid]);
rc = wil_ring_init_tx(vif, evt->cid);
if (rc) {