Merge "qcacld-3.0: Do not intrabss forward fragmented EAPOL frames" into wlan-cld3.driver.lnx.2.0.r18
diff --git a/Kbuild b/Kbuild
index 791ca6c..d6aff10 100644
--- a/Kbuild
+++ b/Kbuild
@@ -2902,6 +2902,7 @@
cppflags-y += -DENABLE_HAL_REG_WR_HISTORY
cppflags-y += -DDP_RX_DESC_COOKIE_INVALIDATE
cppflags-y += -DPCI_LINK_STATUS_SANITY
+cppflags-y += -DDISABLE_EAPOL_INTRABSS_FWD
endif
cppflags-$(CONFIG_WLAN_CLD_PM_QOS) += -DCLD_PM_QOS
diff --git a/components/ipa/core/inc/wlan_ipa_priv.h b/components/ipa/core/inc/wlan_ipa_priv.h
index 2d3fc96..d3555b5 100644
--- a/components/ipa/core/inc/wlan_ipa_priv.h
+++ b/components/ipa/core/inc/wlan_ipa_priv.h
@@ -320,6 +320,7 @@
* @interface_lock: Interface lock
* @ifa_address: Interface address
* @stats: Interface stats
+ * @bssid: BSSID. valid only for sta iface ctx;
*/
struct wlan_ipa_iface_context {
struct wlan_ipa_priv *ipa_ctx;
@@ -334,6 +335,7 @@
qdf_spinlock_t interface_lock;
uint32_t ifa_address;
struct wlan_ipa_iface_stats stats;
+ struct qdf_mac_addr bssid;
};
/**
diff --git a/components/ipa/core/src/wlan_ipa_core.c b/components/ipa/core/src/wlan_ipa_core.c
index 96c75cc..57842bd 100644
--- a/components/ipa/core/src/wlan_ipa_core.c
+++ b/components/ipa/core/src/wlan_ipa_core.c
@@ -972,6 +972,33 @@
}
/**
+ * wlan_ipa_eapol_intrabss_fwd_check() - Check if eapol pkt intrabss fwd is
+ * allowed or not
+ * @ipa_ctx: IPA global context
+ * @vdev_id: vdev id
+ * @nbuf: network buffer
+ *
+ * Return: true if intrabss fwd is allowed for eapol else false
+ */
+static bool
+wlan_ipa_eapol_intrabss_fwd_check(struct wlan_ipa_priv *ipa_ctx,
+ uint8_t vdev_id, qdf_nbuf_t nbuf)
+{
+ uint8_t *vdev_mac_addr;
+
+ vdev_mac_addr = cdp_get_vdev_mac_addr(ipa_ctx->dp_soc, vdev_id);
+
+ if (!vdev_mac_addr)
+ return false;
+
+ if (qdf_mem_cmp(qdf_nbuf_data(nbuf) + QDF_NBUF_DEST_MAC_OFFSET,
+ vdev_mac_addr, QDF_MAC_ADDR_SIZE))
+ return false;
+
+ return true;
+}
+
+/**
* __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
* @priv: pointer to private data registered with IPA (we register a
* pointer to the global IPA context)
@@ -988,6 +1015,8 @@
uint8_t iface_id;
uint8_t session_id = 0xff;
struct wlan_ipa_iface_context *iface_context;
+ bool is_eapol_wapi = false;
+ struct qdf_mac_addr peer_mac_addr = QDF_MAC_ADDR_ZERO_INIT;
ipa_ctx = (struct wlan_ipa_priv *)priv;
if (!ipa_ctx) {
@@ -1037,6 +1066,46 @@
}
iface_context->stats.num_rx_ipa_excep++;
+ if (iface_context->device_mode == QDF_STA_MODE)
+ qdf_copy_macaddr(&peer_mac_addr, &iface_context->bssid);
+ else if (iface_context->device_mode == QDF_SAP_MODE)
+ qdf_mem_copy(&peer_mac_addr.bytes[0],
+ qdf_nbuf_data(skb) +
+ QDF_NBUF_SRC_MAC_OFFSET,
+ QDF_MAC_ADDR_SIZE);
+
+ if (qdf_nbuf_is_ipv4_eapol_pkt(skb)) {
+ is_eapol_wapi = true;
+ if (iface_context->device_mode == QDF_SAP_MODE &&
+ !wlan_ipa_eapol_intrabss_fwd_check(ipa_ctx,
+ iface_context->session_id, skb)) {
+ ipa_err_rl("EAPOL intrabss fwd drop DA:"QDF_MAC_ADDR_FMT,
+ QDF_MAC_ADDR_REF(qdf_nbuf_data(skb) +
+ QDF_NBUF_DEST_MAC_OFFSET));
+ ipa_ctx->ipa_rx_internal_drop_count++;
+ dev_kfree_skb_any(skb);
+ return;
+ }
+ } else if (qdf_nbuf_is_ipv4_wapi_pkt(skb)) {
+ is_eapol_wapi = true;
+ }
+
+ /*
+ * Check for peer authorized state before allowing
+ * non-EAPOL/WAPI frames to be intrabss forwarded
+ * or submitted to stack.
+ */
+ if (cdp_peer_state_get(ipa_ctx->dp_soc,
+ iface_context->session_id,
+ &peer_mac_addr.bytes[0]) !=
+ OL_TXRX_PEER_STATE_AUTH && !is_eapol_wapi) {
+ ipa_err_rl("Non EAPOL/WAPI packet received when peer "QDF_MAC_ADDR_FMT" is unauthorized",
+ QDF_MAC_ADDR_REF(peer_mac_addr.bytes));
+ ipa_ctx->ipa_rx_internal_drop_count++;
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
/* Disable to forward Intra-BSS Rx packets when
* ap_isolate=1 in hostapd.conf
*/
@@ -1467,6 +1536,7 @@
iface_context->session_id = WLAN_IPA_MAX_SESSION;
qdf_spin_unlock_bh(&iface_context->interface_lock);
iface_context->ifa_address = 0;
+ qdf_zero_macaddr(&iface_context->bssid);
if (!iface_context->ipa_ctx->num_iface) {
ipa_err("NUM INTF 0, Invalid");
QDF_ASSERT(0);
@@ -2029,6 +2099,14 @@
}
#endif
+static inline void
+wlan_ipa_save_bssid_iface_ctx(struct wlan_ipa_priv *ipa_ctx, uint8_t iface_id,
+ uint8_t *mac_addr)
+{
+ qdf_mem_copy(ipa_ctx->iface_context[iface_id].bssid.bytes,
+ mac_addr, QDF_MAC_ADDR_SIZE);
+}
+
/**
* __wlan_ipa_wlan_evt() - IPA event handler
* @net_dev: Interface net device
@@ -2230,6 +2308,10 @@
ipa_ctx->vdev_to_iface[session_id] =
wlan_ipa_get_ifaceid(ipa_ctx, session_id);
+ wlan_ipa_save_bssid_iface_ctx(ipa_ctx,
+ ipa_ctx->vdev_to_iface[session_id],
+ mac_addr);
+
if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
(ipa_ctx->sap_num_connected_sta > 0 ||
wlan_ipa_is_sta_only_offload_enabled()) &&
diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c
index 5ae389f..bfaef16 100644
--- a/core/dp/txrx/ol_rx_defrag.c
+++ b/core/dp/txrx/ol_rx_defrag.c
@@ -414,6 +414,8 @@
struct ol_rx_reorder_array_elem_t *rx_reorder_array_elem;
uint16_t frxseq, rxseq, seq;
htt_pdev_handle htt_pdev = pdev->htt_pdev;
+ void *rx_desc;
+ uint8_t index;
seq = seq_num & peer->tids_rx_reorder[tid].win_sz_mask;
qdf_assert(seq == 0);
@@ -427,6 +429,28 @@
IEEE80211_SEQ_FRAG_MASK;
more_frag = mac_hdr->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
+ rx_desc = htt_rx_msdu_desc_retrieve(htt_pdev, frag);
+ qdf_assert(htt_rx_msdu_has_wlan_mcast_flag(htt_pdev, rx_desc));
+ index = htt_rx_msdu_is_wlan_mcast(htt_pdev, rx_desc) ?
+ txrx_sec_mcast : txrx_sec_ucast;
+
+ /*
+ * Multicast/Broadcast frames should not be fragmented so drop
+ * such frames.
+ */
+ if (index != txrx_sec_ucast) {
+ ol_rx_frames_free(htt_pdev, frag);
+ return;
+ }
+
+ if (peer->security[index].sec_type != htt_sec_type_none &&
+ !htt_rx_mpdu_is_encrypted(htt_pdev, rx_desc)) {
+ ol_txrx_err("Unencrypted fragment received in security mode %d",
+ peer->security[index].sec_type);
+ ol_rx_frames_free(htt_pdev, frag);
+ return;
+ }
+
if ((!more_frag) && (!fragno) && (!rx_reorder_array_elem->head)) {
rx_reorder_array_elem->head = frag;
rx_reorder_array_elem->tail = frag;
@@ -668,7 +692,13 @@
while (cur) {
tmp_next = qdf_nbuf_next(cur);
qdf_nbuf_set_next(cur, NULL);
- if (!ol_rx_pn_check_base(vdev, peer, tid, cur)) {
+ /*
+ * Strict PN check between the first fragment of the current
+ * frame and the last fragment of the previous frame is not
+ * necessary.
+ */
+ if (!ol_rx_pn_check_base(vdev, peer, tid, cur,
+ (cur == frag_list) ? false : true)) {
/* PN check failed,discard frags */
if (prev) {
qdf_nbuf_set_next(prev, NULL);
diff --git a/core/dp/txrx/ol_rx_pn.c b/core/dp/txrx/ol_rx_pn.c
index 3920c17..2cb9748 100644
--- a/core/dp/txrx/ol_rx_pn.c
+++ b/core/dp/txrx/ol_rx_pn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013-2017, 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2013-2017, 2019, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -37,25 +37,36 @@
} while (0)
int ol_rx_pn_cmp24(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode)
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk)
{
- int rc = ((new_pn->pn24 & 0xffffff) <= (old_pn->pn24 & 0xffffff));
- return rc;
+ if (strict_chk)
+ return ((new_pn->pn24 & 0xffffff) - (old_pn->pn24 & 0xffffff)
+ != 1);
+ else
+ return ((new_pn->pn24 & 0xffffff) <= (old_pn->pn24 & 0xffffff));
}
int ol_rx_pn_cmp48(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode)
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk)
{
- int rc = ((new_pn->pn48 & 0xffffffffffffULL) <=
- (old_pn->pn48 & 0xffffffffffffULL));
- return rc;
+ if (strict_chk)
+ return ((new_pn->pn48 & 0xffffffffffffULL) -
+ (old_pn->pn48 & 0xffffffffffffULL) != 1);
+ else
+ return ((new_pn->pn48 & 0xffffffffffffULL) <=
+ (old_pn->pn48 & 0xffffffffffffULL));
}
int ol_rx_pn_wapi_cmp(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode)
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk)
{
int pn_is_replay = 0;
+ /* TODO Strick check for WAPI is not implemented*/
+
if (new_pn->pn128[1] == old_pn->pn128[1])
pn_is_replay = (new_pn->pn128[0] <= old_pn->pn128[0]);
else
@@ -73,7 +84,7 @@
qdf_nbuf_t
ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev,
struct ol_txrx_peer_t *peer,
- unsigned int tid, qdf_nbuf_t msdu_list)
+ unsigned int tid, qdf_nbuf_t msdu_list, bool strict_chk)
{
struct ol_txrx_pdev_t *pdev = vdev->pdev;
union htt_rx_pn_t *last_pn;
@@ -132,7 +143,7 @@
pn_is_replay =
pdev->rx_pn[peer->security[index].sec_type].
cmp(&new_pn, last_pn, index == txrx_sec_ucast,
- vdev->opmode);
+ vdev->opmode, strict_chk);
} else {
last_pn_valid = peer->tids_last_pn_valid[tid] = 1;
}
@@ -249,7 +260,7 @@
struct ol_txrx_peer_t *peer, unsigned int tid,
qdf_nbuf_t msdu_list)
{
- msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list);
+ msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list, false);
ol_rx_fwd_check(vdev, peer, tid, msdu_list);
}
@@ -258,7 +269,7 @@
struct ol_txrx_peer_t *peer,
unsigned int tid, qdf_nbuf_t msdu_list)
{
- msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list);
+ msdu_list = ol_rx_pn_check_base(vdev, peer, tid, msdu_list, false);
ol_rx_deliver(vdev, peer, tid, msdu_list);
}
diff --git a/core/dp/txrx/ol_rx_pn.h b/core/dp/txrx/ol_rx_pn.h
index 8e0c007..fa64c3e 100644
--- a/core/dp/txrx/ol_rx_pn.h
+++ b/core/dp/txrx/ol_rx_pn.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2014-2017, 2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -24,13 +24,16 @@
#include <ol_txrx_api.h> /* ol_txrx_peer_t, etc. */
int ol_rx_pn_cmp24(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode);
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk);
int ol_rx_pn_cmp48(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode);
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk);
int ol_rx_pn_wapi_cmp(union htt_rx_pn_t *new_pn,
- union htt_rx_pn_t *old_pn, int is_unicast, int opmode);
+ union htt_rx_pn_t *old_pn, int is_unicast, int opmode,
+ bool strict_chk);
/**
* @brief If applicable, check the Packet Number to detect replays.
@@ -87,11 +90,12 @@
* @param tid - which TID within the peer the rx frames belong to
* @param msdu_list - NULL-terminated list of MSDUs to perform PN check on
* (if PN check is applicable, i.e. PN length > 0)
+ * @param strick_chk - if PN consecutive stric check is needed or not
* @return list of netbufs that didn't fail the PN check
*/
qdf_nbuf_t
ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev,
struct ol_txrx_peer_t *peer,
- unsigned int tid, qdf_nbuf_t msdu_list);
+ unsigned int tid, qdf_nbuf_t msdu_list, bool strict_chk);
#endif /* _OL_RX_PN_H_ */
diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c
index b8a9872..e900ef9 100644
--- a/core/dp/txrx/ol_txrx.c
+++ b/core/dp/txrx/ol_txrx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -1439,14 +1439,32 @@
*/
qdf_mem_zero(&pdev->rx_pn[0], sizeof(pdev->rx_pn));
+ /* WEP: 24-bit PN */
+ pdev->rx_pn[htt_sec_type_wep40].len =
+ pdev->rx_pn[htt_sec_type_wep104].len =
+ pdev->rx_pn[htt_sec_type_wep128].len = 24;
+
+ pdev->rx_pn[htt_sec_type_wep40].cmp =
+ pdev->rx_pn[htt_sec_type_wep104].cmp =
+ pdev->rx_pn[htt_sec_type_wep128].cmp = ol_rx_pn_cmp24;
+
/* TKIP: 48-bit TSC, CCMP: 48-bit PN */
pdev->rx_pn[htt_sec_type_tkip].len =
pdev->rx_pn[htt_sec_type_tkip_nomic].len =
pdev->rx_pn[htt_sec_type_aes_ccmp].len = 48;
+
+ pdev->rx_pn[htt_sec_type_aes_ccmp_256].len =
+ pdev->rx_pn[htt_sec_type_aes_gcmp].len =
+ pdev->rx_pn[htt_sec_type_aes_gcmp_256].len = 48;
+
pdev->rx_pn[htt_sec_type_tkip].cmp =
pdev->rx_pn[htt_sec_type_tkip_nomic].cmp =
pdev->rx_pn[htt_sec_type_aes_ccmp].cmp = ol_rx_pn_cmp48;
+ pdev->rx_pn[htt_sec_type_aes_ccmp_256].cmp =
+ pdev->rx_pn[htt_sec_type_aes_gcmp].cmp =
+ pdev->rx_pn[htt_sec_type_aes_gcmp_256].cmp = ol_rx_pn_cmp48;
+
/* WAPI: 128-bit PN */
pdev->rx_pn[htt_sec_type_wapi].len = 128;
pdev->rx_pn[htt_sec_type_wapi].cmp = ol_rx_pn_wapi_cmp;
diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h
index e298612..f9fedd3 100644
--- a/core/dp/txrx/ol_txrx_types.h
+++ b/core/dp/txrx/ol_txrx_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -834,7 +834,7 @@
struct {
int (*cmp)(union htt_rx_pn_t *new,
union htt_rx_pn_t *old,
- int is_unicast, int opmode);
+ int is_unicast, int opmode, bool strict_chk);
int len;
} rx_pn[htt_num_sec_types];
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 294ae9f..915bd12 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -17689,6 +17689,9 @@
if (pairwise)
wma_set_peer_ucast_cipher(mac_address.bytes, cipher);
+ cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC),
+ wlan_vdev_get_id(vdev), mac_address.bytes);
+
switch (adapter->device_mode) {
case QDF_IBSS_MODE:
errno = wlan_hdd_add_key_ibss(adapter, pairwise, key_index,
diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c
index 81b18aa..aff65d1 100644
--- a/core/hdd/src/wlan_hdd_softap_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c
@@ -1136,6 +1136,15 @@
STA_INFO_SOFTAP_RX_PACKET_CBK);
}
+ if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(skb) &&
+ qdf_mem_cmp(qdf_nbuf_data(skb) +
+ QDF_NBUF_DEST_MAC_OFFSET,
+ adapter->mac_addr.bytes,
+ QDF_MAC_ADDR_SIZE))) {
+ qdf_nbuf_free(skb);
+ continue;
+ }
+
hdd_event_eapol_log(skb, QDF_RX);
qdf_dp_trace_log_pkt(adapter->vdev_id,
skb, QDF_RX, QDF_TRACE_DEFAULT_PDEV_ID);
diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c
index 16b7f50..b2c0b99 100644
--- a/core/wma/src/wma_mgmt.c
+++ b/core/wma/src/wma_mgmt.c
@@ -902,46 +902,6 @@
return 0;
}
-#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS)
-
-/**
- * wma_unified_peer_state_update() - update peer state
- * @sta_mac: pointer to sta mac addr
- * @bss_addr: bss address
- * @sta_type: sta entry type
- *
- *
- * Return: None
- */
-static void
-wma_unified_peer_state_update(
- uint8_t *sta_mac,
- uint8_t *bss_addr,
- uint8_t sta_type)
-{
- void *soc = cds_get_context(QDF_MODULE_ID_SOC);
-
- if (STA_ENTRY_TDLS_PEER == sta_type)
- cdp_peer_state_update(soc, sta_mac,
- OL_TXRX_PEER_STATE_AUTH);
- else
- cdp_peer_state_update(soc, bss_addr,
- OL_TXRX_PEER_STATE_AUTH);
-}
-#else
-
-static inline void
-wma_unified_peer_state_update(
- uint8_t *sta_mac,
- uint8_t *bss_addr,
- uint8_t sta_type)
-{
- void *soc = cds_get_context(QDF_MODULE_ID_SOC);
-
- cdp_peer_state_update(soc, bss_addr, OL_TXRX_PEER_STATE_AUTH);
-}
-#endif
-
#define CFG_CTRL_MASK 0xFF00
#define CFG_DATA_MASK 0x00FF
@@ -1506,9 +1466,6 @@
if (params->wpa_rsn >> 1)
cmd->need_gtk_2_way = 1;
- wma_unified_peer_state_update(params->staMac,
- params->bssId, params->staType);
-
#ifdef FEATURE_WLAN_WAPI
if (params->encryptType == eSIR_ED_WPI) {
ret = wma_vdev_set_param(wma->wmi_handle, params->smesessionId,