Ver Fonte

qcacld-3.0: Stop TDLS peer timers upon STA disconnection

TDLS peer_update_timer and peer discovery timers are not stopped
upon sta disconnect.
So while the handler is invoked upon timer expiry, the
vdev could have been already deleted. This could result in
null pointer dereference of vdev while trying to get
TDLS vdev objects.

Since the timer is not required upon sta disconnection and
peer will already be deleted, stop the timer upon STA
disconnection itself, instead of doing it during vdev
destroy.

Change-Id: I3c405b3e7b57d25a7d1afbf6c93476271a29a6b8
CRs-Fixed: 3673078
Pragaspathi Thilagaraj há 1 ano atrás
pai
commit
fd744a4b58

+ 10 - 6
components/tdls/core/src/wlan_tdls_ct.c

@@ -99,12 +99,12 @@ void tdls_discovery_timeout_peer_cb(void *user_data)
 	uint8_t *mac;
 	bool unforce = true;
 
-	if (!user_data) {
-		tdls_err("discovery time out data is null");
+	vdev = user_data;
+	if (!vdev) {
+		tdls_err("discovery time out vdev is null");
 		return;
 	}
 
-	vdev = (struct wlan_objmgr_vdev *)user_data;
 	tdls_soc = wlan_vdev_get_tdls_soc_obj(vdev);
 	if (!tdls_soc)
 		return;
@@ -251,10 +251,12 @@ void tdls_implicit_disable(struct tdls_vdev_priv_obj *tdls_vdev)
  */
 void tdls_implicit_enable(struct tdls_vdev_priv_obj *tdls_vdev)
 {
-	tdls_debug("Enable Implicit TDLS");
 	if (!tdls_vdev)
 		return;
 
+	tdls_debug("vdev:%d Enable Implicit TDLS",
+		   wlan_vdev_get_id(tdls_vdev->vdev));
+
 	tdls_peer_reset_discovery_processed(tdls_vdev);
 	tdls_reset_tx_rx(tdls_vdev);
 	/* TODO check whether tdls power save prohibited */
@@ -1062,6 +1064,7 @@ void tdls_ct_handler(void *user_data)
 {
 	struct wlan_objmgr_vdev *vdev;
 	struct wlan_objmgr_vdev *link_vdev;
+	QDF_STATUS status;
 
 	if (!user_data)
 		return;
@@ -1072,8 +1075,9 @@ void tdls_ct_handler(void *user_data)
 
 	link_vdev = tdls_mlo_get_tdls_link_vdev(vdev);
 	if (link_vdev) {
-		if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_TDLS_NB_ID) ==
-		    QDF_STATUS_SUCCESS) {
+		status = wlan_objmgr_vdev_try_get_ref(link_vdev,
+						      WLAN_TDLS_NB_ID);
+		if (QDF_IS_STATUS_SUCCESS(status)) {
 			tdls_ct_process_handler(link_vdev);
 			wlan_objmgr_vdev_release_ref(link_vdev,
 						     WLAN_TDLS_NB_ID);

+ 18 - 9
components/tdls/core/src/wlan_tdls_main.c

@@ -599,12 +599,12 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	if (!msg || !msg->bodyptr) {
-		tdls_err("msg: 0x%pK", msg);
+		tdls_err("msg %s is NULL", !msg ? "" : "body ptr");
 		QDF_ASSERT(0);
 		return QDF_STATUS_E_NULL_VALUE;
 	}
-	tdls_debug("TDLS process command: %s(%d)",
-		   tdls_get_cmd_type_str(msg->type), msg->type);
+
+	tdls_debug(" %s(%d)", tdls_get_cmd_type_str(msg->type), msg->type);
 
 	switch (msg->type) {
 	case TDLS_CMD_TX_ACTION:
@@ -735,9 +735,14 @@ QDF_STATUS tdls_process_evt(struct scheduler_msg *msg)
 }
 
 void tdls_timer_restart(struct wlan_objmgr_vdev *vdev,
-				 qdf_mc_timer_t *timer,
-				 uint32_t expiration_time)
+			qdf_mc_timer_t *timer, uint32_t expiration_time)
 {
+	if (!wlan_cm_is_vdev_connected(vdev)) {
+		tdls_debug("vdev:%d is not connected. Can't restart timer",
+			   wlan_vdev_get_id(vdev));
+		return;
+	}
+
 	if (QDF_TIMER_STATE_RUNNING !=
 	    qdf_mc_timer_get_current_state(timer))
 		qdf_mc_timer_start(timer, expiration_time);
@@ -752,7 +757,7 @@ void tdls_timer_restart(struct wlan_objmgr_vdev *vdev,
 static void tdls_monitor_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
 {
 	if (!wlan_vdev_mlme_is_mlo_vdev(tdls_vdev->vdev))
-		qdf_mc_timer_stop(&tdls_vdev->peer_discovery_timer);
+		qdf_mc_timer_stop_sync(&tdls_vdev->peer_discovery_timer);
 }
 
 /**
@@ -780,7 +785,7 @@ static void tdls_peer_idle_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
 			curr_peer = qdf_container_of(p_node, struct tdls_peer,
 						     node);
 			if (curr_peer->is_peer_idle_timer_initialised)
-				qdf_mc_timer_stop(&curr_peer->peer_idle_timer);
+				qdf_mc_timer_stop_sync(&curr_peer->peer_idle_timer);
 			status = qdf_list_peek_next(head, p_node, &p_node);
 		}
 	}
@@ -795,7 +800,8 @@ static void tdls_peer_idle_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
  */
 static void tdls_ct_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
 {
-	qdf_mc_timer_stop(&tdls_vdev->peer_update_timer);
+	qdf_mc_timer_stop_sync(&tdls_vdev->peer_update_timer);
+
 	tdls_peer_idle_timers_stop(tdls_vdev);
 }
 
@@ -807,6 +813,7 @@ static void tdls_ct_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
  */
 void tdls_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
 {
+	tdls_debug("Stop TDLS timers");
 	tdls_monitor_timers_stop(tdls_vdev);
 	tdls_ct_timers_stop(tdls_vdev);
 }
@@ -1633,7 +1640,9 @@ tdls_process_sta_disconnect(struct tdls_sta_notify_params *notify)
 	tdls_send_update_to_fw(tdls_vdev_obj, tdls_soc_obj, false,
 			       false, false, notify->session_id);
 
-	/* If concurrency is not marked, then we have to
+	tdls_timers_stop(tdls_vdev_obj);
+	/*
+	 * If concurrency is not marked, then we have to
 	 * check, whether TDLS could be enabled in the
 	 * system after this disassoc event.
 	 */