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
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 90da610..1c7ac5b 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 @@
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 @@
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 @@
}
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 @@
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 @@
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