summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiger Yu <tfyu@codeaurora.org>2017-12-08 15:53:40 +0800
committersnandini <snandini@codeaurora.org>2017-12-10 22:52:13 -0800
commitb0c8f25d29f32991bf53e82ba87b6d959c407d56 (patch)
tree8922d829696448e5efe376f371a92899d9e96149
parentc03e9af01c2fe7ef265629b5bfcf5217c6f95e96 (diff)
qcacld-3.0: Fix potential BUG_ON in the htt_rx_offload_msdu_pop_ll
qcacld-2.0 to qcacld-3.0 propagation 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
-rw-r--r--core/dp/htt/htt_rx.c20
-rw-r--r--core/dp/htt/htt_t2h.c2
-rw-r--r--core/dp/ol/inc/ol_htt_rx_api.h9
-rw-r--r--core/dp/ol/inc/ol_txrx_htt_api.h2
-rw-r--r--core/dp/txrx/ol_rx.c13
5 files changed, 43 insertions, 3 deletions
diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c
index 6ac120b40639..4af58f59d1a2 100644
--- a/core/dp/htt/htt_rx.c
+++ b/core/dp/htt/htt_rx.c
@@ -1579,6 +1579,13 @@ htt_rx_frag_pop_hl(
}
static inline int
+htt_rx_offload_msdu_cnt_hl(
+ htt_pdev_handle pdev)
+{
+ return 1;
+}
+
+static inline int
htt_rx_offload_msdu_pop_hl(htt_pdev_handle pdev,
qdf_nbuf_t offload_deliver_msg,
int *vdev_id,
@@ -1625,6 +1632,13 @@ htt_rx_offload_msdu_pop_hl(htt_pdev_handle pdev,
#endif
#ifndef CONFIG_HL_SUPPORT
+static inline int
+htt_rx_offload_msdu_cnt_ll(
+ htt_pdev_handle pdev)
+{
+ return htt_rx_ring_elems(pdev);
+}
+
static int
htt_rx_offload_msdu_pop_ll(htt_pdev_handle pdev,
qdf_nbuf_t offload_deliver_msg,
@@ -2995,6 +3009,10 @@ int (*htt_rx_frag_pop)(htt_pdev_handle pdev,
uint32_t *msdu_count);
int
+(*htt_rx_offload_msdu_cnt)(
+ htt_pdev_handle pdev);
+
+int
(*htt_rx_offload_msdu_pop)(htt_pdev_handle pdev,
qdf_nbuf_t offload_deliver_msg,
int *vdev_id,
@@ -3671,6 +3689,7 @@ int htt_rx_attach(struct htt_pdev_t *pdev)
pdev->rx_ring.base_paddr = 0;
htt_rx_amsdu_pop = htt_rx_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;
@@ -3816,6 +3835,7 @@ int htt_rx_attach(struct htt_pdev_t *pdev)
if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
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;
diff --git a/core/dp/htt/htt_t2h.c b/core/dp/htt/htt_t2h.c
index 36588897dfe8..cde66d960af4 100644
--- a/core/dp/htt/htt_t2h.c
+++ b/core/dp/htt/htt_t2h.c
@@ -208,7 +208,7 @@ static void htt_t2h_lp_msg_handler(void *context, qdf_nbuf_t htt_t2h_msg,
}
case HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND:
{
- int msdu_cnt;
+ uint16_t msdu_cnt;
msdu_cnt =
HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_GET(*msg_word);
diff --git a/core/dp/ol/inc/ol_htt_rx_api.h b/core/dp/ol/inc/ol_htt_rx_api.h
index e70e29cefa26..7048f6b9721b 100644
--- a/core/dp/ol/inc/ol_htt_rx_api.h
+++ b/core/dp/ol/inc/ol_htt_rx_api.h
@@ -665,6 +665,15 @@ extern int
uint32_t *msdu_count);
/**
+ * @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/dp/ol/inc/ol_txrx_htt_api.h b/core/dp/ol/inc/ol_txrx_htt_api.h
index 2636fd94e0b3..4657fca58124 100644
--- a/core/dp/ol/inc/ol_txrx_htt_api.h
+++ b/core/dp/ol/inc/ol_txrx_htt_api.h
@@ -419,7 +419,7 @@ void ol_rx_frag_indication_handler(ol_txrx_pdev_handle pdev,
*/
void
ol_rx_offload_deliver_ind_handler(ol_txrx_pdev_handle pdev,
- qdf_nbuf_t msg, int msdu_cnt);
+ qdf_nbuf_t msg, uint16_t msdu_cnt);
/**
* @brief Process a peer map message sent by the target.
diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c
index e4d95713e795..d37e97e80b48 100644
--- a/core/dp/txrx/ol_rx.c
+++ b/core/dp/txrx/ol_rx.c
@@ -917,7 +917,7 @@ ol_rx_inspect(struct ol_txrx_vdev_t *vdev,
void
ol_rx_offload_deliver_ind_handler(ol_txrx_pdev_handle pdev,
- qdf_nbuf_t msg, int msdu_cnt)
+ qdf_nbuf_t msg, uint16_t msdu_cnt)
{
int vdev_id, peer_id, tid;
qdf_nbuf_t head_buf, tail_buf, buf;
@@ -925,6 +925,17 @@ ol_rx_offload_deliver_ind_handler(ol_txrx_pdev_handle pdev,
uint8_t fw_desc;
htt_pdev_handle htt_pdev = pdev->htt_pdev;
+ if (msdu_cnt > htt_rx_offload_msdu_cnt(htt_pdev)) {
+ ol_txrx_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,
&tid, &fw_desc, &head_buf, &tail_buf)) {