Explorar el Código

qcacld-3.0: Fix potential integer overflow when TX_CREDIT_UPDATE

qcacld-2.0 to qcacld-3.0 propagation

Check for the validity of credits when received the htt message of
HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND or HTT_T2H_MSG_TYPE_TX_COMPL_IND
from firmware to ensure the integer overflow does not happen if these
messages invoked many times.

Change-Id: I01386b88f1b677153f3e51e055b7fbac073cd6b3
CRs-Fixed: 2147127
Tiger Yu hace 7 años
padre
commit
c35fbb1e72
Se han modificado 1 ficheros con 43 adiciones y 18 borrados
  1. 43 18
      core/dp/htt/htt_t2h.c

+ 43 - 18
core/dp/htt/htt_t2h.c

@@ -195,6 +195,8 @@ static void htt_ipa_op_response(struct htt_pdev_t *pdev, uint32_t *msg_word)
 }
 #endif
 
+#define MAX_TARGET_TX_CREDIT    204800
+
 /* Target to host Msg/event  handler  for low priority messages*/
 static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg,
 				   bool free_msg_buf)
@@ -450,13 +452,24 @@ static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg,
 	{
 		uint32_t htt_credit_delta_abs;
 		int32_t htt_credit_delta;
-		int sign;
+		int sign, old_credit;
 
 		htt_credit_delta_abs =
 			HTT_TX_CREDIT_DELTA_ABS_GET(*msg_word);
 		sign = HTT_TX_CREDIT_SIGN_BIT_GET(*msg_word) ? -1 : 1;
 		htt_credit_delta = sign * htt_credit_delta_abs;
 
+		old_credit = qdf_atomic_read(&pdev->htt_tx_credit.target_delta);
+		if (((old_credit + htt_credit_delta) > MAX_TARGET_TX_CREDIT) ||
+			((old_credit + htt_credit_delta) < -MAX_TARGET_TX_CREDIT)) {
+			qdf_print("%s: invalid credit update,old_credit=%d,"
+				"htt_credit_delta=%d\n",
+				__func__,
+				old_credit,
+				htt_credit_delta);
+			break;
+		}
+
 		if (pdev->cfg.is_high_latency &&
 		    !pdev->cfg.default_tx_comp_req) {
 			HTT_TX_MUTEX_ACQUIRE(&pdev->credit_mutex);
@@ -657,6 +670,7 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 	}
 	case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
 	{
+		int old_credit;
 		int num_msdus;
 		enum htt_tx_status status;
 
@@ -683,24 +697,35 @@ void htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 		}
 
 		if (pdev->cfg.is_high_latency) {
-			if (!pdev->cfg.default_tx_comp_req) {
-				int credit_delta;
-
-				HTT_TX_MUTEX_ACQUIRE(&pdev->credit_mutex);
-				qdf_atomic_add(num_msdus,
-					       &pdev->htt_tx_credit.
-								target_delta);
-				credit_delta = htt_tx_credit_update(pdev);
-				HTT_TX_MUTEX_RELEASE(&pdev->credit_mutex);
-
-				if (credit_delta) {
-					ol_tx_target_credit_update(
-							pdev->txrx_pdev,
-							credit_delta);
-				}
+			old_credit = qdf_atomic_read(
+						&pdev->htt_tx_credit.target_delta);
+			if (((old_credit + num_msdus) > MAX_TARGET_TX_CREDIT) ||
+				((old_credit + num_msdus) < -MAX_TARGET_TX_CREDIT)) {
+				qdf_print("%s: invalid credit update,old_credit=%d,"
+					"num_msdus=%d\n",
+					__func__,
+					old_credit,
+					num_msdus);
 			} else {
-				ol_tx_target_credit_update(pdev->txrx_pdev,
-							   num_msdus);
+				if (!pdev->cfg.default_tx_comp_req) {
+					int credit_delta;
+
+					HTT_TX_MUTEX_ACQUIRE(&pdev->credit_mutex);
+					qdf_atomic_add(num_msdus,
+						       &pdev->htt_tx_credit.
+							target_delta);
+					credit_delta = htt_tx_credit_update(pdev);
+					HTT_TX_MUTEX_RELEASE(&pdev->credit_mutex);
+
+					if (credit_delta) {
+						ol_tx_target_credit_update(
+								pdev->txrx_pdev,
+								credit_delta);
+					}
+				} else {
+					ol_tx_target_credit_update(pdev->txrx_pdev,
+								   num_msdus);
+				}
 			}
 		}