From 5eda62d43ce6e033e2eecc3d22be43e8829bf025 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Tue, 13 Feb 2018 13:00:39 +0530 Subject: [PATCH] qcacld-3.0: Fix to avoid race condition during acs scan Currently, driver allows multiple acs scan requests at a time. Due to this race conditions can occur and causes "use after free" issue for variable channelList. To avoid race condition, driver should allow only one acs scan request at a time. Add a new atomic variable to make sure that if one acs scan request is in process, the driver should reject all further acs scan requests. Change-Id: I7aa2f4df0dd4c6ca8ff791fe462d142fc7b3e691 CRs-Fixed: 2176354 --- core/hdd/inc/wlan_hdd_main.h | 1 + core/hdd/src/wlan_hdd_cfg80211.c | 10 ++++++++++ core/hdd/src/wlan_hdd_hostapd.c | 3 +++ 3 files changed, 14 insertions(+) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ccf231a7f174..7e76ca34f431 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1688,6 +1688,7 @@ struct hdd_context { /* Lock to control access to dnbs and coex avoid freq list */ struct mutex avoid_freq_lock; #endif + qdf_atomic_t is_acs_allowed; #ifdef WLAN_FEATURE_TSF /* indicate whether tsf has been initialized */ qdf_atomic_t tsf_ready_flag; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 4e0b739bdb67..e8c5f4756088 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -2510,6 +2510,12 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, goto out; } + if (qdf_atomic_inc_return(&hdd_ctx->is_acs_allowed) > 1) { + hdd_err("ACS rejected as previous req already in progress"); + status = -EINVAL; + goto out; + } + sap_config = &adapter->session.ap.sap_config; if (sap_config->acs_cfg.ch_list) qdf_mem_free(sap_config->acs_cfg.ch_list); @@ -2520,12 +2526,14 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, wlan_hdd_cfg80211_do_acs_policy); if (status) { hdd_err("Invalid ATTR"); + qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0); goto out; } if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) { hdd_err("Attr hw_mode failed"); status = -EINVAL; + qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0); goto out; } hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]); @@ -2607,6 +2615,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, if (!sap_config->acs_cfg.ch_list) { hdd_err("ACS config alloc fail"); status = -ENOMEM; + qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0); goto out; } @@ -2625,6 +2634,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy, if (!sap_config->acs_cfg.ch_list) { hdd_err("ACS config alloc fail"); status = -ENOMEM; + qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0); goto out; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 01da4746cfde..f3257a274318 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -214,6 +214,8 @@ int hdd_sap_context_init(struct hdd_context *hdd_ctx) qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock"); qdf_spinlock_create(&hdd_ctx->sap_update_info_lock); + qdf_atomic_init(&hdd_ctx->is_acs_allowed); + return 0; } @@ -2550,6 +2552,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, /* send vendor event to hostapd only for hostapd based acs*/ if (!hdd_ctx->config->force_sap_acs) wlan_hdd_cfg80211_acs_ch_select_evt(adapter); + qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0); return QDF_STATUS_SUCCESS; case eSAP_ECSA_CHANGE_CHAN_IND: hdd_debug("Channel change indication from peer for channel %d",