Browse Source

qcacmn: Avoid peer/vdev/pdev spin lock used before init

qdf_spinlock_create(&peer->peer_lock) is called after
wlan_objmgr_psoc_peer_attach and wlan_objmgr_vdev_peer_attach in
wlan_objmgr_peer_obj_create.

In mgmt rx handler, peer is accessed and peer_lock is acquired
before peer_lock initialized in race condition case, spinlock
bad magic issue will happen

Initialize the peer spin lock before peer attaching to avoid the
race condition

Fix same things for vdev and pdev objects

Change-Id: I4cc9d281f8c9efa9de246747641804d985b4653c
CRs-Fixed: 2198193
Zhu Jianmin 7 years ago
parent
commit
8a8fa10854

+ 3 - 2
umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c

@@ -111,17 +111,18 @@ struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create(
 		return NULL;
 	}
 	pdev->obj_state = WLAN_OBJ_STATE_ALLOCATED;
+	/* Initialize PDEV spinlock */
+	qdf_spinlock_create(&pdev->pdev_lock);
 	/* Attach PDEV with PSOC */
 	if (wlan_objmgr_psoc_pdev_attach(psoc, pdev)
 				!= QDF_STATUS_SUCCESS) {
 		obj_mgr_err("pdev psoc attach failed");
+		qdf_spinlock_destroy(&pdev->pdev_lock);
 		qdf_mem_free(pdev);
 		return NULL;
 	}
 	/* Save PSOC object pointer in PDEV */
 	wlan_pdev_set_psoc(pdev, psoc);
-	/* Initialize PDEV spinlock */
-	qdf_spinlock_create(&pdev->pdev_lock);
 	/* Initialize PDEV's VDEV list, assign default values */
 	qdf_list_create(&pdev->pdev_objmgr.wlan_vdev_list,
 			WLAN_UMAC_PDEV_MAX_VDEVS);

+ 4 - 1
umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c

@@ -183,6 +183,8 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
 	wlan_peer_mlme_set_state(peer, WLAN_INIT_STATE);
 	wlan_peer_mlme_reset_seq_num(peer);
 	peer->peer_objmgr.print_cnt = 0;
+
+	qdf_spinlock_create(&peer->peer_lock);
 	/* Attach peer to psoc, psoc maintains the node table for the device */
 	if (wlan_objmgr_psoc_peer_attach(psoc, peer) !=
 					QDF_STATUS_SUCCESS) {
@@ -190,6 +192,7 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
 		"Peer(%02x:%02x:%02x:%02x:%02x:%02x) PSOC attach failure",
 				macaddr[0], macaddr[1], macaddr[2],
 				macaddr[3], macaddr[4], macaddr[5]);
+		qdf_spinlock_destroy(&peer->peer_lock);
 		qdf_mem_free(peer);
 		return NULL;
 	}
@@ -202,10 +205,10 @@ struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create(
 				macaddr[3], macaddr[4], macaddr[5]);
 		/* if attach fails, detach from psoc table before free */
 		wlan_objmgr_psoc_peer_detach(psoc, peer);
+		qdf_spinlock_destroy(&peer->peer_lock);
 		qdf_mem_free(peer);
 		return NULL;
 	}
-	qdf_spinlock_create(&peer->peer_lock);
 	/* Increment ref count for BSS peer, so that BSS peer deletes last*/
 	if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP)
 				    || (type == WLAN_PEER_P2P_CLI))

+ 4 - 2
umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c

@@ -163,6 +163,8 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
 		return NULL;
 	}
 
+	/* Initialize spinlock */
+	qdf_spinlock_create(&vdev->vdev_lock);
 	/* Attach VDEV to PSOC VDEV's list */
 	if (wlan_objmgr_psoc_vdev_attach(psoc, vdev) !=
 				QDF_STATUS_SUCCESS) {
@@ -170,6 +172,7 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
 					vdev->vdev_objmgr.vdev_id);
 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
 		qdf_mem_free(vdev->vdev_mlme.des_chan);
+		qdf_spinlock_destroy(&vdev->vdev_lock);
 		qdf_mem_free(vdev);
 		return NULL;
 	}
@@ -183,11 +186,10 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
 		wlan_objmgr_psoc_vdev_detach(psoc, vdev);
 		qdf_mem_free(vdev->vdev_mlme.bss_chan);
 		qdf_mem_free(vdev->vdev_mlme.des_chan);
+		qdf_spinlock_destroy(&vdev->vdev_lock);
 		qdf_mem_free(vdev);
 		return NULL;
 	}
-	/* Initialize spinlock */
-	qdf_spinlock_create(&vdev->vdev_lock);
 	/* set opmode */
 	wlan_vdev_mlme_set_opmode(vdev, params->opmode);
 	/* set MAC address */