소스 검색

qcacld-3.0: Fix bss peer use after free in TDLS

wlan_vdev_get_bsspeer() return bss peer without taking the ref count
of the peer and thus if peer is deleted after wlan_vdev_get_bsspeer()
returns a valid peer, the caller will have stale entry of the peer.
Stale entry of peer can lead to Assert.

Use wlan_objmgr_vdev_try_get_bsspeer API in TDLS to get the BSS peer
which increment the refcount if peer is valid. With this the peer
won't be deleted till the caller release the ref count of the peer.

Change-Id: I9dc26771a0e8dadf75898c94bff5d4b8fb8a88d5
CRs-Fixed: 2445795
sheenam monga 6 년 전
부모
커밋
0b2054b3c5
3개의 변경된 파일20개의 추가작업 그리고 35개의 파일을 삭제
  1. 6 19
      components/tdls/core/src/wlan_tdls_cmds_process.c
  2. 8 10
      components/tdls/core/src/wlan_tdls_ct.c
  3. 6 6
      components/tdls/core/src/wlan_tdls_mgmt.c

+ 6 - 19
components/tdls/core/src/wlan_tdls_cmds_process.c

@@ -150,17 +150,12 @@ static QDF_STATUS tdls_pe_add_peer(struct tdls_add_peer_request *req)
 	addstareq->transaction_id = 0;
 
 	addstareq->session_id = wlan_vdev_get_id(vdev);
-	peer = wlan_vdev_get_bsspeer(vdev);
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
 	if (!peer) {
 		tdls_err("bss peer is NULL");
 		status = QDF_STATUS_E_INVAL;
 		goto error;
 	}
-	status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_NB_ID);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		tdls_err("can't get bss peer");
-		goto error;
-	}
 	wlan_peer_obj_lock(peer);
 	qdf_mem_copy(addstareq->bssid.bytes,
 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
@@ -217,17 +212,13 @@ QDF_STATUS tdls_pe_del_peer(struct tdls_del_peer_request *req)
 	delstareq->transaction_id = 0;
 
 	delstareq->session_id = wlan_vdev_get_id(vdev);
-	peer = wlan_vdev_get_bsspeer(vdev);
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
 	if (!peer) {
 		tdls_err("bss peer is NULL");
 		status = QDF_STATUS_E_INVAL;
 		goto error;
 	}
-	status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_NB_ID);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		tdls_err("can't get bss peer");
-		goto error;
-	}
+
 	wlan_peer_obj_lock(peer);
 	qdf_mem_copy(delstareq->bssid.bytes,
 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
@@ -287,17 +278,12 @@ static QDF_STATUS tdls_pe_update_peer(struct tdls_update_peer_request *req)
 	addstareq->transaction_id = 0;
 
 	addstareq->session_id = wlan_vdev_get_id(vdev);
-	peer = wlan_vdev_get_bsspeer(vdev);
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
 	if (!peer) {
 		tdls_err("bss peer is NULL");
 		status = QDF_STATUS_E_INVAL;
 		goto error;
 	}
-	status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_NB_ID);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		tdls_err("can't get bss peer");
-		goto error;
-	}
 	wlan_peer_obj_lock(peer);
 	qdf_mem_copy(addstareq->bssid.bytes,
 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
@@ -1613,7 +1599,7 @@ tdls_update_uapsd(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev,
 		return QDF_STATUS_SUCCESS;
 	}
 	vdev_id = wlan_vdev_get_id(vdev);
-	bsspeer = wlan_vdev_get_bsspeer(vdev);
+	bsspeer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_SB_ID);
 	if (!bsspeer) {
 		tdls_err("bss peer is NULL");
 		return QDF_STATUS_E_FAILURE;
@@ -1622,6 +1608,7 @@ tdls_update_uapsd(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev,
 	qdf_mem_copy(macaddr,
 		     wlan_peer_get_macaddr(bsspeer), QDF_MAC_ADDR_SIZE);
 	wlan_vdev_obj_unlock(vdev);
+	wlan_objmgr_peer_release_ref(bsspeer, WLAN_TDLS_SB_ID);
 
 	tdls_debug("TDLS uapsd id %d, srvc %d, sus %d, dir %d psb %d delay %d",
 		   sta_id, srvc_int, sus_int, dir, psb, delay_interval);

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

@@ -32,15 +32,14 @@ bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev)
 	struct wlan_objmgr_peer *peer;
 	bool is_authenticated = false;
 
-	peer = wlan_vdev_get_bsspeer(vdev);
-
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
 	if (!peer) {
 		tdls_err("peer is null");
 		return false;
 	}
 
 	is_authenticated = wlan_peer_mlme_get_auth_state(peer);
-
+	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_NB_ID);
 	return is_authenticated;
 }
 
@@ -1119,13 +1118,11 @@ QDF_STATUS tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev *vdev,
 	struct scheduler_msg msg = {0};
 	QDF_STATUS status;
 
-	peer = wlan_vdev_get_bsspeer(vdev);
-	if (!peer)
-		return QDF_STATUS_E_FAILURE;
-
-	if (QDF_STATUS_SUCCESS !=
-	    wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_SB_ID))
+	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_SB_ID);
+	if (!peer) {
+		tdls_err("bss peer is null");
 		return QDF_STATUS_E_FAILURE;
+	}
 
 	del_msg = qdf_mem_malloc(sizeof(*del_msg));
 	if (!del_msg) {
@@ -1137,6 +1134,8 @@ QDF_STATUS tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev *vdev,
 	qdf_mem_copy(del_msg->bssid.bytes,
 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
 
+	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
+
 	del_msg->msg_type = tdls_soc->tdls_del_all_peers;
 	del_msg->msg_len = (uint16_t) sizeof(*del_msg);
 
@@ -1157,7 +1156,6 @@ QDF_STATUS tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev *vdev,
 		qdf_mem_free(del_msg);
 	}
 
-	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
 	return status;
 }
 

+ 6 - 6
components/tdls/core/src/wlan_tdls_mgmt.c

@@ -279,10 +279,10 @@ static QDF_STATUS tdls_activate_send_mgmt_request(
 	tdls_mgmt_req->responder = action_req->tdls_mgmt.responder;
 	tdls_mgmt_req->peer_capability = action_req->tdls_mgmt.peer_capability;
 
-	peer = wlan_vdev_get_bsspeer(action_req->vdev);
-
-	status =  wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_SB_ID);
-	if (QDF_IS_STATUS_ERROR(status)) {
+	peer = wlan_objmgr_vdev_try_get_bsspeer(action_req->vdev,
+						WLAN_TDLS_SB_ID);
+	if (!peer) {
+		tdls_err("bss peer is null");
 		qdf_mem_free(tdls_mgmt_req);
 		goto release_cmd;
 	}
@@ -290,6 +290,8 @@ static QDF_STATUS tdls_activate_send_mgmt_request(
 	qdf_mem_copy(tdls_mgmt_req->bssid.bytes,
 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
 
+	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
+
 	qdf_mem_copy(tdls_mgmt_req->peer_mac.bytes,
 		     action_req->tdls_mgmt.peer_mac.bytes, QDF_MAC_ADDR_SIZE);
 
@@ -321,8 +323,6 @@ static QDF_STATUS tdls_activate_send_mgmt_request(
 	if (QDF_IS_STATUS_ERROR(status))
 		qdf_mem_free(tdls_mgmt_req);
 
-	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
-
 release_cmd:
 	/*update tdls nss infornation based on action code */
 	tdls_reset_nss(tdls_soc_obj, action_req->chk_frame.action_code);