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
commit 7a7799b04a
2 changed files with 85 additions and 61 deletions

View file

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

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
* 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() ***/