Browse Source

qcacmn: fix use after free in WDS aging timer

In case of pdev attach failure reset pdev reference in
soc->pdev_list to NULL before free to avoid use after
free

Also initialize WDS aging timer only when ast hash is
allocated

Change-Id: I6a406bd94aa46a95d9e5bb970ae83b3dfde29d0a
Chaithanya Garrepalli 4 years ago
parent
commit
76d4ea4287
2 changed files with 11 additions and 13 deletions
  1. 1 13
      dp/wifi3.0/dp_main.c
  2. 10 0
      dp/wifi3.0/dp_peer.c

+ 1 - 13
dp/wifi3.0/dp_main.c

@@ -3150,15 +3150,6 @@ void dp_link_desc_ring_replenish(struct dp_soc *soc, uint32_t mac_id)
 #endif /* CONFIG_WIFI_EMULATION_WIFI_3_0 */
 #endif /* IPA_OFFLOAD */
 
-#ifndef FEATURE_WDS
-static void dp_soc_wds_attach(struct dp_soc *soc)
-{
-}
-
-static void dp_soc_wds_detach(struct dp_soc *soc)
-{
-}
-#endif
 /*
  * dp_soc_reset_ring_map() - Reset cpu ring map
  * @soc: Datapath soc handler
@@ -4386,6 +4377,7 @@ fail3:
 fail2:
 	wlan_cfg_pdev_detach(pdev->wlan_cfg_ctx);
 fail1:
+	soc->pdev_list[pdev_id] = NULL;
 	qdf_mem_free(pdev);
 fail0:
 	return QDF_STATUS_E_FAILURE;
@@ -4816,8 +4808,6 @@ static void dp_soc_deinit(void *txrx_soc)
 
 	qdf_nbuf_queue_free(&soc->htt_stats.msg);
 
-	dp_soc_wds_detach(soc);
-
 	qdf_spinlock_destroy(&soc->rx.defrag.defrag_lock);
 
 	qdf_spinlock_destroy(&soc->vdev_map_lock);
@@ -12392,8 +12382,6 @@ void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle,
 
 	qdf_atomic_set(&soc->cmn_init_done, 1);
 
-	dp_soc_wds_attach(soc);
-
 	qdf_nbuf_queue_init(&soc->htt_stats.msg);
 
 	qdf_spinlock_create(&soc->ast_lock);

+ 10 - 0
dp/wifi3.0/dp_peer.c

@@ -67,6 +67,14 @@ dp_peer_ast_free_in_unmap_supported(struct dp_soc *soc,
 {
 	return false;
 }
+
+static void dp_soc_wds_attach(struct dp_soc *soc)
+{
+}
+
+static void dp_soc_wds_detach(struct dp_soc *soc)
+{
+}
 #endif
 
 static inline void
@@ -1831,6 +1839,7 @@ int dp_peer_find_attach(struct dp_soc *soc)
 		return 1;
 	}
 
+	dp_soc_wds_attach(soc);
 	return 0; /* success */
 }
 
@@ -2166,6 +2175,7 @@ dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id,
 void
 dp_peer_find_detach(struct dp_soc *soc)
 {
+	dp_soc_wds_detach(soc);
 	dp_peer_find_map_detach(soc);
 	dp_peer_find_hash_detach(soc);
 	dp_peer_ast_hash_detach(soc);