mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
Merge "wil6210: check integrity of received AMSDU packets"
This commit is contained in:
commit
191c26868f
8 changed files with 156 additions and 10 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue