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
This commit is contained in:
Pragaspathi Thilagaraj 2018-07-31 19:08:19 +05:30 • committed by nshrivas
commit 210362a1c2
4 changed files with 29 additions and 2 deletions

View file

@ -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
------------------------------------------------------------------------*/

View file

@ -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:

View file

@ -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;
}

View file

@ -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;
}