Browse Source

qcacmn: Fix skb memory leak in RX REO error path

If host receive REO error code 0 - NULL REO queue descriptor from
REO exception ring, it will be raw data and likely spread across
multiple msdu buffers for amsdu packets. in this case, only the
last msdu will contain the valid rx msdu length, but currently host
use msdu length from head skb (msdu length is 0), then the sub-skbs
followed after head skb will be leaked as following,
(1) dp_rx_sg_create() fail to add sub-skbs into frag_list of head_skb,
then sub-skbs still exist in head_skb->next.
(2) As peer_id is not valid, dp_rx_null_q_desc_handle()->
dp_rx_chain_msdus_be() will configure head_skb->next = NULL during
DP_RX_LIST_APPEND, then all sub-skbs get leaked.

Get msdu length from last skb and overwrite it in head_skb, then
dp_rx_sg_create() will process all skbs correctly.

Change-Id: I1953afb4e3b44450ff5e8269ef0f4f0c38e1d446
CRs-Fixed: 3476534
Jinwei Chen 2 years ago
parent
commit
58b1c384df
1 changed files with 12 additions and 1 deletions
  1. 12 1
      dp/wifi3.0/dp_rx_err.c

+ 12 - 1
dp/wifi3.0/dp_rx_err.c

@@ -1114,8 +1114,10 @@ more_msdu_link_desc:
 		DP_RX_LIST_APPEND(head_nbuf, tail_nbuf, nbuf);
 
 		if (qdf_unlikely(msdu_list.msdu_info[i].msdu_flags &
-				 HAL_MSDU_F_MSDU_CONTINUATION))
+				 HAL_MSDU_F_MSDU_CONTINUATION)) {
+			qdf_nbuf_set_rx_chfrag_cont(nbuf, 1);
 			continue;
+		}
 
 		if (dp_rx_buffer_pool_refill(soc, head_nbuf,
 					     rx_desc_pool_id)) {
@@ -1180,6 +1182,15 @@ more_msdu_link_desc:
 		rx_tlv_hdr_last = qdf_nbuf_data(tail_nbuf);
 
 		if (qdf_unlikely(head_nbuf != tail_nbuf)) {
+			/*
+			 * For SG case, only the length of last skb is valid
+			 * as HW only populate the msdu_len for last msdu
+			 * in rx link descriptor, use the length from
+			 * last skb to overwrite the head skb for further
+			 * SG processing.
+			 */
+			QDF_NBUF_CB_RX_PKT_LEN(head_nbuf) =
+					QDF_NBUF_CB_RX_PKT_LEN(tail_nbuf);
 			nbuf = dp_rx_sg_create(soc, head_nbuf);
 			qdf_nbuf_set_is_frag(nbuf, 1);
 			DP_STATS_INC(soc, rx.err.reo_err_oor_sg_count, 1);