qcacmn: Avoid buffer overflow in roam scan stats extract handler

In extract_roam_scan_stats_res_evt_tlv(), there is potential
buffer-overflow due to no input validation of following event
parameters from firmware:
(a) Roam scan frequencies against maximum value of 50
(WMI_ROAM_SCAN_STATS_CHANNELS_MAX) and
(b) Roam scan candidates against maximum value of 4
(WMI_ROAM_SCAN_STATS_CANDIDATES_MAX)

To fix this, validate roam scan stats event parameters.

Change-Id: I866b492f7ccb48c4960ff25a9e817cbdb394509e
CRs-Fixed: 2335530
diff --git a/wmi_unified_tlv.c b/wmi_unified_tlv.c
index 413ce6a..7d56095 100644
--- a/wmi_unified_tlv.c
+++ b/wmi_unified_tlv.c
@@ -10377,13 +10377,14 @@
 
 	num_scans = fixed_param->num_roam_scans;
 	scan_param_size = sizeof(struct wmi_roam_scan_stats_params);
-	if ((num_scans > ((UINT_MAX - sizeof(*res)) / scan_param_size))) {
-		wmi_err_rl("Invalid num_roam_scans %d", num_scans);
+	*vdev_id = fixed_param->vdev_id;
+	if (num_scans > WMI_ROAM_SCAN_STATS_MAX) {
+		wmi_err_rl("%u exceeded maximum roam scan stats: %u",
+			   num_scans, WMI_ROAM_SCAN_STATS_MAX);
 		return QDF_STATUS_E_INVAL;
 	}
 
 	total_len = sizeof(*res) + num_scans * scan_param_size;
-	*vdev_id = fixed_param->vdev_id;
 
 	res = qdf_mem_malloc(total_len);
 	if (!res) {
@@ -10425,8 +10426,16 @@
 		uint32_t count, chan_info_sum = 0;
 
 		num_channels = param_buf->num_channels;
-		for (count = 0; count < param_buf->num_num_channels; count++)
+		for (count = 0; count < param_buf->num_num_channels; count++) {
+			if (param_buf->num_channels[count] >
+			    WMI_ROAM_SCAN_STATS_CHANNELS_MAX) {
+				wmi_err_rl("%u exceeded max scan channels %u",
+					   param_buf->num_channels[count],
+					   WMI_ROAM_SCAN_STATS_CHANNELS_MAX);
+				goto error;
+			}
 			chan_info_sum += param_buf->num_channels[count];
+		}
 
 		if (param_buf->chan_info &&
 		    param_buf->num_chan_info == chan_info_sum)
@@ -10435,12 +10444,19 @@
 
 	if (param_buf->num_roam_candidates &&
 	    param_buf->num_num_roam_candidates == num_scans) {
-		uint32_t count, roam_cand_sum = 0;
+		uint32_t cnt, roam_cand_sum = 0;
 
 		num_roam_candidates = param_buf->num_roam_candidates;
-		for (count = 0; count < param_buf->num_num_roam_candidates;
-		     count++)
-			roam_cand_sum += param_buf->num_roam_candidates[count];
+		for (cnt = 0; cnt < param_buf->num_num_roam_candidates; cnt++) {
+			if (param_buf->num_roam_candidates[cnt] >
+			    WMI_ROAM_SCAN_STATS_CANDIDATES_MAX) {
+				wmi_err_rl("%u exceeded max scan cand %u",
+					   param_buf->num_roam_candidates[cnt],
+					   WMI_ROAM_SCAN_STATS_CANDIDATES_MAX);
+				goto error;
+			}
+			roam_cand_sum += param_buf->num_roam_candidates[cnt];
+		}
 
 		if (param_buf->bssid &&
 		    param_buf->num_bssid == roam_cand_sum)
@@ -10520,6 +10536,9 @@
 	*res_param = res;
 
 	return QDF_STATUS_SUCCESS;
+error:
+	qdf_mem_free(res);
+	return QDF_STATUS_E_FAILURE;
 }
 
 /**