qcacld-2.0: Fix potential BUG_ON in the htt_rx_offload_msdu_pop_ll
For HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND, the msdu_cnt is a signed
integer coming from firmware. If set the msdu_cnt to a negative value,
or be greater than the number of current elements in the queue, the loop
will execute lots of times in ol_rx_offload_deliver_ind_handler, the
htt_rx_netbuf_pop will cause the BUG_ON issue sooner or later if it is
low latency solution.
Change the msdu_cnt type from signed to unsigned and add the validity
msdu_cnt checking will fix this issue.
Change-Id: I436557a124074f59ab11fd937dfdc975b9caebe8
CRs-Fixed: 2149461
diff --git a/CORE/CLD_TXRX/HTT/htt_rx.c b/CORE/CLD_TXRX/HTT/htt_rx.c
index b38043d..57762e0 100644
--- a/CORE/CLD_TXRX/HTT/htt_rx.c
+++ b/CORE/CLD_TXRX/HTT/htt_rx.c
@@ -1291,6 +1291,13 @@
}
int
+htt_rx_offload_msdu_cnt_ll(
+ htt_pdev_handle pdev)
+{
+ return htt_rx_ring_elems(pdev);
+}
+
+int
htt_rx_offload_msdu_pop_ll(
htt_pdev_handle pdev,
adf_nbuf_t offload_deliver_msg,
@@ -1914,6 +1921,13 @@
return 0;
}
+int
+htt_rx_offload_msdu_cnt_hl(
+ htt_pdev_handle pdev)
+{
+ return 1;
+}
+
/* Return values: 1 - success, 0 - failure */
int
htt_rx_offload_msdu_pop_hl(
@@ -2577,6 +2591,10 @@
adf_nbuf_t *tail_msdu);
int
+(*htt_rx_offload_msdu_cnt)(
+ htt_pdev_handle pdev);
+
+int
(*htt_rx_offload_msdu_pop)(
htt_pdev_handle pdev,
adf_nbuf_t offload_deliver_msg,
@@ -3404,6 +3422,7 @@
if (VOS_MONITOR_MODE == vos_get_conparam())
htt_rx_amsdu_pop = htt_rx_mon_amsdu_rx_in_order_pop_ll;
+ htt_rx_offload_msdu_cnt = htt_rx_offload_msdu_cnt_ll;
htt_rx_offload_msdu_pop = htt_rx_offload_msdu_pop_ll;
htt_rx_mpdu_desc_retry = htt_rx_mpdu_desc_retry_ll;
htt_rx_mpdu_desc_seq_num = htt_rx_mpdu_desc_seq_num_ll;
@@ -3430,6 +3449,7 @@
if (VOS_MONITOR_MODE == vos_get_conparam())
htt_rx_amsdu_pop = htt_rx_mon_amsdu_pop_hl;
htt_rx_frag_pop = htt_rx_frag_pop_hl;
+ htt_rx_offload_msdu_cnt = htt_rx_offload_msdu_cnt_hl;
htt_rx_offload_msdu_pop = htt_rx_offload_msdu_pop_hl;
htt_rx_mpdu_desc_list_next = htt_rx_mpdu_desc_list_next_hl;
htt_rx_mpdu_desc_retry = htt_rx_mpdu_desc_retry_hl;
diff --git a/CORE/CLD_TXRX/HTT/htt_t2h.c b/CORE/CLD_TXRX/HTT/htt_t2h.c
index 4467ca7..6dedfb9 100644
--- a/CORE/CLD_TXRX/HTT/htt_t2h.c
+++ b/CORE/CLD_TXRX/HTT/htt_t2h.c
@@ -196,7 +196,7 @@
}
case HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND:
{
- int msdu_cnt;
+ u_int16_t msdu_cnt;
msdu_cnt = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_GET(*msg_word);
ol_rx_offload_deliver_ind_handler(
pdev->txrx_pdev,
diff --git a/CORE/CLD_TXRX/TXRX/ol_rx.c b/CORE/CLD_TXRX/TXRX/ol_rx.c
index 22fab03..6e8ced2 100644
--- a/CORE/CLD_TXRX/TXRX/ol_rx.c
+++ b/CORE/CLD_TXRX/TXRX/ol_rx.c
@@ -815,7 +815,7 @@
ol_rx_offload_deliver_ind_handler(
ol_txrx_pdev_handle pdev,
adf_nbuf_t msg,
- int msdu_cnt)
+ u_int16_t msdu_cnt)
{
int vdev_id, peer_id, tid;
adf_nbuf_t head_buf, tail_buf, buf;
@@ -824,6 +824,17 @@
u_int8_t fw_desc;
htt_pdev_handle htt_pdev = pdev->htt_pdev;
+ if (msdu_cnt > htt_rx_offload_msdu_cnt(htt_pdev)) {
+ TXRX_PRINT(TXRX_PRINT_LEVEL_ERR,
+ "%s: invalid msdu_cnt=%u\n",
+ __func__,
+ msdu_cnt);
+ if (pdev->cfg.is_high_latency)
+ htt_rx_desc_frame_free(htt_pdev, msg);
+
+ return;
+ }
+
while (msdu_cnt) {
if (!htt_rx_offload_msdu_pop(
htt_pdev, msg, &vdev_id, &peer_id,
diff --git a/CORE/SERVICES/COMMON/ol_htt_rx_api.h b/CORE/SERVICES/COMMON/ol_htt_rx_api.h
index 34a209c..3ac1aff 100644
--- a/CORE/SERVICES/COMMON/ol_htt_rx_api.h
+++ b/CORE/SERVICES/COMMON/ol_htt_rx_api.h
@@ -671,6 +671,15 @@
adf_nbuf_t *tail_msdu);
/**
+ * @brief Return the maximum number of available msdus currently
+ *
+ * @param pdev - the HTT instance the rx data was received on
+ */
+extern int
+(*htt_rx_offload_msdu_cnt)(
+ htt_pdev_handle pdev);
+
+/**
* @brief Return a linked list of buffers holding one MSDU
* In some systems the buffers are delivered along with offload delivery
* indication message itself, while in other systems the buffers are uploaded
diff --git a/CORE/SERVICES/COMMON/ol_txrx_htt_api.h b/CORE/SERVICES/COMMON/ol_txrx_htt_api.h
index cb6b828..6918a6d 100644
--- a/CORE/SERVICES/COMMON/ol_txrx_htt_api.h
+++ b/CORE/SERVICES/COMMON/ol_txrx_htt_api.h
@@ -448,7 +448,7 @@
ol_rx_offload_deliver_ind_handler(
ol_txrx_pdev_handle pdev,
adf_nbuf_t msg,
- int msdu_cnt);
+ u_int16_t msdu_cnt);
/**
* @brief Process a peer map message sent by the target.