Quellcode durchsuchen

qcacld-3.0: Fix potential buffer overflow for TX_COMPL_IND

qcacld-2.0 to qcacld-3.0 propagation

Check for the validity of num_msdus when received the htt message of
HTT_T2H_MSG_TYPE_TX_COMPL_IND or HTT_T2H_MSG_TYPE_TX_INSPECT_IND from
firmware to ensure the buffer overflow does not happen.

Change-Id: Ic6ce75f34c5e2705d174eda014350e6ef0391388
CRs-Fixed: 2146869
Tiger Yu vor 7 Jahren
Ursprung
Commit
a007b9a256
1 geänderte Dateien mit 63 neuen und 0 gelöschten Zeilen
  1. 63 0
      core/dp/htt/htt_t2h.c

+ 63 - 0
core/dp/htt/htt_t2h.c

@@ -582,6 +582,9 @@ static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg,
 		qdf_nbuf_free(htt_t2h_msg);
 }
 
+#define HTT_TX_COMPL_HEAD_SZ			4
+#define HTT_TX_COMPL_BYTES_PER_MSDU_ID		2
+
 /**
  * Generic Target to host Msg/event  handler  for low priority messages
  * Low priority message are handler in a different handler called from
@@ -673,10 +676,26 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 		int old_credit;
 		int num_msdus;
 		enum htt_tx_status status;
+		int msg_len = qdf_nbuf_len(htt_t2h_msg);
 
 		/* status - no enum translation needed */
 		status = HTT_TX_COMPL_IND_STATUS_GET(*msg_word);
 		num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word);
+
+		/*
+		 * each desc id will occupy 2 bytes.
+		 * the 4 is for htt msg header
+		 */
+		if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID +
+			HTT_TX_COMPL_HEAD_SZ) > msg_len) {
+			qdf_print("%s: num_msdus(%d) is invalid,"
+				"adf_nbuf_len = %d\n",
+				__FUNCTION__,
+				num_msdus,
+				msg_len);
+			break;
+		}
+
 		if (num_msdus & 0x1) {
 			struct htt_tx_compl_ind_base *compl =
 				(void *)msg_word;
@@ -765,8 +784,23 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 	case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
 	{
 		int num_msdus;
+		int msg_len = qdf_nbuf_len(htt_t2h_msg);
 
 		num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word);
+		/*
+		 * each desc id will occupy 2 bytes.
+		 * the 4 is for htt msg header
+		 */
+		if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID +
+			HTT_TX_COMPL_HEAD_SZ) > msg_len) {
+			qdf_print("%s: num_msdus(%d) is invalid,"
+				"adf_nbuf_len = %d\n",
+				__FUNCTION__,
+				num_msdus,
+				msg_len);
+			break;
+		}
+
 		if (num_msdus & 0x1) {
 			struct htt_tx_compl_ind_base *compl =
 				(void *)msg_word;
@@ -933,6 +967,21 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus,
 			/* status - no enum translation needed */
 			status = HTT_TX_COMPL_IND_STATUS_GET(*msg_word);
 			num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word);
+
+			/*
+			 * each desc id will occupy 2 bytes.
+			 * the 4 is for htt msg header
+			 */
+			if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID +
+				HTT_TX_COMPL_HEAD_SZ) > msg_len) {
+				qdf_print("%s: num_msdus(%d) is invalid,"
+					"adf_nbuf_len = %d\n",
+					__FUNCTION__,
+					num_msdus,
+					msg_len);
+				break;
+			}
+
 			if (num_msdus & 0x1) {
 				struct htt_tx_compl_ind_base *compl =
 					(void *)msg_word;
@@ -992,6 +1041,20 @@ void htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus,
 			int num_msdus;
 
 			num_msdus = HTT_TX_COMPL_IND_NUM_GET(*msg_word);
+			/*
+			 * each desc id will occupy 2 bytes.
+			 * the 4 is for htt msg header
+			 */
+			if ((num_msdus * HTT_TX_COMPL_BYTES_PER_MSDU_ID +
+				HTT_TX_COMPL_HEAD_SZ) > msg_len) {
+				qdf_print("%s: num_msdus(%d) is invalid,"
+					"adf_nbuf_len = %d\n",
+					__FUNCTION__,
+					num_msdus,
+					msg_len);
+				break;
+			}
+
 			if (num_msdus & 0x1) {
 				struct htt_tx_compl_ind_base *compl =
 					(void *)msg_word;