Explorar o código

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
Yeshwanth Sriram Guntuka %!s(int64=5) %!d(string=hai) anos
pai
achega
90e1136afb
Modificáronse 1 ficheiros con 10 adicións e 10 borrados
  1. 10 10
      dp/wifi3.0/dp_rx.c

+ 10 - 10
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 =