From c0b2e333be7876d452e98e48bf4019e7f7411458 Mon Sep 17 00:00:00 2001 From: Liangwei Dong Date: Thu, 16 Nov 2017 06:04:46 -0500 Subject: [PATCH] qcacld-3.0: Fix memory double free The lim_deauth_tx_complete_cnf and lim_disassoc_tx_complete_cnf are called in data path softirq thread. The lim_process_deauth_ack_timeout are called in pe context in scheduler thread. Both thread will call lim_send_deauth_cnf to free lim.limDisassocDeauthCnfReq.pMlmDeauthReq. Fix by posting WMA_DISASSOC_TX_COMP and WMA_DEAUTH_TX_COMP to scheduler thread. Let lim_disassoc_tx_complete_cnf and lim_deauth_tx_complete_cnf run in correct PE thread context. Change-Id: I83a4ad741da46aa907603ae587c74042730b67bd CRs-Fixed: 2143794 --- .../src/pe/lim/lim_process_message_queue.c | 6 +- .../src/pe/lim/lim_send_management_frames.c | 173 +++++++++++------- core/mac/src/pe/lim/lim_types.h | 4 - 3 files changed, 111 insertions(+), 72 deletions(-) diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 11e54b1ed7a8..fcd2c7c3e4b8 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1766,10 +1766,12 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx, msg->bodyptr = NULL; break; case WMA_DISASSOC_TX_COMP: - lim_disassoc_tx_complete_cnf(mac_ctx, NULL, msg->bodyval, NULL); + lim_disassoc_tx_complete_cnf(mac_ctx, msg->bodyval, + msg->bodyptr); break; case WMA_DEAUTH_TX_COMP: - lim_deauth_tx_complete_cnf(mac_ctx, NULL, msg->bodyval, NULL); + lim_deauth_tx_complete_cnf(mac_ctx, msg->bodyval, + msg->bodyptr); break; #ifdef FEATURE_AP_MCC_CH_AVOIDANCE case WMA_UPDATE_Q2Q_IE_IND: diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 90da61092a88..1c7ac5b0512f 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -2453,90 +2453,91 @@ alloc_packet: return; } -QDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac) +QDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal mac_ctx) { uint16_t aid; - tpDphHashNode pStaDs; - tLimMlmDeauthReq *pMlmDeauthReq; - tLimMlmDeauthCnf mlmDeauthCnf; - tpPESession psessionEntry; + tpDphHashNode sta_ds; + tLimMlmDeauthReq *deauth_req; + tLimMlmDeauthCnf deauth_cnf; + tpPESession session_entry; - pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; - if (pMlmDeauthReq) { - if (tx_timer_running(&pMac->lim.limTimers.gLimDeauthAckTimer)) { - lim_deactivate_and_change_timer(pMac, + deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; + if (deauth_req) { + if (tx_timer_running( + &mac_ctx->lim.limTimers.gLimDeauthAckTimer)) + lim_deactivate_and_change_timer(mac_ctx, eLIM_DEAUTH_ACK_TIMER); - } - psessionEntry = pe_find_session_by_session_id(pMac, - pMlmDeauthReq->sessionId); - if (psessionEntry == NULL) { + session_entry = pe_find_session_by_session_id(mac_ctx, + deauth_req->sessionId); + if (session_entry == NULL) { pe_err("session does not exist for given sessionId"); - mlmDeauthCnf.resultCode = + deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } - pStaDs = - dph_lookup_hash_entry(pMac, - pMlmDeauthReq->peer_macaddr.bytes, + sta_ds = + dph_lookup_hash_entry(mac_ctx, + deauth_req->peer_macaddr.bytes, &aid, - &psessionEntry->dph.dphHashTable); - if (pStaDs == NULL) { - mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; + &session_entry->dph.dphHashTable); + if (sta_ds == NULL) { + deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } /* / Receive path cleanup with dummy packet */ - lim_ft_cleanup_pre_auth_info(pMac, psessionEntry); - lim_cleanup_rx_path(pMac, pStaDs, psessionEntry); - if ((psessionEntry->limSystemRole == eLIM_STA_ROLE) && - ( + lim_ft_cleanup_pre_auth_info(mac_ctx, session_entry); + lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry); + if ((session_entry->limSystemRole == eLIM_STA_ROLE) && + ( #ifdef FEATURE_WLAN_ESE - (psessionEntry->isESEconnection) || + (session_entry->isESEconnection) || #endif - (psessionEntry->isFastRoamIniFeatureEnabled) || - (psessionEntry->is11Rconnection))) { + (session_entry->isFastRoamIniFeatureEnabled) || + (session_entry->is11Rconnection))) { pe_debug("FT Preauth (%pK,%d) Deauth rc %d src = %d", - psessionEntry, - psessionEntry->peSessionId, - pMlmDeauthReq->reasonCode, - pMlmDeauthReq->deauthTrigger); - lim_ft_cleanup(pMac, psessionEntry); + session_entry, + session_entry->peSessionId, + deauth_req->reasonCode, + deauth_req->deauthTrigger); + lim_ft_cleanup(mac_ctx, session_entry); } else { pe_debug("No FT Preauth Session Cleanup in role %d" #ifdef FEATURE_WLAN_ESE - " isESE %d" + " isESE %d" #endif - " isLFR %d" - " is11r %d, Deauth reason %d Trigger = %d", - psessionEntry->limSystemRole, + " isLFR %d" + " is11r %d, Deauth reason %d Trigger = %d", + session_entry->limSystemRole, #ifdef FEATURE_WLAN_ESE - psessionEntry->isESEconnection, + session_entry->isESEconnection, #endif - psessionEntry->isFastRoamIniFeatureEnabled, - psessionEntry->is11Rconnection, - pMlmDeauthReq->reasonCode, - pMlmDeauthReq->deauthTrigger); + session_entry->isFastRoamIniFeatureEnabled, + session_entry->is11Rconnection, + deauth_req->reasonCode, + deauth_req->deauthTrigger); } /* Free up buffer allocated for mlmDeauthReq */ - qdf_mem_free(pMlmDeauthReq); - pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL; + qdf_mem_free(deauth_req); + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL; } return QDF_STATUS_SUCCESS; end: - qdf_copy_macaddr(&mlmDeauthCnf.peer_macaddr, - &pMlmDeauthReq->peer_macaddr); - mlmDeauthCnf.deauthTrigger = pMlmDeauthReq->deauthTrigger; - mlmDeauthCnf.aid = pMlmDeauthReq->aid; - mlmDeauthCnf.sessionId = pMlmDeauthReq->sessionId; + qdf_copy_macaddr(&deauth_cnf.peer_macaddr, + &deauth_req->peer_macaddr); + deauth_cnf.deauthTrigger = deauth_req->deauthTrigger; + deauth_cnf.aid = deauth_req->aid; + deauth_cnf.sessionId = deauth_req->sessionId; /* Free up buffer allocated */ /* for mlmDeauthReq */ - qdf_mem_free(pMlmDeauthReq); + qdf_mem_free(deauth_req); + mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL; - lim_post_sme_message(pMac, - LIM_MLM_DEAUTH_CNF, (uint32_t *) &mlmDeauthCnf); + lim_post_sme_message(mac_ctx, + LIM_MLM_DEAUTH_CNF, (uint32_t *) &deauth_cnf); return QDF_STATUS_SUCCESS; } @@ -2592,10 +2593,10 @@ QDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal mac_ctx) goto end; } if (LIM_IS_STA_ROLE(pe_session) && - (disassoc_req->reasonCode != - eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) { + (disassoc_req->reasonCode != + eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) { pe_debug("FT Preauth Session (%pK %d) Clean up", - pe_session, pe_session->peSessionId); + pe_session, pe_session->peSessionId); /* Delete FT session if there exists one */ lim_ft_cleanup_pre_auth_info(mac_ctx, pe_session); @@ -2629,33 +2630,73 @@ end: } QDF_STATUS lim_disassoc_tx_complete_cnf(void *context, - qdf_nbuf_t buf, - uint32_t txCompleteSuccess, + uint32_t tx_success, void *params) { - tpAniSirGlobal pMac = (tpAniSirGlobal)context; + tpAniSirGlobal max_ctx = (tpAniSirGlobal)context; - pe_debug("txCompleteSuccess: %d", txCompleteSuccess); + pe_debug("tx_success: %d", tx_success); + + return lim_send_disassoc_cnf(max_ctx); +} + +static QDF_STATUS lim_disassoc_tx_complete_cnf_handler(void *context, + qdf_nbuf_t buf, + uint32_t tx_success, + void *params) +{ + tpAniSirGlobal max_ctx = (tpAniSirGlobal)context; + QDF_STATUS status_code; + struct scheduler_msg msg = {0}; + + pe_debug("tx_success: %d", tx_success); if (buf) qdf_nbuf_free(buf); + msg.type = (uint16_t) WMA_DISASSOC_TX_COMP; + msg.bodyptr = params; + msg.bodyval = tx_success; - return lim_send_disassoc_cnf(pMac); + status_code = lim_post_msg_high_priority(max_ctx, &msg); + if (status_code != QDF_STATUS_SUCCESS) + pe_err("posting message: %X to LIM failed, reason: %d", + msg.type, status_code); + return status_code; } QDF_STATUS lim_deauth_tx_complete_cnf(void *context, - qdf_nbuf_t buf, - uint32_t txCompleteSuccess, + uint32_t tx_success, void *params) { - tpAniSirGlobal pMac = (tpAniSirGlobal)context; + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)context; - pe_debug("txCompleteSuccess: %d", txCompleteSuccess); + pe_debug("tx_success: %d", tx_success); + + return lim_send_deauth_cnf(mac_ctx); +} + +static QDF_STATUS lim_deauth_tx_complete_cnf_handler(void *context, + qdf_nbuf_t buf, + uint32_t tx_success, + void *params) +{ + tpAniSirGlobal mac_ctx = (tpAniSirGlobal)context; + QDF_STATUS status_code; + struct scheduler_msg msg = {0}; + + pe_debug("tx_success: %d", tx_success); if (buf) qdf_nbuf_free(buf); + msg.type = (uint16_t) WMA_DEAUTH_TX_COMP; + msg.bodyptr = params; + msg.bodyval = tx_success; - return lim_send_deauth_cnf(pMac); + status_code = lim_post_msg_high_priority(mac_ctx, &msg); + if (status_code != QDF_STATUS_SUCCESS) + pe_err("posting message: %X to LIM failed, reason: %d", + msg.type, status_code); + return status_code; } /** @@ -2784,7 +2825,7 @@ lim_send_disassoc_mgmt_frame(tpAniSirGlobal pMac, wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, lim_tx_complete, - pFrame, lim_disassoc_tx_complete_cnf, + pFrame, lim_disassoc_tx_complete_cnf_handler, txFlag, smeSessionId, false, 0, RATEID_DEFAULT); MTRACE(qdf_trace @@ -2960,7 +3001,7 @@ lim_send_deauth_mgmt_frame(tpAniSirGlobal pMac, wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes, TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7, lim_tx_complete, - pFrame, lim_deauth_tx_complete_cnf, + pFrame, lim_deauth_tx_complete_cnf_handler, txFlag, smeSessionId, false, 0, RATEID_DEFAULT); MTRACE(qdf_trace diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index b56fed29795b..6f28105811b9 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -898,7 +898,6 @@ QDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac); /** * lim_disassoc_tx_complete_cnf() - callback to indicate Tx completion * @context: pointer to mac structure - * @buf: buffer * @txCompleteSuccess: indicates tx success/failure * @params: tx completion params * @@ -907,14 +906,12 @@ QDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac); * return: success: QDF_STATUS_SUCCESS failure: QDF_STATUS_E_FAILURE */ QDF_STATUS lim_disassoc_tx_complete_cnf(void *context, - qdf_nbuf_t buf, uint32_t txCompleteSuccess, void *params); /** * lim_deauth_tx_complete_cnf() - callback to indicate Tx completion * @context: pointer to mac structure - * @buf: buffer * @txCompleteSuccess: indicates tx success/failure * @params: tx completion params * @@ -923,7 +920,6 @@ QDF_STATUS lim_disassoc_tx_complete_cnf(void *context, * return: success: QDF_STATUS_SUCCESS failure: QDF_STATUS_E_FAILURE */ QDF_STATUS lim_deauth_tx_complete_cnf(void *context, - qdf_nbuf_t buf, uint32_t txCompleteSuccess, void *params);