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
This commit is contained in:
Abhishek Singh
2020-01-21 10:30:28 +05:30
committed by nshrivas
parent 77aca6ed3c
commit 7a7799b04a
2 changed files with 87 additions and 63 deletions

View File

@@ -1197,6 +1197,36 @@ static bool lim_process_assoc_req_no_sta_ctx(struct mac_context *mac_ctx,
return true; 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 * lim_process_assoc_req_sta_ctx() - process assoc req for sta context present
* @mac_ctx: pointer to Global MAC structure * @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, tpDphHashNode sta_ds, uint16_t peer_idx,
tAniAuthType *auth_type, uint8_t *update_ctx) tAniAuthType *auth_type, uint8_t *update_ctx)
{ {
/* STA context does exist for this STA */ /* Drop if STA deletion is in progress or not in established state */
if (sta_ds->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) { if (sta_ds->sta_deletion_in_progress ||
/* (sta_ds->mlmStaContext.mlmState !=
* Requesting STA is in some 'transient' state? Ignore the eLIM_MLM_LINK_ESTABLISHED_STATE)) {
* Re/Assoc Req frame by incrementing debug counter & logging pe_debug("%s: peer:%pM in mlmState %d (%s) and sta del %d",
* error. (sub_type == LIM_ASSOC) ? "Assoc" : "ReAssoc",
*/ sta_ds->staAddr, sta_ds->mlmStaContext.mlmState,
if (sub_type == LIM_ASSOC) { lim_mlm_state_str(sta_ds->mlmStaContext.mlmState),
#ifdef WLAN_DEBUG sta_ds->sta_deletion_in_progress);
mac_ctx->lim.gLimNumAssocReqDropInvldState++; lim_update_assoc_drop_count(mac_ctx, sub_type);
#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);
return false; 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", pe_err("Received Assoc req in state: %X STAid: %d",
sta_ds->mlmStaContext.mlmState, peer_idx); sta_ds->mlmStaContext.mlmState, peer_idx);
return false; return false;
} 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;
}
*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;
}
} }
/*
* 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;
}
*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; 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) { if (cfg_min(CFG_PMF_SA_QUERY_RETRY_INTERVAL) > retry_interval) {
retry_interval = cfg_default(CFG_PMF_SA_QUERY_RETRY_INTERVAL); retry_interval = cfg_default(CFG_PMF_SA_QUERY_RETRY_INTERVAL);
} }
if (sta_ds->rmfEnabled && if (sta_ds->rmfEnabled) {
tx_timer_create(mac_ctx, &sta_ds->pmfSaQueryTimer, /* Try to delete it before, creating.*/
"PMF SA Query timer", lim_pmf_sa_query_timer_handler, lim_delete_pmf_query_timer(sta_ds);
timer_id.value, if (tx_timer_create(mac_ctx, &sta_ds->pmfSaQueryTimer,
SYS_MS_TO_TICKS((retry_interval * 1024) / 1000), "PMF SA Query timer", lim_pmf_sa_query_timer_handler,
0, TX_NO_ACTIVATE) != TX_SUCCESS) { timer_id.value,
pe_err("could not create PMF SA Query timer"); SYS_MS_TO_TICKS((retry_interval * 1024) / 1000),
lim_reject_association(mac_ctx, hdr->sa, sub_type, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
true, auth_type, peer_idx, false, pe_err("could not create PMF SA Query timer");
eSIR_MAC_UNSPEC_FAILURE_STATUS, lim_reject_association(mac_ctx, hdr->sa, sub_type,
session); true, auth_type, peer_idx, false,
return 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 #endif
if (assoc_req->ExtCap.present) { if (assoc_req->ExtCap.present) {

View File

@@ -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 * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * 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); qdf_mc_timer_destroy(&timer_ptr->qdf_timer);
timer_ptr->tmrSignature = 0;
return TX_SUCCESS; return TX_SUCCESS;
} /*** tx_timer_delete() ***/ } /*** tx_timer_delete() ***/