Forráskód Böngészése

qcacmn: Fix out-of-bounds of src_freq

When handling WMI_ROAM_SCAN_STATS_EVENTID,
the number of channels scanned for each roam trigger is fetched from
wmi_roam_scan_info TLV (wmi_roam_scan_info->roam_scan_channel_count),
The total number of channels for all the roam triggers is fetched from
param_buf->num_roam_scan_chan_info.

chan_idx is the index used to fetch the current channel info TLV to be
read. So if wmi_roam_scan_info->roam_scan_channel_count provided by
firmware exceeds the total param_buf->num_roam_scan_chan_info starting
from given chan_idx then OOB access of event buffer can happen.

To avoid this, validate the sum of the current chan_idx and
src_data->roam_scan_channel_count against
evt_buf->num_roam_scan_chan_info.

Change-Id: Ied94464d1f12690cf8832962b94595c2e00c33f8
CRs-Fixed: 3357714
Vinod Kumar Myadam 2 éve
szülő
commit
9934d3513c
1 módosított fájl, 17 hozzáadás és 0 törlés
  1. 17 0
      wmi/src/wmi_unified_tlv.c

+ 17 - 0
wmi/src/wmi_unified_tlv.c

@@ -19211,6 +19211,15 @@ extract_roam_scan_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
 			dst->num_chan = MAX_ROAM_SCAN_CHAN;
 
 		src_chan = &param_buf->roam_scan_chan_info[chan_idx];
+
+		if ((dst->num_chan + chan_idx) >
+		    param_buf->num_roam_scan_chan_info) {
+			wmi_err("Invalid TLV. num_chan %d chan_idx %d num_roam_scan_chan_info %d",
+				dst->num_chan, chan_idx,
+				param_buf->num_roam_scan_chan_info);
+			return QDF_STATUS_SUCCESS;
+		}
+
 		for (i = 0; i < dst->num_chan; i++) {
 			dst->chan_freq[i] = src_chan->channel;
 			dst->dwell_type[i] =
@@ -19330,6 +19339,14 @@ extract_roam_11kv_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf,
 	if (dst->num_freq > MAX_ROAM_SCAN_CHAN)
 		dst->num_freq = MAX_ROAM_SCAN_CHAN;
 
+	if ((dst->num_freq + rpt_idx) >
+	    param_buf->num_roam_neighbor_report_chan_info) {
+		wmi_err("Invalid TLV. num_freq %d rpt_idx %d num_roam_neighbor_report_chan_info %d",
+			dst->num_freq, rpt_idx,
+			param_buf->num_roam_scan_chan_info);
+		return QDF_STATUS_SUCCESS;
+	}
+
 	for (i = 0; i < dst->num_freq; i++) {
 		dst->freq[i] = src_freq->channel;
 		src_freq++;