Browse Source

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
Pragaspathi Thilagaraj 6 years ago
parent
commit
210362a1c2

+ 4 - 0
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
    ------------------------------------------------------------------------*/

+ 2 - 0
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:

+ 22 - 2
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;
 	}
 

+ 1 - 0
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;
 	}