From 0b2054b3c5c77aaaf0c4a6b7a9133b5b9c2471a5 Mon Sep 17 00:00:00 2001 From: sheenam monga Date: Thu, 2 May 2019 14:17:31 +0530 Subject: [PATCH] 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 --- .../tdls/core/src/wlan_tdls_cmds_process.c | 25 +++++-------------- components/tdls/core/src/wlan_tdls_ct.c | 18 ++++++------- components/tdls/core/src/wlan_tdls_mgmt.c | 12 ++++----- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/components/tdls/core/src/wlan_tdls_cmds_process.c b/components/tdls/core/src/wlan_tdls_cmds_process.c index 1dc706292168..0a665b1cdfc2 100644 --- a/components/tdls/core/src/wlan_tdls_cmds_process.c +++ b/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); diff --git a/components/tdls/core/src/wlan_tdls_ct.c b/components/tdls/core/src/wlan_tdls_ct.c index a64bbe201bcb..c076d2086766 100644 --- a/components/tdls/core/src/wlan_tdls_ct.c +++ b/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; } diff --git a/components/tdls/core/src/wlan_tdls_mgmt.c b/components/tdls/core/src/wlan_tdls_mgmt.c index b2eeb760765c..0d35db5fdd64 100644 --- a/components/tdls/core/src/wlan_tdls_mgmt.c +++ b/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);