1
0

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
Este cometimento está contido em:
Rajeev Kumar Sirasanagandla
2018-10-23 16:00:11 +05:30
cometido por nshrivas
ascendente 78b6ac9cec
cometimento d7b4847bee

Ver ficheiro

@@ -10377,13 +10377,14 @@ extract_roam_scan_stats_res_evt_tlv(wmi_unified_t wmi_handle, void *evt_buf,
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 @@ extract_roam_scan_stats_res_evt_tlv(wmi_unified_t wmi_handle, void *evt_buf,
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 @@ extract_roam_scan_stats_res_evt_tlv(wmi_unified_t wmi_handle, void *evt_buf,
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 @@ extract_roam_scan_stats_res_evt_tlv(wmi_unified_t wmi_handle, void *evt_buf,
*res_param = res;
return QDF_STATUS_SUCCESS;
error:
qdf_mem_free(res);
return QDF_STATUS_E_FAILURE;
}
/**