From 210362a1c283134c6ad197365bd6c2cf6c27770f Mon Sep 17 00:00:00 2001 From: Pragaspathi Thilagaraj Date: Tue, 31 Jul 2018 19:08:19 +0530 Subject: [PATCH] qcacld-3.0: Fix memory corruption in pe_free_nested_messages When peer creation fails in wma_set_link_state, wma sends the WMA_SET_LINK_STATE_RSP msg to LIM and Lim frees the msg->bodyptr But there is a situation occurs where after this wma_peer_create fails, mc thread stop sys event also occurs where the mac_stop is invoked which calls the pe_free_msg -> pe_free_nested_messages In pe_free_nested_messages, if the msg type is WMA_SET_LINK_STATE_RSP, we free the msg->bodyptr->callbackArg. This callbackArg points to the PE session. Trying to free the PE session results in memory corruption. Just pass the session id as callback argument when the callback is lim_post_join_set_link_state_callback. Change-Id: I27f9127685ac7ef8d215b135f1625e8e2f225fc0 CRs-Fixed: 2287827 --- core/mac/src/pe/include/lim_session.h | 4 ++++ core/mac/src/pe/lim/lim_api.c | 2 ++ .../src/pe/lim/lim_process_mlm_req_messages.c | 24 +++++++++++++++++-- core/wma/src/wma_dev_if.c | 1 + 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index dcc4ffcc46a8..ff85e7d4c58c 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -559,6 +559,10 @@ typedef struct sPESession /* Added to Support BT-AMP */ #endif } tPESession, *tpPESession; +struct session_params { + uint16_t session_id; +}; + /*------------------------------------------------------------------------- Function declarations and documenation ------------------------------------------------------------------------*/ diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 6dbc21c5d048..4a2401ebbda2 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1007,6 +1007,7 @@ QDF_STATUS pe_start(tpAniSirGlobal pMac) void pe_stop(tpAniSirGlobal pMac) { lim_cleanup_mlm(pMac); + pe_debug(" PE STOP: Set LIM state to eLIM_MLM_OFFLINE_STATE"); SET_LIM_MLM_STATE(pMac, eLIM_MLM_OFFLINE_STATE); return; } @@ -1015,6 +1016,7 @@ static void pe_free_nested_messages(struct scheduler_msg *msg) { switch (msg->type) { case WMA_SET_LINK_STATE_RSP: + pe_debug("pe_free_nested_messages: WMA_SET_LINK_STATE_RSP"); qdf_mem_free(((tpLinkStateParams) msg->bodyptr)->callbackArg); break; default: diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index c421dc169110..32b68bb4b002 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -734,9 +734,20 @@ static void lim_post_join_set_link_state_callback(tpAniSirGlobal mac, void *callback_arg, bool status) { uint8_t chan_num, sec_chan_offset; - tpPESession session_entry = (tpPESession) callback_arg; + struct session_params *session_cb_param = + (struct session_params *)callback_arg; tLimMlmJoinCnf mlm_join_cnf; + tpPESession session_entry = pe_find_session_by_session_id(mac, + session_cb_param->session_id); + if (!session_entry) { + pe_err("sessionId:%d does not exist", + session_cb_param->session_id); + qdf_mem_free(session_cb_param); + return; + } + + qdf_mem_free(session_cb_param); pe_debug("Sessionid %d set link state(%d) cb status: %d", session_entry->peSessionId, session_entry->limMlmState, status); @@ -805,6 +816,7 @@ lim_process_mlm_post_join_suspend_link(tpAniSirGlobal mac_ctx, tLimMlmJoinCnf mlm_join_cnf; tpPESession session = (tpPESession) ctx; tSirLinkState lnk_state; + struct session_params *pe_session_param = NULL; if (QDF_STATUS_SUCCESS != status) { pe_err("Sessionid %d Suspend link(NOTIFY_BSS) failed. Still proceeding with join", @@ -820,11 +832,18 @@ lim_process_mlm_post_join_suspend_link(tpAniSirGlobal mac_ctx, pe_debug("[lim_process_mlm_join_req]: lnk_state: %d", lnk_state); + pe_session_param = qdf_mem_malloc(sizeof(struct session_params)); + if (pe_session_param) { + pe_session_param->session_id = session->peSessionId; + } else { + pe_err("insufficient memory"); + goto error; + } if (lim_set_link_state(mac_ctx, lnk_state, session->pLimMlmJoinReq->bssDescription.bssId, session->selfMacAddr, lim_post_join_set_link_state_callback, - session) != QDF_STATUS_SUCCESS) { + pe_session_param) != QDF_STATUS_SUCCESS) { pe_err("SessionId:%d lim_set_link_state to eSIR_LINK_PREASSOC_STATE Failed!!", session->peSessionId); lim_print_mac_addr(mac_ctx, @@ -833,6 +852,7 @@ lim_process_mlm_post_join_suspend_link(tpAniSirGlobal mac_ctx, session->limMlmState = eLIM_MLM_IDLE_STATE; MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId, session->limMlmState)); + qdf_mem_free(pe_session_param); goto error; } diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 80913901f2f8..7cf2cb88a5cd 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1843,6 +1843,7 @@ static void wma_cleanup_target_req_param(struct wma_target_req *tgt_req) tpLinkStateParams params = (tpLinkStateParams) tgt_req->user_data; qdf_mem_free(params->callbackArg); + params->callbackArg = NULL; qdf_mem_free(tgt_req->user_data); tgt_req->user_data = NULL; }