From 90e1136afba0c8e92a19dd83895d4ce939777ff7 Mon Sep 17 00:00:00 2001 From: Yeshwanth Sriram Guntuka Date: Mon, 29 Jun 2020 17:01:55 +0530 Subject: [PATCH] qcacmn: Decrement peer ref cnt after dp_rx_deliver_to_stack Ths issue scenario is that valid peer is fetched from peer_id in dp_rx_process and peer ref count is released prior to invoking dp_rx_deliver_to_stack. In parallel, the peer is freed in a different context. This results in use after free within dp_rx_check_delivery_to_stack since stale peer is dereferenced to update stats. Fix is to decrement peer ref cnt after dp_rx_deliver_to_stack Change-Id: I145247f7795f926faba66c05927fdae0599f0cad CRs-Fixed: 2720396 --- dp/wifi3.0/dp_rx.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 43fe14e707..149f6fed8b 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -2247,7 +2247,13 @@ done: tid = qdf_nbuf_get_tid_val(nbuf); peer_id = QDF_NBUF_CB_RX_PEER_ID(nbuf); - peer = dp_peer_find_by_id(soc, peer_id); + + if (qdf_unlikely(!peer)) { + peer = dp_peer_find_by_id(soc, peer_id); + } else if (peer && peer->peer_id != peer_id) { + dp_peer_unref_del_find_by_id(peer); + peer = dp_peer_find_by_id(soc, peer_id); + } if (peer) { QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) = false; @@ -2272,7 +2278,6 @@ done: qdf_nbuf_free(nbuf); nbuf = next; DP_STATS_INC(soc, rx.err.invalid_vdev, 1); - dp_peer_unref_del_find_by_id(peer); continue; } @@ -2360,7 +2365,6 @@ done: dp_info_rl("scatter msdu len %d, dropped", msdu_len); nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } } else { @@ -2382,7 +2386,6 @@ done: DP_STATS_INC(peer, rx.multipass_rx_pkt_drop, 1); qdf_nbuf_free(nbuf); nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } } @@ -2396,7 +2399,6 @@ done: qdf_nbuf_free(nbuf); /* Statistics */ nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } @@ -2409,7 +2411,6 @@ done: DP_STATS_INC(peer, rx.nawds_mcast_drop, 1); qdf_nbuf_free(nbuf); nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } @@ -2438,7 +2439,6 @@ done: qdf_nbuf_free(nbuf); nbuf = next; - dp_peer_unref_del_find_by_id(peer); continue; } dp_rx_fill_mesh_stats(vdev, nbuf, rx_tlv_hdr, peer); @@ -2465,7 +2465,6 @@ done: qdf_nbuf_free(nbuf); nbuf = next; DP_STATS_INC(soc, rx.err.invalid_sa_da_idx, 1); - dp_peer_unref_del_find_by_id(peer); continue; } /* WDS Source Port Learning */ @@ -2484,7 +2483,6 @@ done: nbuf, msdu_metadata)) { nbuf = next; - dp_peer_unref_del_find_by_id(peer); tid_stats->intrabss_cnt++; continue; /* Get next desc */ } @@ -2500,7 +2498,6 @@ done: tid_stats->delivered_to_stack++; nbuf = next; - dp_peer_unref_del_find_by_id(peer); } if (qdf_likely(deliver_list_head)) { @@ -2519,6 +2516,9 @@ done: } } + if (qdf_likely(peer)) + dp_peer_unref_del_find_by_id(peer); + if (dp_rx_enable_eol_data_check(soc) && rx_bufs_used) { if (quota) { num_pending =