diff options
| author | jitiphil <jitiphil@codeaurora.org> | 2018-05-24 14:12:07 +0530 |
|---|---|---|
| committer | nshrivas <nshrivas@codeaurora.org> | 2018-05-30 07:33:30 -0700 |
| commit | 889ded18bd3dff02af90742e0f0936f899a64fc7 (patch) | |
| tree | de287e97b974cb880ac7f958a8550f557529cf9e | |
| parent | 47ae12c0aa2e5a0aa3abeba23b4e9a443b5f9e93 (diff) | |
qcacld-3.0: Incorrect message offset validations in t2h message handling
Currently in htt_t2h_msg_handler_fast, msg_len, which is in number of
bytes, is directly compared with pdev->rx_mpdu_range_offset_words,
which is in number of words. Thus their comparison becomes invalid.
In htt_t2h_msg_handler, in addition to similar issue as above, the
checks for message offset validations do not consider integer overflows
occurring.
In htt_t2h_msg_handler_fast, the check condition involving
pdev_rx_mpdu_range_offset_words were corrected to work with bytes,
and in htt_t2h_msg_handler checks for integer overflow were also
added.
Change-Id: I9ec7d30cc24d288ddcabd3bb30674a2ca21f2251
CRs-Fixed: 2248069
| -rw-r--r-- | core/dp/htt/htt_t2h.c | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c index 017bf9991f7a..d32a7c508510 100644 --- a/core/dp/htt/htt_t2h.c +++ b/core/dp/htt/htt_t2h.c @@ -702,6 +702,8 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) { unsigned int num_mpdu_ranges; unsigned int num_msdu_bytes; + unsigned int calculated_msg_len; + unsigned int rx_mpdu_range_offset_bytes; uint16_t peer_id; uint8_t tid; int msg_len = qdf_nbuf_len(htt_t2h_msg); @@ -733,18 +735,46 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt) * 1 word for every 4 MSDU bytes (round up), * 1 word for the MPDU range header */ + rx_mpdu_range_offset_bytes = + (HTT_RX_IND_HDR_BYTES + num_msdu_bytes + 3); + if (qdf_unlikely(num_msdu_bytes > + rx_mpdu_range_offset_bytes)) { + qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid num_msdu_bytes %u\n", + num_msdu_bytes); + WARN_ON(1); + break; + } pdev->rx_mpdu_range_offset_words = - (HTT_RX_IND_HDR_BYTES + num_msdu_bytes + 3) >> 2; + rx_mpdu_range_offset_bytes >> 2; num_mpdu_ranges = HTT_RX_IND_NUM_MPDU_RANGES_GET(*(msg_word + 1)); pdev->rx_ind_msdu_byte_idx = 0; - if (qdf_unlikely(pdev->rx_mpdu_range_offset_words + (num_mpdu_ranges * 4) > msg_len)) { - qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid mpdu_ranges %d\n", - num_mpdu_ranges); + if (qdf_unlikely(rx_mpdu_range_offset_bytes > + msg_len)) { + qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid rx_mpdu_range_offset_words %d\n", + pdev->rx_mpdu_range_offset_words); + WARN_ON(1); + break; + } + calculated_msg_len = rx_mpdu_range_offset_bytes + + (num_mpdu_ranges * (int)sizeof(uint32_t)); + /* + * Check that the addition and multiplication + * do not cause integer overflow + */ + if (qdf_unlikely(calculated_msg_len < + rx_mpdu_range_offset_bytes)) { + qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid num_mpdu_ranges %u\n", + (num_mpdu_ranges * (int)sizeof(uint32_t))); + WARN_ON(1); + break; + } + if (qdf_unlikely(calculated_msg_len > msg_len)) { + qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid offset_words + mpdu_ranges %u\n", + calculated_msg_len); WARN_ON(1); break; } - ol_rx_indication_handler(pdev->txrx_pdev, htt_t2h_msg, peer_id, tid, num_mpdu_ranges); @@ -993,6 +1023,7 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus, unsigned int num_mpdu_ranges; unsigned int num_msdu_bytes; unsigned int calculated_msg_len; + unsigned int rx_mpdu_range_offset_bytes; u_int16_t peer_id; u_int8_t tid; msg_len = qdf_nbuf_len(htt_t2h_msg); @@ -1017,21 +1048,29 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus, * 1 word for every 4 MSDU bytes (round up), * 1 word for the MPDU range header */ + rx_mpdu_range_offset_bytes = + (HTT_RX_IND_HDR_BYTES + num_msdu_bytes + 3); + if (qdf_unlikely(num_msdu_bytes > + rx_mpdu_range_offset_bytes)) { + qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid num_msdu_bytes %u\n", + num_msdu_bytes); + WARN_ON(1); + break; + } pdev->rx_mpdu_range_offset_words = - (HTT_RX_IND_HDR_BYTES + num_msdu_bytes + 3) >> - 2; + rx_mpdu_range_offset_bytes >> 2; num_mpdu_ranges = HTT_RX_IND_NUM_MPDU_RANGES_GET(*(msg_word + 1)); pdev->rx_ind_msdu_byte_idx = 0; - if (qdf_unlikely(pdev->rx_mpdu_range_offset_words > + if (qdf_unlikely(rx_mpdu_range_offset_bytes > msg_len)) { qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid rx_mpdu_range_offset_words %d\n", pdev->rx_mpdu_range_offset_words); WARN_ON(1); break; } - calculated_msg_len = pdev->rx_mpdu_range_offset_words + + calculated_msg_len = rx_mpdu_range_offset_bytes + (num_mpdu_ranges * (int)sizeof(uint32_t)); /* @@ -1039,8 +1078,8 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus, * do not cause integer overflow */ if (qdf_unlikely(calculated_msg_len < - pdev->rx_mpdu_range_offset_words)) { - qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid mpdu_ranges %u\n", + rx_mpdu_range_offset_bytes)) { + qdf_print("HTT_T2H_MSG_TYPE_RX_IND, invalid num_mpdu_ranges %u\n", (num_mpdu_ranges * (int)sizeof(uint32_t))); WARN_ON(1); |
