From d74e1fdc5fc0932e01248a1dbb45e76baafccebf Mon Sep 17 00:00:00 2001 From: sheenam monga Date: Mon, 20 May 2019 16:31:44 +0530 Subject: [PATCH] qcacmn: Fix bss peer use after free in stats 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 for stats 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: I3690f1309cbc7643ed55d8e903814b06f9d8755f CRs-Fixed: 2454080 --- os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c | 8 ++++++-- umac/cmn_services/crypto/src/wlan_crypto_global_api.c | 2 +- umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index 3b4d0e7e9cd0..77e40eade06a 100644 --- a/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/os_if/linux/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -254,13 +254,15 @@ int wlan_cfg80211_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev, info.u.get_tx_power_cb = get_tx_power_cb; info.vdev_id = wlan_vdev_get_id(vdev); info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)); - peer = wlan_vdev_get_bsspeer(vdev); + peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID); if (!peer) { ret = -EINVAL; goto peer_is_null; } qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE); + wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); + status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_CONNECTION_TX_POWER, &info); @@ -506,7 +508,7 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, info.u.get_station_stats_cb = get_station_stats_cb; info.vdev_id = wlan_vdev_get_id(vdev); info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)); - peer = wlan_vdev_get_bsspeer(vdev); + peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CP_STATS_ID); if (!peer) { cfg80211_err("peer is null"); *errno = -EINVAL; @@ -514,6 +516,8 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, } qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE); + wlan_objmgr_peer_release_ref(peer, WLAN_CP_STATS_ID); + status = ucfg_mc_cp_stats_send_stats_request(vdev, TYPE_STATION_STATS, &info); if (QDF_IS_STATUS_ERROR(status)) { diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index a95c417290be..53ff4fab8a04 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -649,7 +649,7 @@ QDF_STATUS wlan_crypto_setkey(struct wlan_objmgr_vdev *vdev, peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_CRYPTO_ID); if (!peer) { - crypto_err("peer %pK failed", peer); + crypto_err("peer NULL"); if (IS_MGMT_CIPHER(req_key->type)) { crypto_priv->igtk_key[igtk_idx] = NULL; crypto_priv->igtk_key_type diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h index 952cd01a4139..7a1d4ec3c51f 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h @@ -1406,7 +1406,9 @@ static inline void wlan_vdev_set_bsspeer(struct wlan_objmgr_vdev *vdev, * wlan_vdev_get_bsspeer() - get bss peer * @vdev: VDEV object * - * API to get the BSS peer of VDEV + * API to get the BSS peer of VDEV, wlan_objmgr_vdev_try_get_bsspeer API + * preferred to use outside obj manager to take and handle ref count of + * bss_peer with ref debug ID. * * Return: * @peer: BSS peer pointer