Jelajahi Sumber

qcacld-3.0: Fix pmfSaQueryTimer timer leak

In case of PMF connection the sta_ds is memset to 0 in case of
SA query timeout whithout deleting pmfSaQueryTimer.
Also in lim_update_sta_ds pmfSaQueryTimer is
created without any check if its already created and thus may
lead to overwrite of the previous timer.

Thus destroy the pmfSaQueryTimer before memset sta_ds to 0 and
before creating it in lim_update_sta_ds.

Also use peer deletion is in progress in lim_process_assoc_req_sta_ctx
to check if STA is in proper state and assoc can be handled.

Change-Id: I63a701c1bd4324c6fce62338df80d0911cc9b703
CRs-Fixed: 2606900
Abhishek Singh 5 tahun lalu
induk
melakukan
7a7799b04a

+ 82 - 60
core/mac/src/pe/lim/lim_process_assoc_req_frame.c

@@ -1197,6 +1197,36 @@ static bool lim_process_assoc_req_no_sta_ctx(struct mac_context *mac_ctx,
 	return true;
 }
 
+#ifdef WLAN_DEBUG
+static inline void
+lim_update_assoc_drop_count(struct mac_context *mac_ctx, uint8_t sub_type)
+{
+	if (sub_type == LIM_ASSOC)
+		mac_ctx->lim.gLimNumAssocReqDropInvldState++;
+	else
+		mac_ctx->lim.gLimNumReassocReqDropInvldState++;
+}
+#else
+static inline void
+lim_update_assoc_drop_count(struct mac_context *mac_ctx, uint8_t sub_type) {}
+#endif
+
+#ifdef WLAN_FEATURE_11W
+static inline void
+lim_delete_pmf_query_timer(tpDphHashNode sta_ds)
+{
+	if (!sta_ds->rmfEnabled)
+		return;
+
+	if (tx_timer_running(&sta_ds->pmfSaQueryTimer))
+		tx_timer_deactivate(&sta_ds->pmfSaQueryTimer);
+	tx_timer_delete(&sta_ds->pmfSaQueryTimer);
+}
+#else
+static inline void
+lim_delete_pmf_query_timer(tpDphHashNode sta_ds) {}
+#endif
+
 /**
  * lim_process_assoc_req_sta_ctx() - process assoc req for sta context present
  * @mac_ctx: pointer to Global MAC structure
@@ -1221,29 +1251,16 @@ static bool lim_process_assoc_req_sta_ctx(struct mac_context *mac_ctx,
 				tpDphHashNode sta_ds, uint16_t peer_idx,
 				tAniAuthType *auth_type, uint8_t *update_ctx)
 {
-	/* STA context does exist for this STA */
-	if (sta_ds->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) {
-		/*
-		 * Requesting STA is in some 'transient' state? Ignore the
-		 * Re/Assoc Req frame by incrementing debug counter & logging
-		 * error.
-		 */
-		if (sub_type == LIM_ASSOC) {
-#ifdef WLAN_DEBUG
-			mac_ctx->lim.gLimNumAssocReqDropInvldState++;
-#endif
-			pe_debug("received Assoc req in state: %X from",
-				sta_ds->mlmStaContext.mlmState);
-		} else {
-#ifdef WLAN_DEBUG
-			mac_ctx->lim.gLimNumReassocReqDropInvldState++;
-#endif
-			pe_debug("received ReAssoc req in state: %X from",
-				sta_ds->mlmStaContext.mlmState);
-		}
-		lim_print_mac_addr(mac_ctx, hdr->sa, LOGD);
-		lim_print_mlm_state(mac_ctx, LOGD,
-			(tLimMlmStates) sta_ds->mlmStaContext.mlmState);
+	/* Drop if STA deletion is in progress or not in established state */
+	if (sta_ds->sta_deletion_in_progress ||
+	    (sta_ds->mlmStaContext.mlmState !=
+	     eLIM_MLM_LINK_ESTABLISHED_STATE)) {
+		pe_debug("%s: peer:%pM in mlmState %d (%s) and sta del %d",
+			 (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc",
+			 sta_ds->staAddr, sta_ds->mlmStaContext.mlmState,
+			 lim_mlm_state_str(sta_ds->mlmStaContext.mlmState),
+			 sta_ds->sta_deletion_in_progress);
+		lim_update_assoc_drop_count(mac_ctx, sub_type);
 		return false;
 	}
 
@@ -1313,31 +1330,34 @@ static bool lim_process_assoc_req_sta_ctx(struct mac_context *mac_ctx,
 		pe_err("Received Assoc req in state: %X STAid: %d",
 			sta_ds->mlmStaContext.mlmState, peer_idx);
 		return false;
+	}
+
+	/*
+	 * STA sent Re/association Request frame while already in
+	 * 'associated' state. Update STA capabilities and send
+	 * Association response frame with same AID
+	 */
+	pe_debug("Rcvd Assoc req from STA already connected");
+	sta_ds->mlmStaContext.capabilityInfo =
+		assoc_req->capabilityInfo;
+	if (sta_pre_auth_ctx && (sta_pre_auth_ctx->mlmState ==
+		eLIM_MLM_AUTHENTICATED_STATE)) {
+		/* STA has triggered pre-auth again */
+		*auth_type = sta_pre_auth_ctx->authType;
+		lim_delete_pre_auth_node(mac_ctx, hdr->sa);
 	} else {
-		/*
-		 * STA sent Re/association Request frame while already in
-		 * 'associated' state. Update STA capabilities and send
-		 * Association response frame with same AID
-		 */
-		pe_debug("Rcvd Assoc req from STA already connected");
-		sta_ds->mlmStaContext.capabilityInfo =
-			assoc_req->capabilityInfo;
-		if (sta_pre_auth_ctx && (sta_pre_auth_ctx->mlmState ==
-			eLIM_MLM_AUTHENTICATED_STATE)) {
-			/* STA has triggered pre-auth again */
-			*auth_type = sta_pre_auth_ctx->authType;
-			lim_delete_pre_auth_node(mac_ctx, hdr->sa);
-		} else {
-			*auth_type = sta_ds->mlmStaContext.authType;
-		}
+		*auth_type = sta_ds->mlmStaContext.authType;
+	}
 
-		*update_ctx = true;
-		if (dph_init_sta_state(mac_ctx, hdr->sa, peer_idx,
-				       &session->dph.dphHashTable) == NULL) {
-			pe_err("could not Init STAid: %d", peer_idx);
-			return false;
-		}
+	*update_ctx = true;
+	/* Free pmf query timer before resetting the sta_ds */
+	lim_delete_pmf_query_timer(sta_ds);
+	if (dph_init_sta_state(mac_ctx, hdr->sa, peer_idx,
+			       &session->dph.dphHashTable) == NULL) {
+		pe_err("could not Init STAid: %d", peer_idx);
+		return false;
 	}
+
 	return true;
 }
 
@@ -1760,22 +1780,24 @@ static bool lim_update_sta_ds(struct mac_context *mac_ctx, tpSirMacMgmtHdr hdr,
 	if (cfg_min(CFG_PMF_SA_QUERY_RETRY_INTERVAL) > retry_interval) {
 		retry_interval = cfg_default(CFG_PMF_SA_QUERY_RETRY_INTERVAL);
 	}
-	if (sta_ds->rmfEnabled &&
-		tx_timer_create(mac_ctx, &sta_ds->pmfSaQueryTimer,
-			"PMF SA Query timer", lim_pmf_sa_query_timer_handler,
-			timer_id.value,
-			SYS_MS_TO_TICKS((retry_interval * 1024) / 1000),
-			0, TX_NO_ACTIVATE) != TX_SUCCESS) {
-		pe_err("could not create PMF SA Query timer");
-		lim_reject_association(mac_ctx, hdr->sa, sub_type,
-			true, auth_type, peer_idx, false,
-			eSIR_MAC_UNSPEC_FAILURE_STATUS,
-			session);
-		return false;
+	if (sta_ds->rmfEnabled) {
+		/* Try to delete it before, creating.*/
+		lim_delete_pmf_query_timer(sta_ds);
+		if (tx_timer_create(mac_ctx, &sta_ds->pmfSaQueryTimer,
+		    "PMF SA Query timer", lim_pmf_sa_query_timer_handler,
+		    timer_id.value,
+		    SYS_MS_TO_TICKS((retry_interval * 1024) / 1000),
+		    0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+			pe_err("could not create PMF SA Query timer");
+			lim_reject_association(mac_ctx, hdr->sa, sub_type,
+					       true, auth_type, peer_idx, false,
+					       eSIR_MAC_UNSPEC_FAILURE_STATUS,
+					       session);
+			return false;
+		}
+		pe_debug("Created pmf timer assoc-id:%d sta mac" QDF_MAC_ADDR_STR,
+			 sta_ds->assocId, QDF_MAC_ADDR_ARRAY(sta_ds->staAddr));
 	}
-	if (sta_ds->rmfEnabled)
-	    pe_debug("Created pmf timer assoc-id:%d sta mac" QDF_MAC_ADDR_STR,
-		     sta_ds->assocId, QDF_MAC_ADDR_ARRAY(sta_ds->staAddr));
 #endif
 
 	if (assoc_req->ExtCap.present) {

+ 3 - 1
core/mac/src/sys/legacy/src/platform/src/sys_wrapper.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -421,6 +421,8 @@ uint32_t tx_timer_delete(TX_TIMER *timer_ptr)
 	}
 
 	qdf_mc_timer_destroy(&timer_ptr->qdf_timer);
+	timer_ptr->tmrSignature = 0;
+
 	return TX_SUCCESS;
 } /*** tx_timer_delete() ***/