From a2ef8b1904cde681cd8485e1d6d9202544178800 Mon Sep 17 00:00:00 2001 From: Vignesh Viswanathan Date: Tue, 24 Oct 2017 22:32:28 +0530 Subject: [PATCH] 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 --- core/wma/src/wma_mgmt.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 4a4ec1abc749..b67bcfbe8ca1 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -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]);