From aa151aa02a11159b4e19fa98e9812aeac4906c0e Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Thu, 12 Dec 2019 14:17:03 +0530 Subject: qcacld-3.0: Validate assoc response IE len before copy When host sends ft assoc response to supplicant, it allocates a buffer of fixed size and copies a variable length of assoc response IEs to this fixed sized buffer. There is a possibility of OOB write to the allocated buffer if the assoc response IEs length is greater than the allocated buffer size. To avoid above issue validate the assoc response IEs length with the allocated buffer size before data copy to the buffer. Change-ID: Ife9c2071a8cc4a2918b9f349f4024478f94b2d78 CRs-Fixed: 2575144 --- core/hdd/src/wlan_hdd_assoc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index dff5e4fec567..df3aa8be02c8 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1103,8 +1103,9 @@ hdd_send_ft_assoc_response(struct net_device *dev, unsigned int len = 0; u8 *pFTAssocRsp = NULL; - if (pCsrRoamInfo->nAssocRspLength == 0) { - hdd_debug("assoc rsp length is 0"); + if (pCsrRoamInfo->nAssocRspLength < FT_ASSOC_RSP_IES_OFFSET) { + hdd_debug("Invalid assoc rsp length %d", + pCsrRoamInfo->nAssocRspLength); return; } @@ -1121,15 +1122,20 @@ hdd_send_ft_assoc_response(struct net_device *dev, (unsigned int)pFTAssocRsp[0], (unsigned int)pFTAssocRsp[1]); + /* Send the Assoc Resp, the supplicant needs this for initial Auth. */ + len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; + if (len > IW_GENERIC_IE_MAX) { + hdd_err("Invalid Assoc resp length %d", len); + return; + } + wrqu.data.length = len; + /* We need to send the IEs to the supplicant. */ buff = qdf_mem_malloc(IW_GENERIC_IE_MAX); if (buff == NULL) { hdd_err("unable to allocate memory"); return; } - /* Send the Assoc Resp, the supplicant needs this for initial Auth. */ - len = pCsrRoamInfo->nAssocRspLength - FT_ASSOC_RSP_IES_OFFSET; - wrqu.data.length = len; memcpy(buff, pFTAssocRsp, len); wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, buff); -- cgit v1.2.3 From e4dbe91724e48d330d622827b1130d2707d91c6f Mon Sep 17 00:00:00 2001 From: Gururaj Pandurangi Date: Wed, 26 Feb 2020 11:00:07 -0800 Subject: qcacld-3.0: Fix while condition in rrm_fill_beacon_ies() In function rrm_fill_beacon_ies, do while loop is checked for BcnNumIes if it is greater than IE length 0. Fix the check to be greater than 2 as the first two bytes is IE header(element ID and IE length fields both 1 byte each.) Change-Id: I11e5de481cd49a22acafee938fbe73f839f5b0e4 CRs-Fixed: 2626729 --- core/mac/src/pe/rrm/rrm_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c index 5ef0a9afbb0c..fe196f7d9a90 100644 --- a/core/mac/src/pe/rrm/rrm_api.c +++ b/core/mac/src/pe/rrm/rrm_api.c @@ -746,7 +746,7 @@ rrm_fill_beacon_ies(tpAniSirGlobal pMac, pIes += sizeof(uint16_t); } - while (BcnNumIes > 0) { + while (BcnNumIes >= 2) { len = *(pBcnIes + 1); len += 2; /* element id + length. */ pe_debug("EID = %d, len = %d total = %d", -- cgit v1.2.3 From 2668ab7b67e4d434e299a07ca11ad351ec313f8b Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Wed, 23 Dec 2020 09:59:43 +0530 Subject: qcacld-3.0: Send assoc reject upon failing to post ASSOC_IND Currently, lim silently drops the association if it fails to post ASSOC_IND due to some reason(e.g. invalid contents of assoc request) and the MLM state is stuck in eLIM_MLM_WT_ASSOC_CNF_STATE. Station context is not cleaned up till the next association. Gracefully cleanup the association in such failure cases. Change-Id: Iede43a1ddc4ac6ef300af02776b153b58dd70c2c CRs-Fixed: 2810235 --- core/mac/src/pe/lim/lim_process_assoc_req_frame.c | 26 +++++++--------------- core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c | 10 ++++++++- core/mac/src/pe/lim/lim_types.h | 17 ++++++++++++-- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 5cded988402d..1ec446dffacc 100644 --- a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -2382,19 +2382,9 @@ static void fill_mlm_assoc_ind_vht(tpSirAssocReq assocreq, } } -/** - * lim_send_mlm_assoc_ind() - Sends assoc indication to SME - * @mac_ctx: Global Mac context - * @sta_ds: Station DPH hash entry - * @session_entry: PE session entry - * - * This function sends either LIM_MLM_ASSOC_IND - * or LIM_MLM_REASSOC_IND to SME. - * - * Return: None - */ -void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, - tpDphHashNode sta_ds, tpPESession session_entry) +QDF_STATUS lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, + tpPESession session_entry) { tpLimMlmAssocInd assoc_ind = NULL; tpSirAssocReq assoc_req; @@ -2407,7 +2397,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, if (!session_entry->parsedAssocReq) { pe_err(" Parsed Assoc req is NULL"); - return; + return QDF_STATUS_E_INVAL; } /* Get a copy of the already parsed Assoc Request */ @@ -2416,7 +2406,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, if (!assoc_req) { pe_err("assoc req for assoc_id:%d is NULL", sta_ds->assocId); - return; + return QDF_STATUS_E_INVAL; } /* Get the phy_mode */ @@ -2441,7 +2431,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, lim_release_peer_idx(mac_ctx, sta_ds->assocId, session_entry); pe_err("AllocateMemory failed for assoc_ind"); - return; + return QDF_STATUS_E_NOMEM; } qdf_mem_copy((uint8_t *) assoc_ind->peerMacAddr, (uint8_t *) sta_ds->staAddr, sizeof(tSirMacAddr)); @@ -2494,7 +2484,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, pe_err("rsnIEdata index out of bounds: %d", rsn_len); qdf_mem_free(assoc_ind); - return; + return QDF_STATUS_E_INVAL; } assoc_ind->rsnIE.rsnIEdata[rsn_len] = SIR_MAC_WPA_EID; @@ -2648,5 +2638,5 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, (uint32_t *) assoc_ind); qdf_mem_free(assoc_ind); } - return; + return QDF_STATUS_SUCCESS; } diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index f21787407d6b..c513e55c40ac 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1977,7 +1977,15 @@ void lim_process_ap_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, * 2) PE receives eWNI_SME_ASSOC_CNF from SME * 3) BTAMP-AP sends Re/Association Response to BTAMP-STA */ - lim_send_mlm_assoc_ind(pMac, pStaDs, psessionEntry); + if (lim_send_mlm_assoc_ind(pMac, pStaDs, psessionEntry) != + QDF_STATUS_SUCCESS) { + lim_reject_association(pMac, pStaDs->staAddr, + pStaDs->mlmStaContext.subType, + true, pStaDs->mlmStaContext.authType, + pStaDs->assocId, true, + eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry); + } /* fall though to reclaim the original Add STA Response message */ end: if (0 != limMsgQ->bodyptr) { diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index babb7ffae70f..ac78c9f2ead6 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -458,8 +458,21 @@ tSirRetStatus lim_process_auth_frame_no_session(tpAniSirGlobal pMac, uint8_t *, void *body); void lim_process_assoc_req_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession); -void lim_send_mlm_assoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, - tpPESession psessionEntry); + +/** + * lim_send_mlm_assoc_ind() - Sends assoc indication to SME + * @mac_ctx: Global Mac context + * @sta_ds: Station DPH hash entry + * @session_entry: PE session entry + * + * This function sends either LIM_MLM_ASSOC_IND + * or LIM_MLM_REASSOC_IND to SME. + * + * Return: QDF_STATUS + */ +QDF_STATUS lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, + tpPESession session_entry); void lim_process_assoc_rsp_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession); void lim_process_disassoc_frame(tpAniSirGlobal, uint8_t *, tpPESession); -- cgit v1.2.3 From c19e3e2207689da7a6ea18e523d796bdc44aafdf Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Sat, 23 Jan 2021 01:11:38 +0530 Subject: qcacld-3.0: lim_strip_ie to extract multiple IEs of given type Currently lim_strip_ie strips the matched IEs from given buffer but return only last matched IE. All the previous IEs matched to the given type are lost. Fix this to strip and extract all IEs matched to given type. This is to address the case when multiple vendor specific IEs are given from userspace. Current implementation returns only last vendor specific IE. This is to fix the same Change-Id: I64ca5d2e679b8457dc2cbaf7b4b12dc0a840260d CRs-Fixed: 2499592 --- core/mac/src/pe/lim/lim_utils.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 253c87bbfced..23b9df7f258a 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-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 @@ -6550,7 +6550,7 @@ tSirRetStatus lim_strip_ie(tpAniSirGlobal mac_ctx, int left = *addn_ielen; uint8_t *ptr = addn_ie; uint8_t elem_id; - uint16_t elem_len; + uint16_t elem_len, ie_len, extracted_ie_len = 0; if (NULL == addn_ie) { pe_err("NULL addn_ie pointer"); @@ -6563,6 +6563,10 @@ tSirRetStatus lim_strip_ie(tpAniSirGlobal mac_ctx, return eSIR_MEM_ALLOC_FAILED; } + if (extracted_ie) + qdf_mem_set(extracted_ie, eid_max_len + size_of_len_field + 1, + 0); + while (left >= 2) { elem_id = ptr[0]; left -= 1; @@ -6593,12 +6597,13 @@ tSirRetStatus lim_strip_ie(tpAniSirGlobal mac_ctx, * take oui IE and store in provided buffer. */ if (NULL != extracted_ie) { - qdf_mem_set(extracted_ie, - eid_max_len + size_of_len_field + 1, - 0); - if (elem_len <= eid_max_len) - qdf_mem_copy(extracted_ie, &ptr[0], - elem_len + size_of_len_field + 1); + ie_len = elem_len + size_of_len_field + 1; + if (ie_len <= eid_max_len - extracted_ie_len) { + qdf_mem_copy( + extracted_ie + extracted_ie_len, + &ptr[0], ie_len); + extracted_ie_len += ie_len; + } } } left -= elem_len; -- cgit v1.2.3 From 1edcf4f6758512de056709edcb667b9902630031 Mon Sep 17 00:00:00 2001 From: Jyoti Kumari Date: Fri, 29 Jan 2021 12:59:07 +0530 Subject: qcacld-3.0: Fix integer underflow in assoc response frame In func aead_decrypt_assoc_rsp(), it calls find_ie_data_after_fils_session_ie() to find IE pointer after FILS session IE from the frame payload. There is possibility of integer underflow if frame payload length is less than FIXED_PARAM_OFFSET_ASSOC_RSP which may increase value of buf_len variable in find_ie_data_after_fils_session_ie() and cause OOB during parsing process. Validate frame payload length with FIXED_PARAM_OFFSET_ASSOC_RSP, if it is less then return failure. Change-Id: I78fbcfeaa1058fcf2a6fe47cd5c26390b54974af CRs-Fixed: 2859024 --- core/mac/src/pe/lim/lim_process_fils.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/mac/src/pe/lim/lim_process_fils.c b/core/mac/src/pe/lim/lim_process_fils.c index 4877816d63c0..c37ffd12ea9b 100644 --- a/core/mac/src/pe/lim/lim_process_fils.c +++ b/core/mac/src/pe/lim/lim_process_fils.c @@ -1819,6 +1819,11 @@ QDF_STATUS aead_decrypt_assoc_rsp(tpAniSirGlobal mac_ctx, uint8_t *fils_ies; struct pe_fils_session *fils_info = (session->fils_info); + if (*n_frame < FIXED_PARAM_OFFSET_ASSOC_RSP) { + pe_debug("payload len is less than ASSOC RES offset"); + return QDF_STATUS_E_FAILURE; + } + status = find_ie_data_after_fils_session_ie(mac_ctx, p_frame + FIXED_PARAM_OFFSET_ASSOC_RSP, ((*n_frame) - -- cgit v1.2.3 From e170c984c6e88302640c4d627833735c0592f42b Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 23 Feb 2021 14:53:31 +0530 Subject: qcacld-3.0: Drop mcast and plaintext frags in protected network Multicast frames should not be fragmented and plaintext frags should not be reassembeld in protected network. Fix is to drop mcast frags and plaintext frags received in protected network. Change-Id: I98cf0715f5832f2f86f86b79dbdbc3a7c86dbfd0 CRs-Fixed: 2860245 --- core/dp/txrx/ol_rx_defrag.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c index 84045eb8ad58..81361a408ba7 100644 --- a/core/dp/txrx/ol_rx_defrag.c +++ b/core/dp/txrx/ol_rx_defrag.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-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 @@ -445,6 +445,8 @@ ol_rx_reorder_store_frag(ol_txrx_pdev_handle pdev, 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); @@ -458,6 +460,28 @@ ol_rx_reorder_store_frag(ol_txrx_pdev_handle pdev, 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)) { ol_rx_fraglist_insert(htt_pdev, &rx_reorder_array_elem->head, &rx_reorder_array_elem->tail, frag, &all_frag_present); -- cgit v1.2.3 From 6595c44aeb7fb00e6b94728e085bd886b5e37764 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 23 Feb 2021 14:16:01 +0530 Subject: qcacld-3.0: Add support to flush fragments for a particular peer Add support for flushing fragments for a particular peer. Change-Id: I91236d2edc73317380590458b974013a02e858a1 CRs-Fixed: 2860131 --- core/dp/txrx/ol_txrx.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index ecf0bf196a2e..77ccb248596c 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -1,5 +1,8 @@ /* - * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2019, 2021 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -4004,6 +4007,26 @@ ol_txrx_peer_find_by_addr(struct ol_txrx_pdev_t *pdev, uint8_t *peer_mac_addr) return peer; } +void +ol_txrx_peer_flush_frags(ol_txrx_pdev_handle pdev, uint8_t vdev_id, + uint8_t *peer_mac) +{ + struct ol_txrx_peer_t *peer; + uint8_t peer_id; + + if (!pdev) + return; + + peer = ol_txrx_find_peer_by_addr_inc_ref(pdev, peer_mac, &peer_id); + + if (!peer) + return; + + ol_rx_reorder_peer_cleanup(peer->vdev, peer); + + OL_TXRX_PEER_UNREF_DELETE(peer); +} + /** * ol_txrx_dump_tx_desc() - dump tx desc total and free count * @txrx_pdev: Pointer to txrx pdev -- cgit v1.2.3 From 967fac24625f7e06cfdebb440f5dbb11131036ea Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 23 Feb 2021 14:46:11 +0530 Subject: qcacld-3.0: Flush frags for peer on add key request Fragments are not flushed as part of rekey which could result in fragments encrypted under different keys to be reassembled. Fix is to flush fragments for the peer for which add key request is received. Change-Id: I0c018ff7375272125c62aaea7b8ad4df9e842508 CRs-Fixed: 2875950 --- core/hdd/src/wlan_hdd_cfg80211.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 75254e293084..73e5e9f453cb 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1,5 +1,8 @@ /* - * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, 2021 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -15473,6 +15476,12 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy, QDF_STATUS qdf_ret_status; hdd_context_t *pHddCtx; hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter); + ol_txrx_pdev_handle pdev = cds_get_context(QDF_MODULE_ID_TXRX); + + if (!pdev) { + hdd_err("DP pdev is NULL"); + return -EINVAL; + } ENTER(); @@ -15636,6 +15645,10 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy, setKey.keyDirection = eSIR_TX_RX; qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE); } + + ol_txrx_peer_flush_frags(pdev, pAdapter->sessionId, + setKey.peerMac.bytes); + if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) { /* if a key is already installed, block all subsequent ones */ if (pAdapter->sessionCtx.station.ibss_enc_key_installed) { -- cgit v1.2.3 From 081cea2bfb2a096d9da1e401c042cc332b6f5b70 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 23 Feb 2021 14:51:04 +0530 Subject: qcacld-3.0: Modify check to ensure consecutive PN for frags Modify check to ensure packet number is consecutive for fragments and drop the fragments if the check fails. Change-Id: Ica24f65aff65ca58bb010c876f27964b5b2bae6a CRs-Fixed: 2860242 --- core/dp/txrx/ol_rx_defrag.c | 13 +++++++++++-- core/dp/txrx/ol_rx_pn.c | 37 ++++++++++++++++++++++++------------- core/dp/txrx/ol_rx_pn.h | 14 +++++++++----- core/dp/txrx/ol_txrx.c | 18 ++++++++++++++++++ core/dp/txrx/ol_txrx_types.h | 7 +++++-- 5 files changed, 67 insertions(+), 22 deletions(-) diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c index 81361a408ba7..e066ab5498e2 100644 --- a/core/dp/txrx/ol_rx_defrag.c +++ b/core/dp/txrx/ol_rx_defrag.c @@ -1,5 +1,8 @@ /* - * Copyright (c) 2011-2019, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2021 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -724,7 +727,13 @@ ol_rx_defrag(ol_txrx_pdev_handle pdev, 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 dd09c3f50c71..0bd8e75e5191 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 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2013-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 @@ -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 @@ int ol_rx_pn_wapi_cmp(union htt_rx_pn_t *new_pn, 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 @@ ol_rx_pn_check_base(struct ol_txrx_vdev_t *vdev, 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; } @@ -253,7 +264,7 @@ ol_rx_pn_check(struct ol_txrx_vdev_t *vdev, 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); } @@ -262,7 +273,7 @@ ol_rx_pn_check_only(struct ol_txrx_vdev_t *vdev, 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 8e0c007b091d..fa64c3e5133c 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_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 @@ ol_rx_pn_check_only(struct ol_txrx_vdev_t *vdev, * @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 77ccb248596c..3ebee628a5bf 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -1954,14 +1954,32 @@ ol_txrx_pdev_post_attach(ol_txrx_pdev_handle pdev) */ qdf_mem_set(&pdev->rx_pn[0], sizeof(pdev->rx_pn), 0); + /* 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 3203a75ebeb0..c6a68c057d17 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -1,5 +1,8 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, 2021 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -802,7 +805,7 @@ struct ol_txrx_pdev_t { 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]; -- cgit v1.2.3 From 9268d8d1ba0a9c1e9473467ab8542c45b5f8a0b7 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 23 Feb 2021 14:59:49 +0530 Subject: qcacld-3.0: Drop non-EAPOL/WAPI frames from unauthorized peer Drop non-EAPOL/WAPI frames from unauthorized peer received in the IPA exception path. Change-Id: I0c0bc6e60efa193126ba1e3eca36c5e02f7f76a3 CRs-Fixed: 2860206 --- core/hdd/src/wlan_hdd_ipa.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 6d1377ef0b02..05978a3acba8 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -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 @@ -5798,6 +5798,12 @@ static void __hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, struct hdd_ipa_iface_context *iface_context; uint8_t fw_desc; QDF_STATUS status = QDF_STATUS_SUCCESS; + bool is_eapol_wapi = false; + struct qdf_mac_addr peer_mac_addr = QDF_MAC_ADDR_ZERO_INITIALIZER; + uint8_t sta_idx; + ol_txrx_peer_handle peer; + ol_txrx_pdev_handle pdev; + hdd_station_ctx_t *sta_ctx; hdd_ipa = (struct hdd_ipa_priv *)priv; @@ -5821,6 +5827,13 @@ static void __hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, return; } + pdev = cds_get_context(QDF_MODULE_ID_TXRX); + if (NULL == pdev) { + WMA_LOGE("%s: DP pdev is NULL", __func__); + kfree_skb(skb); + return; + } + if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) { session_id = (uint8_t)skb->cb[0]; iface_id = hdd_ipa->vdev_to_iface[session_id]; @@ -5863,6 +5876,38 @@ static void __hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, skb_pull(skb, HDD_IPA_WLAN_CLD_HDR_LEN); } + if (iface_context->adapter->device_mode == QDF_STA_MODE) { + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR( + iface_context->adapter); + qdf_copy_macaddr(&peer_mac_addr, + &sta_ctx->conn_info.bssId); + } else if (iface_context->adapter->device_mode + == QDF_SAP_MODE) { + qdf_mem_copy(peer_mac_addr.bytes, qdf_nbuf_data(skb) + + QDF_NBUF_SRC_MAC_OFFSET, + QDF_MAC_ADDR_SIZE); + } + + if (qdf_nbuf_is_ipv4_eapol_pkt(skb) || + qdf_nbuf_is_ipv4_wapi_pkt(skb)) + is_eapol_wapi = true; + + peer = ol_txrx_find_peer_by_addr(pdev, peer_mac_addr.bytes, + &sta_idx); + + /* + * Check for peer auth state before allowing non-EAPOL/WAPI + * frames to be intrabss forwarded or submitted to stack. + */ + if (peer && ol_txrx_get_peer_state(peer) != + OL_TXRX_PEER_STATE_AUTH && !is_eapol_wapi) { + HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, + "non-EAPOL/WAPI frame received when peer is unauthorized"); + hdd_ipa->ipa_rx_internal_drop_count++; + kfree_skb(skb); + return; + } + iface_context->stats.num_rx_ipa_excep++; /* Disable to forward Intra-BSS Rx packets when -- cgit v1.2.3 From c95b6fbdb7970d33fb4102e62d5bf5cd855c150c Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Sat, 27 Feb 2021 01:07:29 +0530 Subject: qcacld-3.0: Drop EAPOL frame with DA different from SAP vdev mac addr Fragmented EAPOL frames and EAPOL frames received in few error scenarios with DA different from SAP vdev mac addr will be dropped. Change-Id: I624eba5bdb43c6b88a1f57112550f8026cc35e24 CRs-Fixed: 2888227 --- core/hdd/src/wlan_hdd_softap_tx_rx.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c index c66a8ab5b65b..92fe1d522878 100644 --- a/core/hdd/src/wlan_hdd_softap_tx_rx.c +++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, 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 @@ -910,6 +910,13 @@ QDF_STATUS hdd_softap_rx_packet_cbk(void *context, qdf_nbuf_t rxBuf) hdd_dhcp_indication(pAdapter, staid, skb, QDF_RX); + if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(skb) && + qdf_mem_cmp(qdf_nbuf_data(skb) + + QDF_NBUF_DEST_MAC_OFFSET, + pAdapter->macAddressCurrent.bytes, + QDF_MAC_ADDR_SIZE))) + return QDF_STATUS_E_FAILURE; + hdd_event_eapol_log(skb, QDF_RX); qdf_dp_trace_log_pkt(pAdapter->sessionId, skb, QDF_RX); DPTRACE(qdf_dp_trace(skb, -- cgit v1.2.3 From 38629817a9a665ad4209e67b0193d102a08efdfd Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Tue, 23 Feb 2021 16:39:00 +0530 Subject: qcacld-3.0: Do not intrabss fwd EAPOL frames in IPA exc path Do not intrabss forward EAPOL frames received in IPA exception path. Change-Id: I0be68ec2c186a7b64d4d2f1c3de7dbb20e49d860 CRs-Fixed: 2860225 --- core/hdd/src/wlan_hdd_ipa.c | 52 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 05978a3acba8..5c7bb80ced3d 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -5778,6 +5778,40 @@ static enum hdd_ipa_forward_type hdd_ipa_intrabss_forward( return ret; } +/** + * wlan_ipa_eapol_intrabss_fwd_check() - Check if eapol pkt intrabss fwd is + * allowed or not + * @nbuf: network buffer + * @vdev_id: vdev id + * + * Return: true if intrabss fwd is allowed for eapol else false + */ +static bool +wlan_ipa_eapol_intrabss_fwd_check(qdf_nbuf_t nbuf, uint8_t vdev_id) +{ + ol_txrx_vdev_handle vdev; + uint8_t *vdev_mac_addr; + + vdev = ol_txrx_get_vdev_from_vdev_id(vdev_id); + + if (!vdev) { + HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, + "txrx vdev is NULL for vdev_id = %d", vdev_id); + return false; + } + + vdev_mac_addr = ol_txrx_get_vdev_mac_addr(vdev); + + 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; +} + /** * __hdd_ipa_w2i_cb() - WLAN to IPA callback handler * @priv: pointer to private data registered with IPA (we register a @@ -5888,9 +5922,23 @@ static void __hdd_ipa_w2i_cb(void *priv, enum ipa_dp_evt_type evt, QDF_MAC_ADDR_SIZE); } - if (qdf_nbuf_is_ipv4_eapol_pkt(skb) || - qdf_nbuf_is_ipv4_wapi_pkt(skb)) + if (qdf_nbuf_is_ipv4_eapol_pkt(skb)) { is_eapol_wapi = true; + if (iface_context->adapter->device_mode == + QDF_SAP_MODE && + !wlan_ipa_eapol_intrabss_fwd_check(skb, + iface_context->adapter->sessionId)) { + HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, + "EAPOL intrabss fwd drop DA: %pM", + qdf_nbuf_data(skb) + + QDF_NBUF_DEST_MAC_OFFSET); + hdd_ipa->ipa_rx_internal_drop_count++; + kfree_skb(skb); + return; + } + } else if (qdf_nbuf_is_ipv4_wapi_pkt(skb)) { + is_eapol_wapi = true; + } peer = ol_txrx_find_peer_by_addr(pdev, peer_mac_addr.bytes, &sta_idx); -- cgit v1.2.3 From 98990fcc29a6feec029d5b5485f7c28b7ff80944 Mon Sep 17 00:00:00 2001 From: Karthik Kantamneni Date: Fri, 22 Jan 2021 11:24:05 +0530 Subject: qcacld-3.0: Fix MIC verification in helium family. Currently MIC verification is not proper for fragmented packets, fix MIC verification for helium family. Change-Id: Iac95c579287bafedf6521b38f2c628fd08cca72d CRs-Fixed: 2869483 --- core/dp/txrx/ol_rx_defrag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_rx_defrag.c b/core/dp/txrx/ol_rx_defrag.c index e066ab5498e2..16ba405218f8 100644 --- a/core/dp/txrx/ol_rx_defrag.c +++ b/core/dp/txrx/ol_rx_defrag.c @@ -968,7 +968,7 @@ ol_rx_frag_tkip_demic(ol_txrx_pdev_handle pdev, const uint8_t *key, ol_rx_defrag_copydata(msdu, pktlen - f_tkip.ic_miclen + rx_desc_len, f_tkip.ic_miclen, (caddr_t) mic0); - if (!qdf_mem_cmp(mic, mic0, f_tkip.ic_miclen)) + if (qdf_mem_cmp(mic, mic0, f_tkip.ic_miclen)) return OL_RX_DEFRAG_ERR; qdf_nbuf_trim_tail(msdu, f_tkip.ic_miclen); -- cgit v1.2.3 From e0dbdc7635cee6f8fdaf118237446bc73ad9f75c Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Sat, 27 Feb 2021 12:19:09 +0530 Subject: qcacld-3.0: Do not intrabss forward fragmented EAPOL frames. Do not intrabss forward fragmented EAPOL frames that have DA different from the SAP vdev mac addr. Change-Id: I4145227c9b02fe8cec86ef4ffc3bc2025f906923 CRs-Fixed: 2888467 --- core/dp/txrx/ol_rx_fwd.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_rx_fwd.c b/core/dp/txrx/ol_rx_fwd.c index ebc15b7206d9..db211fea6902 100644 --- a/core/dp/txrx/ol_rx_fwd.c +++ b/core/dp/txrx/ol_rx_fwd.c @@ -1,5 +1,8 @@ /* - * Copyright (c) 2011, 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2014-2017, 2021 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -204,6 +207,20 @@ ol_rx_fwd_check(struct ol_txrx_vdev_t *vdev, continue; } + if (vdev->opmode == wlan_op_mode_ap && + qdf_nbuf_is_ipv4_eapol_pkt(msdu) && + qdf_mem_cmp(qdf_nbuf_data(msdu) + + QDF_NBUF_DEST_MAC_OFFSET, + vdev->mac_addr.raw, + QDF_MAC_ADDR_SIZE)) { + TXRX_STATS_MSDU_LIST_INCR( + pdev, tx.dropped.host_reject, msdu); + qdf_nbuf_set_next(msdu, NULL); + qdf_nbuf_tx_free(msdu, QDF_NBUF_PKT_ERROR); + msdu = msdu_list; + continue; + } + /* * This MSDU needs to be forwarded to the tx path. * Check whether it also needs to be sent to the OS -- cgit v1.2.3 From e584b75906c991d38255a76ceaf2052cedb43bf0 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Mon, 8 Mar 2021 19:52:33 +0530 Subject: qcacld-3.0: Do not intrabss fwd frag EAPOL frames in HL Do not intrabss forward fragmented EAPOL frames that have DA different from the SAP vdev mac addr when high latency is enabled. Change-Id: Idb6e6c001f4dae51c2181e70ab9adbbb964f0ee3 CRs-Fixed: 2942096 --- core/dp/txrx/ol_rx_fwd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/dp/txrx/ol_rx_fwd.c b/core/dp/txrx/ol_rx_fwd.c index db211fea6902..5d2333c3c611 100644 --- a/core/dp/txrx/ol_rx_fwd.c +++ b/core/dp/txrx/ol_rx_fwd.c @@ -153,6 +153,7 @@ ol_rx_fwd_check(struct ol_txrx_vdev_t *vdev, while (msdu) { struct ol_txrx_vdev_t *tx_vdev; void *rx_desc; + uint16_t off = 0; /* * Remember the next list elem, because our processing * may cause the MSDU to get linked into a different list. @@ -207,8 +208,14 @@ ol_rx_fwd_check(struct ol_txrx_vdev_t *vdev, continue; } + if (pdev->cfg.is_high_latency) + off = htt_rx_msdu_rx_desc_size_hl( + pdev->htt_pdev, + rx_desc); + if (vdev->opmode == wlan_op_mode_ap && - qdf_nbuf_is_ipv4_eapol_pkt(msdu) && + __qdf_nbuf_data_is_ipv4_eapol_pkt( + qdf_nbuf_data(msdu) + off) && qdf_mem_cmp(qdf_nbuf_data(msdu) + QDF_NBUF_DEST_MAC_OFFSET, vdev->mac_addr.raw, -- cgit v1.2.3 From c2e2adf298499edea91a72c0912a3285ac07c4cc Mon Sep 17 00:00:00 2001 From: Jyoti Kumari Date: Tue, 2 Mar 2021 17:30:00 +0530 Subject: qcacld-3.0: wma_send_peer_assoc() sets incorrect peer state wma_send_peer_assoc() calls wma_unified_peer_state_update() which always sets the peer state as AUTH irrespective of peer state. Remove wma_unified_peer_state_update() from wma_send_peer_assoc() to handle peer state. Change-Id: I4a887acbc8018653c34b927636cce7cc05323838 CRs-Fixed: 2888808 --- core/wma/src/wma_mgmt.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 0307894ac535..1af38e0ae056 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -918,45 +918,6 @@ static inline uint8_t wma_parse_mpdudensity(uint8_t mpdudensity) return 0; } -#if defined(CONFIG_HL_SUPPORT) && defined(FEATURE_WLAN_TDLS) - -/** - * wma_unified_peer_state_update() - update peer state - * @pdev: pdev handle - * @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( - struct ol_txrx_pdev_t *pdev, - uint8_t *sta_mac, - uint8_t *bss_addr, - uint8_t sta_type) -{ - if (STA_ENTRY_TDLS_PEER == sta_type) - ol_txrx_peer_state_update(pdev, sta_mac, - OL_TXRX_PEER_STATE_AUTH); - else - ol_txrx_peer_state_update(pdev, bss_addr, - OL_TXRX_PEER_STATE_AUTH); -} -#else - -static inline void -wma_unified_peer_state_update( - struct ol_txrx_pdev_t *pdev, - uint8_t *sta_mac, - uint8_t *bss_addr, - uint8_t sta_type) -{ - ol_txrx_peer_state_update(pdev, bss_addr, OL_TXRX_PEER_STATE_AUTH); -} -#endif - #define CFG_CTRL_MASK 0xFF00 #define CFG_DATA_MASK 0x00FF @@ -1247,9 +1208,6 @@ QDF_STATUS wma_send_peer_assoc(tp_wma_handle wma, if (params->wpa_rsn >> 1) cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY; - wma_unified_peer_state_update(pdev, 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, -- cgit v1.2.3 From 686def1e072d577c573182e43e50391ed1830cb5 Mon Sep 17 00:00:00 2001 From: abhinav kumar Date: Fri, 4 Jun 2021 19:45:08 +0530 Subject: qcacld-3.0: Possible buffer overflow issue in wma Possible bufer overflow risk in function wmi_unified_bcn_tmpl_send. Validate the beacon template length against WMI_BEACON_TX_BUFFER_SIZE length to avoid overflow. Change-Id: I98665de677f314f30a57991f48191f847718740c CRs-Fixed: 2960714 --- core/wma/src/wma_mgmt.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 1af38e0ae056..19941f0bd767 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-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 @@ -2329,8 +2329,22 @@ static QDF_STATUS wma_unified_bcn_tmpl_send(tp_wma_handle wma, tmpl_len = *(uint32_t *) &bcn_info->beacon[0]; else tmpl_len = bcn_info->beaconLength; - if (p2p_ie_len) + + if (tmpl_len > WMI_BEACON_TX_BUFFER_SIZE) { + WMA_LOGE("tmpl_len: %d > %d. Invalid tmpl len", tmpl_len, + WMI_BEACON_TX_BUFFER_SIZE); + return -EINVAL; + } + + if (p2p_ie_len) { + if (tmpl_len <= p2p_ie_len) { + WMA_LOGE("tmpl_len %d <= p2p_ie_len %d, Invalid", + tmpl_len, p2p_ie_len); + return -EINVAL; + } tmpl_len -= (uint32_t) p2p_ie_len; + } + frm = bcn_info->beacon + bytes_to_strip; tmpl_len_aligned = roundup(tmpl_len, sizeof(A_UINT32)); /* -- cgit v1.2.3 From a00610418b37ca256ace4e6394f56588e3121638 Mon Sep 17 00:00:00 2001 From: Deeksha Gupta Date: Wed, 29 Sep 2021 13:38:44 +0530 Subject: qcacld-3.0: Fix possible OOB in unpack_tlv_core Currently in unpack_tlv_core(), nBufRemaining is validated after calling framesntohs API. Since, framesntohs() copies pIn address to pOut address with length = 2 bytes as below. DOT11F_MEMCPY(pCtx, (uint16_t *)pOut, pIn, 2); which could cause OOB issue if pIn contains less than 2 bytes. Fix is to validate the nBufRemaining size before calling framesntohs(). Change-Id: I3ead03ec948282a410ddba5b01f82ca31d3d9199 CRs-Fixed: 3042282 --- core/mac/src/include/dot11f.h | 4 ++-- core/mac/src/sys/legacy/src/utils/src/dot11f.c | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/mac/src/include/dot11f.h b/core/mac/src/include/dot11f.h index 8c16f417604e..1a603f547d7f 100644 --- a/core/mac/src/include/dot11f.h +++ b/core/mac/src/include/dot11f.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -26,7 +26,7 @@ * * * This file was automatically generated by 'framesc' - * Mon Mar 25 14:48:07 2019 from the following file(s): + * Wed Sep 29 13:23:21 2021 from the following file(s): * * dot11f.frms * diff --git a/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/core/mac/src/sys/legacy/src/utils/src/dot11f.c index 391d1b8801eb..8325550d3460 100644 --- a/core/mac/src/sys/legacy/src/utils/src/dot11f.c +++ b/core/mac/src/sys/legacy/src/utils/src/dot11f.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -24,7 +24,7 @@ * * * This file was automatically generated by 'framesc' - * Mon Mar 25 14:48:07 2019 from the following file(s): + * Wed Sep 29 13:23:21 2021 from the following file(s): * * dot11f.frms * @@ -13659,25 +13659,30 @@ static uint32_t unpack_tlv_core(tpAniSirGlobal pCtx, } /* & length, */ if (pTlv->sLen == 2) { - framesntohs(pCtx, &len, pBufRemaining, pTlv->fMsb); if (2 > nBufRemaining) { FRAMES_LOG0(pCtx, FRLOGE, FRFL("This frame reports " "fewer two byte(s) remaining.\n")); status |= DOT11F_INCOMPLETE_TLV; FRAMES_DBG_BREAK(); goto MandatoryCheck; - } - pBufRemaining += 2; - nBufRemaining -= 2; + } + framesntohs(pCtx, &len, pBufRemaining, pTlv->fMsb); + pBufRemaining += 2; + nBufRemaining -= 2; } else { len = *pBufRemaining; pBufRemaining += 1; nBufRemaining -= 1; } } else { + if (TLVs[0].sType > nBufRemaining) { + FRAMES_LOG0(pCtx, FRLOGE, FRFL("This frame reports " + "fewer LVs[0].sType byte(s) remaining.\n")); + status |= DOT11F_INCOMPLETE_TLV; + goto MandatoryCheck; + } pBufRemaining += TLVs[0].sType; nBufRemaining -= TLVs[0].sType; - framesntohs(pCtx, &len, pBufRemaining, (TLVs[0].sType == 2)); if (2 > nBufRemaining) { FRAMES_LOG0(pCtx, FRLOGE, FRFL("This frame reports " "fewer two byte(s) remaining.\n")); @@ -13685,6 +13690,7 @@ static uint32_t unpack_tlv_core(tpAniSirGlobal pCtx, FRAMES_DBG_BREAK(); goto MandatoryCheck; } + framesntohs(pCtx, &len, pBufRemaining, (TLVs[0].sType == 2)); pBufRemaining += 2; nBufRemaining -= 2; } -- cgit v1.2.3 From b88e05e1321b1c67585d23de006d6dfa403db239 Mon Sep 17 00:00:00 2001 From: Gururaj Pandurangi Date: Thu, 14 Oct 2021 18:54:56 -0700 Subject: qcacld-3.0: Avoid OOB read in sch_get_csa_ecsa_count_offset Avoid OOB read in sch_get_csa_ecsa_count_offset API by adding check for ie_len before subtracting element ID len from it. Change-Id: Id86e69b2c5abc37a4f33125dc5fd0bd1d92f64a7 CRs-Fixed: 3049251 --- core/mac/src/pe/sch/sch_beacon_gen.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c index 511b07cf699f..e037e45c9faa 100644 --- a/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -156,7 +156,7 @@ sch_append_addn_ie(tpAniSirGlobal mac_ctx, tpPESession session, /** * sch_get_csa_ecsa_count_offset() - get the offset of Switch count field - * @ie: pointer to the beggining of IEs in the beacon frame buffer + * @ie: pointer to the beginning of IEs in the beacon frame buffer * @ie_len: length of the IEs in the buffer * @csa_count_offset: pointer to the csa_count_offset variable in the caller * @ecsa_count_offset: pointer to the ecsa_count_offset variable in the caller @@ -195,6 +195,9 @@ static void sch_get_csa_ecsa_count_offset(uint8_t *ie, uint32_t ie_len, *ecsa_count_offset = offset + SCH_ECSA_SWITCH_COUNT_OFFSET; + if (ie_len < elem_len) + return; + ie_len -= elem_len; offset += elem_len; ptr += (elem_len + 2); -- cgit v1.2.3 From b348a1d2e87cb54266660d53d590fa89c9747368 Mon Sep 17 00:00:00 2001 From: Gururaj Pandurangi Date: Mon, 25 Oct 2021 17:19:51 -0700 Subject: qcacld-3.0: Avoid OOB read in dot11f_unpack_assoc_response Avoid OOB read in dot11f_unpack_assoc_response API. Add check for when nBuf == len to read another byte of pBufRemaining. Change-Id: Iccdb0b268d16f4169b8b701ade6085d47897f785 CRs-Fixed: 3042293 --- core/mac/src/sys/legacy/src/utils/src/dot11f.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/core/mac/src/sys/legacy/src/utils/src/dot11f.c index 8325550d3460..55781cf9a8e0 100644 --- a/core/mac/src/sys/legacy/src/utils/src/dot11f.c +++ b/core/mac/src/sys/legacy/src/utils/src/dot11f.c @@ -335,7 +335,7 @@ static uint32_t get_container_ies_len(tpAniSirGlobal pCtx, len += *(pBufRemaining+1); pBufRemaining += len + 2; len += 2; - while (len < nBuf) { + while (len + 1 < nBuf) { pIe = find_ie_defn(pCtx, pBufRemaining, nBuf - len, IEs); if (NULL == pIe) break; -- cgit v1.2.3 From ab63644b28389f4fc5bfb8fe61e37f455f712964 Mon Sep 17 00:00:00 2001 From: Bapiraju Alla Date: Thu, 11 Nov 2021 13:05:48 +0530 Subject: qcacld-3.0: Validate NDP app info length before accessing NDP app info Currently, NDP app info length is not being validated with max NDP app info length. This may result in buffer oveflow wile accessing NDP app info received from the firmware. To address this, validate NDP app info length before accessing NDP app info Change-Id: Ifddf1afca7ecf2585e8eb450864d9ba127238f6e CRs-Fixed: 3073345 --- core/hdd/src/wlan_hdd_nan_datapath.h | 2 +- core/wma/inc/wma.h | 2 ++ core/wma/src/wma_nan_datapath.c | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/hdd/src/wlan_hdd_nan_datapath.h b/core/hdd/src/wlan_hdd_nan_datapath.h index 72516e3f80e2..5b1353cf856b 100644 --- a/core/hdd/src/wlan_hdd_nan_datapath.h +++ b/core/hdd/src/wlan_hdd_nan_datapath.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -35,7 +36,6 @@ struct wireless_dev; #define NAN_SOCIAL_CHANNEL_5GHZ_LOWER_BAND 44 #define NAN_SOCIAL_CHANNEL_5GHZ_UPPER_BAND 149 -#define NDP_APP_INFO_LEN 255 #define NDP_PMK_LEN 32 #define NDP_SCID_BUF_LEN 256 #define NDP_NUM_INSTANCE_ID 255 diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 5728194c58d6..79f812017119 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -55,6 +56,7 @@ #define WMA_RESUME_TIMEOUT 6000 #define MAX_MEM_CHUNKS 32 #define NAN_CLUSTER_ID_BYTES 4 +#define NDP_APP_INFO_LEN 255 #define WMA_CRASH_INJECT_TIMEOUT 5000 diff --git a/core/wma/src/wma_nan_datapath.c b/core/wma/src/wma_nan_datapath.c index dff36acb30ee..6702ef10c3c8 100644 --- a/core/wma/src/wma_nan_datapath.c +++ b/core/wma/src/wma_nan_datapath.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 Qualcomm Innovation Center, Inc. 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 @@ -720,6 +721,11 @@ static int wma_ndp_confirm_event_handler(void *handle, uint8_t *event_info, WMA_LOGE(FL("malloc failed")); return QDF_STATUS_E_NOMEM; } + + if (ndp_confirm.ndp_info.ndp_app_info_len > NDP_APP_INFO_LEN) + ndp_confirm.ndp_info.ndp_app_info_len = + NDP_APP_INFO_LEN; + qdf_mem_copy(&ndp_confirm.ndp_info.ndp_app_info, event->ndp_app_info, ndp_confirm.ndp_info.ndp_app_info_len); -- cgit v1.2.3 From c858fbc8b8fadb26e09c0133d3dd360c8c84ef04 Mon Sep 17 00:00:00 2001 From: Jingxiang Ge Date: Thu, 2 Dec 2021 15:59:01 +0800 Subject: qcacld-3.0: Fix possible memory leak of tx_time_per_power_level It is possible tx_time_per_power_level is not freed in last event, and it is reused in __wma_unified_radio_tx_power_level_stats_event_handler, the buffer size may be different for each event by manually test. Fix is to check if memory is freed before malloc, if not null, free it before malloc. Change-Id: I51064734cf97b9ff0ecbbaf27f38d5a223c91d3b CRs-Fixed: 3057436 --- core/wma/src/wma_utils.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index af9459c262e0..60f157cbe7f6 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -1635,20 +1635,25 @@ static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle, return -EINVAL; } + if (rs_results->tx_time_per_power_level) { + qdf_mem_free(rs_results->tx_time_per_power_level); + rs_results->tx_time_per_power_level = NULL; + } + + rs_results->tx_time_per_power_level = + qdf_mem_malloc(sizeof(uint32_t) * + rs_results->total_num_tx_power_levels); if (!rs_results->tx_time_per_power_level) { - rs_results->tx_time_per_power_level = qdf_mem_malloc( - sizeof(uint32_t) * - rs_results->total_num_tx_power_levels); - if (!rs_results->tx_time_per_power_level) { - WMA_LOGA("%s: Mem alloc fail for tx power level stats", - __func__); - /* In error case, atleast send the radio stats without - * tx_power_level stats */ - rs_results->total_num_tx_power_levels = 0; - link_stats_results->nr_received++; - goto post_stats; - } + WMA_LOGA("%s: Mem alloc fail for tx power level stats", + __func__); + /* In error case, atleast send the radio stats without + * tx_power_level stats + */ + rs_results->total_num_tx_power_levels = 0; + link_stats_results->nr_received++; + goto post_stats; } + qdf_mem_copy(&rs_results->tx_time_per_power_level[ fixed_param->power_level_offset], tx_power_level_values, -- cgit v1.2.3