qcacld-3.0: Fix sta_ds use after free

lim_is_pkt_candidate_for_drop() uses sta_ds to update last assoc
and deauth/disasocc received time without taking any lock for
sta_ds. deletion of sta_ds in pe_delete_session before accessing
sta_ds in dph_lookup_hash_entry can lead lead to Assert.
Similar is the case with sta_ds->last_assoc_received_time and
sta_ds->last_disassoc_deauth_received_time.

Fix is to use peer_priv instead of sta_ds and update
last_assoc_received_time and last_disassoc_deauth_received_time of
peer_mlme_priv_obj. In this case refcount gets increased for valid
peer and peer won't be deleted until lim_is_pkt_candidate_for_drop
releases the ref count of the peer.

Change-Id: I9daf31f9dd7b509eaf38a93078bb7418605b1c74
CRs-Fixed: 2598841
This commit is contained in:
sheenam monga 2020-01-08 19:53:43 +05:30 • committed by nshrivas
commit 1fa0514eb7
4 changed files with 33 additions and 20 deletions

View file

@ -57,10 +57,14 @@ struct wlan_ies {
* struct peer_mlme_priv_obj - peer MLME component object
* @ucast_key_cipher: unicast crypto type.
* @is_pmf_enabled: True if PMF is enabled
* @last_assoc_received_time: last assoc received time
* @last_disassoc_deauth_received_time: last disassoc/deauth received time
*/
struct peer_mlme_priv_obj {
uint32_t ucast_key_cipher;
bool is_pmf_enabled;
qdf_time_t last_assoc_received_time;
qdf_time_t last_disassoc_deauth_received_time;
};
/**

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
@ -196,8 +196,6 @@ tpDphHashNode dph_init_sta_state(struct mac_context *mac, tSirMacAddr staAddr,
sta->added = 1;
sta->is_disassoc_deauth_in_progress = 0;
sta->last_assoc_received_time = 0;
sta->last_disassoc_deauth_received_time = 0;
sta->sta_deletion_in_progress = false;
sta->valid = 1;
return sta;
@ -334,8 +332,6 @@ QDF_STATUS dph_delete_hash_entry(struct mac_context *mac, tSirMacAddr staAddr,
prev->next = ptr->next;
ptr->added = 0;
ptr->is_disassoc_deauth_in_progress = 0;
ptr->last_assoc_received_time = 0;
ptr->last_disassoc_deauth_received_time = 0;
ptr->sta_deletion_in_progress = false;
ptr->next = 0;
} else {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2011-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
@ -171,8 +171,6 @@ typedef struct sDphHashNode {
/* key installed for this STA or not in the firmware */
uint8_t is_key_installed;
uint8_t is_disassoc_deauth_in_progress;
qdf_time_t last_assoc_received_time;
qdf_time_t last_disassoc_deauth_received_time;
uint8_t nss;
int8_t del_sta_ctx_rssi;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2011-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
@ -2613,9 +2613,8 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac,
} else if ((subType == SIR_MAC_MGMT_ASSOC_REQ) ||
(subType == SIR_MAC_MGMT_DISASSOC) ||
(subType == SIR_MAC_MGMT_DEAUTH)) {
uint16_t assoc_id;
struct dph_hash_table *dph_table;
tDphHashNode *sta_ds;
struct peer_mlme_priv_obj *peer_priv;
struct wlan_objmgr_peer *peer;
qdf_time_t *timestamp;
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
@ -2623,20 +2622,34 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac,
&sessionId);
if (!pe_session)
return eMGMT_DROP_SPURIOUS_FRAME;
dph_table = &pe_session->dph.dphHashTable;
sta_ds = dph_lookup_hash_entry(mac, pHdr->sa, &assoc_id,
dph_table);
if (!sta_ds) {
peer = wlan_objmgr_get_peer_by_mac(mac->psoc,
pHdr->sa,
WLAN_LEGACY_MAC_ID);
if (!peer) {
if (subType == SIR_MAC_MGMT_ASSOC_REQ)
return eMGMT_DROP_NO_DROP;
else
return eMGMT_DROP_SPURIOUS_FRAME;
return eMGMT_DROP_SPURIOUS_FRAME;
}
peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
WLAN_UMAC_COMP_MLME);
if (!peer_priv) {
wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
if (subType == SIR_MAC_MGMT_ASSOC_REQ)
return eMGMT_DROP_NO_DROP;
return eMGMT_DROP_SPURIOUS_FRAME;
}
if (subType == SIR_MAC_MGMT_ASSOC_REQ)
timestamp = &sta_ds->last_assoc_received_time;
timestamp =
&peer_priv->last_assoc_received_time;
else
timestamp = &sta_ds->last_disassoc_deauth_received_time;
timestamp =
&peer_priv->last_disassoc_deauth_received_time;
if (*timestamp > 0 &&
qdf_system_time_before(qdf_get_system_timestamp(),
*timestamp +
@ -2646,10 +2659,12 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac,
(int)(qdf_get_system_timestamp() - *timestamp),
"of last frame. Allow it only after",
LIM_DOS_PROTECTION_TIME);
wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
return eMGMT_DROP_EXCESSIVE_MGMT_FRAME;
}
*timestamp = qdf_get_system_timestamp();
wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
}