qcacld-3.0: Avoid overflow of EXTSCAN bucket list

This is a qcacld-2.0 to qcacld-3.0 propagation.

Currently when processing an EXTSCAN vendor command the "num buckets"
attribute is limit checked and if it exceeds a MAX value then a
warning message is issued. But beyond that the "num buckets" attribute
is not used. Instead when the buckets are actually parsed the number
of buckets is calculated dynamically based upon the number of
attributes present in the request. Unfortunately when the bucket
attributes are parsed there is no check to make sure the number of
buckets processed does not exceed the MAX value, and as a result a
buffer overflow can occur. Address this issue by aborting the bucket
parsing once the expected number of records have been parsed.

Change-Id: Ic260dd65dc99118afbb8042d102acb5b26d1e123
CRs-Fixed: 1087797
diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c
index 663124d..91cba2d 100644
--- a/core/hdd/src/wlan_hdd_ext_scan.c
+++ b/core/hdd/src/wlan_hdd_ext_scan.c
@@ -2755,6 +2755,7 @@
 	int rem1, rem2;
 	QDF_STATUS status;
 	uint8_t bkt_index, j, num_channels, total_channels = 0;
+	uint32_t expected_buckets;
 	uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
 
 	uint32_t min_dwell_time_active_bucket =
@@ -2766,7 +2767,6 @@
 	uint32_t max_dwell_time_passive_bucket =
 		hdd_ctx->config->extscan_passive_max_chn_time;
 
-	bkt_index = 0;
 	req_msg->min_dwell_time_active =
 		req_msg->max_dwell_time_active =
 			hdd_ctx->config->extscan_active_max_chn_time;
@@ -2774,10 +2774,19 @@
 	req_msg->min_dwell_time_passive =
 		req_msg->max_dwell_time_passive =
 			hdd_ctx->config->extscan_passive_max_chn_time;
+
+	expected_buckets = req_msg->numBuckets;
 	req_msg->numBuckets = 0;
+	bkt_index = 0;
 
 	nla_for_each_nested(buckets,
 			tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
+
+		if (bkt_index >= expected_buckets) {
+			hdd_warn("ignoring excess buckets");
+			break;
+		}
+
 		if (nla_parse(bucket,
 			QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
 			nla_data(buckets), nla_len(buckets), NULL)) {
@@ -3271,8 +3280,10 @@
 	if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
 		hdd_warn("Exceeded MAX number of buckets: %d",
 				WLAN_EXTSCAN_MAX_BUCKETS);
+		num_buckets = WLAN_EXTSCAN_MAX_BUCKETS;
 	}
 	hdd_info("Input: Number of Buckets %d", num_buckets);
+	pReqMsg->numBuckets = num_buckets;
 
 	/* This is optional attribute, if not present set it to 0 */
 	if (!tb[PARAM_CONFIG_FLAGS])