From 8f28b9e42bcb3ff7de08134341d7a16274a3b915 Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Thu, 11 Jun 2020 12:09:00 +0530 Subject: [PATCH] qcacld-3.0: Check for invalid put_ref scenario for sta_info Currently in the ref_count mechanism used for sta_info, the driver has no checks to determine if there are any faulty ref counting instances. In case multiple ref_put are done for a single take_ref, it can lead to a memory corruption. Add a sanity check in hdd_sta_info_put_ref that causes a device assert in case the put_ref is called on a sta_info with already zero ref_count. Change-Id: I0b502e1df4c37601b46cc727acc94a72a401e051 CRs-Fixed: 2707614 --- core/hdd/src/wlan_hdd_sta_info.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/hdd/src/wlan_hdd_sta_info.c b/core/hdd/src/wlan_hdd_sta_info.c index fa150394c990..98fb4dd130e8 100644 --- a/core/hdd/src/wlan_hdd_sta_info.c +++ b/core/hdd/src/wlan_hdd_sta_info.c @@ -144,6 +144,7 @@ hdd_put_sta_info_ref(struct hdd_sta_info_obj *sta_info_container, struct hdd_station_info **sta_info, bool lock_required) { struct hdd_station_info *info; + struct qdf_mac_addr addr; if (!sta_info_container || !sta_info) { hdd_err("Parameter(s) null"); @@ -160,6 +161,17 @@ hdd_put_sta_info_ref(struct hdd_sta_info_obj *sta_info_container, if (lock_required) qdf_spin_lock_bh(&sta_info_container->sta_obj_lock); + /* + * In case the put_ref is called more than twice for a single take_ref, + * this will result in either a BUG or page fault. In both the cases, + * the root cause would be known and the buggy put_ref can be taken + * care of. + */ + if (!qdf_atomic_read(&info->ref_cnt)) { + hdd_alert("sta_info ref count is already 0"); + QDF_BUG(0); + } + qdf_atomic_dec(&info->ref_cnt); if (qdf_atomic_read(&info->ref_cnt)) { @@ -168,6 +180,7 @@ hdd_put_sta_info_ref(struct hdd_sta_info_obj *sta_info_container, return; } + qdf_copy_macaddr(&addr, &info->sta_mac); if (info->assoc_req_ies.len) { qdf_mem_free(info->assoc_req_ies.data); info->assoc_req_ies.data = NULL; @@ -180,6 +193,9 @@ hdd_put_sta_info_ref(struct hdd_sta_info_obj *sta_info_container, if (lock_required) qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock); + + hdd_nofl_debug("STA_INFO: " QDF_MAC_ADDR_STR " freed", + QDF_MAC_ADDR_ARRAY(addr.bytes)); } void hdd_clear_cached_sta_info(struct hdd_adapter *adapter)