qcacld-3.0: Fix OOB read in wma_mgmt_tx_bundle_completion_handler

In function wma_mgmt_tx_bundle_completion_handler
cmpl_params->num_reports, param_buf->desc_ids and param_buf->status
are received from the FW. num_reports is used as array index to access
desc_ids and status. If the value of num_reports exceeds the max
allowed array index, out of bounds access would happen.

Add sanity check to make sure num_reports does not exceed the max
allowed limit. Also make sure num_reports is not greater than
num_desc_ids and num_status

Change-Id: I300411febf6449680e873e5947fa767298afe962
CRs-Fixed: 2119439
This commit is contained in:
Vignesh Viswanathan 2017-10-24 22:32:28 +05:30 • committed by snandini
commit a2ef8b1904

View file

@ -2901,7 +2901,8 @@ int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
uint32_t num_reports;
uint32_t *desc_ids;
uint32_t *status;
int i;
uint32_t i, buf_len;
bool excess_data = false;
param_buf = (WMI_MGMT_TX_BUNDLE_COMPLETION_EVENTID_param_tlvs *)buf;
if (!param_buf || !wma_handle) {
@ -2913,6 +2914,31 @@ int wma_mgmt_tx_bundle_completion_handler(void *handle, uint8_t *buf,
desc_ids = (uint32_t *)(param_buf->desc_ids);
status = (uint32_t *)(param_buf->status);
/* buf contains num_reports * sizeof(uint32) len of desc_ids and
* num_reports * sizeof(uint32) status,
* so (2 x (num_reports * sizeof(uint32)) should not exceed MAX
*/
if (cmpl_params->num_reports > (WMI_SVC_MSG_MAX_SIZE /
(2 * sizeof(uint32_t))))
excess_data = true;
else
buf_len = cmpl_params->num_reports * (2 * sizeof(uint32_t));
if (excess_data || (sizeof(*cmpl_params) > (WMI_SVC_MSG_MAX_SIZE -
buf_len))) {
WMA_LOGE("excess wmi buffer: num_reports %d",
cmpl_params->num_reports);
return -EINVAL;
}
if ((cmpl_params->num_reports > param_buf->num_desc_ids) ||
(cmpl_params->num_reports > param_buf->num_status)) {
WMA_LOGE("Invalid num_reports %d, num_desc_ids %d, num_status %d",
cmpl_params->num_reports, param_buf->num_desc_ids,
param_buf->num_status);
return -EINVAL;
}
for (i = 0; i < num_reports; i++)
wma_process_mgmt_tx_completion(wma_handle,
desc_ids[i], status[i]);