summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVignesh Viswanathan <viswanat@codeaurora.org>2017-10-24 22:32:28 +0530
committersnandini <snandini@codeaurora.org>2017-10-26 00:44:07 -0700
commitf8317a77ebbff947a033214645babeb1004988c6 (patch)
treebf171ff3cd40a8a0c88e3d8141bfbd4a035795bd
parent0e0b89ca1ffab91ddd2da6a0a9c0665c3a3c8f61 (diff)
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
-rw-r--r--core/wma/src/wma_mgmt.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c
index d7e1a4648511..bf1c582da59f 100644
--- a/core/wma/src/wma_mgmt.c
+++ b/core/wma/src/wma_mgmt.c
@@ -2842,7 +2842,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) {
@@ -2854,6 +2855,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]);