Просмотр исходного кода

qcacld-3.0: Fix buffer overflow in htt_t2h_msg_handler_fast

Currently variable "num_mpdu_ranges" is from message, which is used
directly without any validation which causes buffer over-write.

To avoid buffer over-write add check for the valid num_mpdu_ranges

Change-Id: I54e138d4bd63cbe7a0ae4faf0fe9d8e59ca92c71
CRs-Fixed: 2213655
jitiphil 7 лет назад
Родитель
Сommit
10ff2ff9ed
1 измененных файлов с 30 добавлено и 1 удалено
  1. 30 1
      core/dp/htt/htt_t2h.c

+ 30 - 1
core/dp/htt/htt_t2h.c

@@ -993,8 +993,10 @@ 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;
 			u_int16_t peer_id;
 			u_int8_t tid;
+			msg_len = qdf_nbuf_len(htt_t2h_msg);
 
 			peer_id = HTT_RX_IND_PEER_ID_GET(*msg_word);
 			tid = HTT_RX_IND_EXT_TID_GET(*msg_word);
@@ -1004,7 +1006,6 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus,
 				WARN_ON(1);
 				break;
 			}
-
 			num_msdu_bytes =
 				HTT_RX_IND_FW_RX_DESC_BYTES_GET(
 				*(msg_word + 2 +
@@ -1024,6 +1025,34 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus,
 				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 >
+					 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 +
+					     (num_mpdu_ranges *
+					     (int)sizeof(uint32_t));
+			/*
+			 * Check that the addition and multiplication
+			 * 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",
+					  (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);
 			break;