Переглянути джерело

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
Abhinav Kumar 7 роки тому
батько
коміт
5eda62d43c

+ 1 - 0
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;

+ 10 - 0
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;
 			}
 

+ 3 - 0
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",