diff options
| author | Vignesh Viswanathan <viswanat@codeaurora.org> | 2017-10-24 22:32:28 +0530 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-10-26 00:44:07 -0700 |
| commit | f8317a77ebbff947a033214645babeb1004988c6 (patch) | |
| tree | bf171ff3cd40a8a0c88e3d8141bfbd4a035795bd | |
| parent | 0e0b89ca1ffab91ddd2da6a0a9c0665c3a3c8f61 (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.c | 28 |
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]); |
