mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
qcacmn: Fix memory leak in get_station_stats_cb
There is memory leak in get_station_stats_cb: priv->vdev_summary_stats, priv->vdev_chain_rssi, priv->peer_adv_stats. But the “request” is not leaked, that means the “.dealloc” should be called. The suspect is the get_station_stats_cb was called two times with same cookie (request) before the "request" was freed, that caused the priv->vdev_summary_stats and the others two member of "priv" were overwritten, and then memory leaks. From the cp stats components there are multiple places to call ucfg_mc_cp_stats_reset_pending_req to reset the unused pending.req(has a cookie) to zero. The zero cookie may be used in again. Change the ucfg_mc_cp_stats_reset_pending_req API to do atomic operation of "reset" and "get" last pending request. Change-Id: I5efb7efec4da1edc0aab33b940dc126012a3f12e CRs-Fixed: 2622444
This commit is contained in:
parent
28432f1195
commit
4f2b0feab6
4 changed files with 45 additions and 14 deletions
|
|
@ -461,6 +461,12 @@ static void get_station_stats_cb(struct stats_event *ev, void *cookie)
|
|||
summary_size, rssi_size);
|
||||
goto station_stats_cb_fail;
|
||||
}
|
||||
if (priv->vdev_summary_stats || priv->vdev_chain_rssi ||
|
||||
priv->peer_adv_stats) {
|
||||
osif_err("invalid context cookie %pK request %pK",
|
||||
cookie, request);
|
||||
goto station_stats_cb_fail;
|
||||
}
|
||||
|
||||
priv->vdev_summary_stats = qdf_mem_malloc(summary_size);
|
||||
if (!priv->vdev_summary_stats)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
|
|
@ -158,11 +158,17 @@ QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc,
|
|||
* ucfg_mc_cp_stats_reset_pending_req() - API to reset pending request
|
||||
* @psoc: pointer to psoc object
|
||||
* @type: request to update
|
||||
* @last_req: last request
|
||||
* @pending: pending request present
|
||||
*
|
||||
* The function is an atomic operation of "reset" and "get" last request.
|
||||
*
|
||||
* Return: status of operation
|
||||
*/
|
||||
QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc,
|
||||
enum stats_req_type type);
|
||||
enum stats_req_type type,
|
||||
struct request_info *last_req,
|
||||
bool *pending);
|
||||
|
||||
/**
|
||||
* ucfg_mc_cp_stats_get_pending_req() - API to get pending request
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
|
|||
struct wlan_objmgr_vdev *vdev = NULL;
|
||||
struct pdev_mc_cp_stats *pdev_mc_stats;
|
||||
struct pdev_cp_stats *pdev_cp_stats_priv;
|
||||
bool pending = false;
|
||||
|
||||
if (!ev->pdev_stats)
|
||||
return;
|
||||
|
|
@ -122,8 +123,10 @@ static void tgt_mc_cp_stats_extract_tx_power(struct wlan_objmgr_psoc *psoc,
|
|||
|
||||
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_CONNECTION_TX_POWER)) {
|
||||
ucfg_mc_cp_stats_reset_pending_req(psoc,
|
||||
TYPE_CONNECTION_TX_POWER);
|
||||
if (last_req.u.get_tx_power_cb)
|
||||
TYPE_CONNECTION_TX_POWER,
|
||||
&last_req,
|
||||
&pending);
|
||||
if (last_req.u.get_tx_power_cb && pending)
|
||||
last_req.u.get_tx_power_cb(max_pwr, last_req.cookie);
|
||||
}
|
||||
end:
|
||||
|
|
@ -465,9 +468,9 @@ static void tgt_mc_cp_stats_extract_peer_stats(struct wlan_objmgr_psoc *psoc,
|
|||
uint32_t i;
|
||||
QDF_STATUS status;
|
||||
struct request_info last_req = {0};
|
||||
bool pending = false;
|
||||
uint32_t selected;
|
||||
|
||||
|
||||
if (is_station_stats)
|
||||
status = ucfg_mc_cp_stats_get_pending_req(psoc,
|
||||
TYPE_STATION_STATS,
|
||||
|
|
@ -542,8 +545,10 @@ complete:
|
|||
|
||||
tgt_mc_cp_stats_extract_peer_extd_stats(psoc, ev);
|
||||
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_PEER_STATS)) {
|
||||
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS);
|
||||
tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req);
|
||||
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_PEER_STATS,
|
||||
&last_req, &pending);
|
||||
if (pending && last_req.u.get_peer_rssi_cb)
|
||||
tgt_mc_cp_stats_prepare_raw_peer_rssi(psoc, &last_req);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -553,6 +558,7 @@ static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
|
|||
{
|
||||
QDF_STATUS status;
|
||||
struct request_info last_req = {0};
|
||||
bool pending = false;
|
||||
|
||||
if (!ev->mib_stats) {
|
||||
cp_stats_debug("no mib stats");
|
||||
|
|
@ -568,8 +574,9 @@ static void tgt_mc_cp_stats_extract_mib_stats(struct wlan_objmgr_psoc *psoc,
|
|||
}
|
||||
|
||||
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_MIB_STATS)) {
|
||||
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS);
|
||||
if (last_req.u.get_mib_stats_cb)
|
||||
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_MIB_STATS,
|
||||
&last_req, &pending);
|
||||
if (last_req.u.get_mib_stats_cb && pending)
|
||||
last_req.u.get_mib_stats_cb(ev, last_req.cookie);
|
||||
}
|
||||
}
|
||||
|
|
@ -857,6 +864,7 @@ static void tgt_mc_cp_stats_extract_station_stats(
|
|||
{
|
||||
QDF_STATUS status;
|
||||
struct request_info last_req = {0};
|
||||
bool pending = false;
|
||||
|
||||
status = ucfg_mc_cp_stats_get_pending_req(psoc,
|
||||
TYPE_STATION_STATS,
|
||||
|
|
@ -876,9 +884,12 @@ static void tgt_mc_cp_stats_extract_station_stats(
|
|||
* reset type_map bit for station stats .
|
||||
*/
|
||||
if (tgt_mc_cp_stats_is_last_event(ev, TYPE_STATION_STATS)) {
|
||||
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS);
|
||||
tgt_mc_cp_stats_prepare_n_send_raw_station_stats(psoc,
|
||||
&last_req);
|
||||
ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS,
|
||||
&last_req,
|
||||
&pending);
|
||||
if (pending && last_req.u.get_station_stats_cb)
|
||||
tgt_mc_cp_stats_prepare_n_send_raw_station_stats(
|
||||
psoc, &last_req);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
|
|
@ -532,7 +532,9 @@ QDF_STATUS ucfg_mc_cp_stats_set_pending_req(struct wlan_objmgr_psoc *psoc,
|
|||
}
|
||||
|
||||
QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc,
|
||||
enum stats_req_type type)
|
||||
enum stats_req_type type,
|
||||
struct request_info *last_req,
|
||||
bool *pending)
|
||||
{
|
||||
struct psoc_mc_cp_stats *psoc_mc_stats;
|
||||
struct psoc_cp_stats *psoc_cp_stats_priv;
|
||||
|
|
@ -550,6 +552,12 @@ QDF_STATUS ucfg_mc_cp_stats_reset_pending_req(struct wlan_objmgr_psoc *psoc,
|
|||
|
||||
wlan_cp_stats_psoc_obj_lock(psoc_cp_stats_priv);
|
||||
psoc_mc_stats = psoc_cp_stats_priv->obj_stats;
|
||||
if (psoc_mc_stats->pending.type_map & (1 << type)) {
|
||||
*last_req = psoc_mc_stats->pending.req[type];
|
||||
*pending = true;
|
||||
} else {
|
||||
*pending = false;
|
||||
}
|
||||
psoc_mc_stats->pending.type_map &= ~(1 << type);
|
||||
qdf_mem_zero(&psoc_mc_stats->pending.req[type],
|
||||
sizeof(psoc_mc_stats->pending.req[type]));
|
||||
|
|
|
|||
Loading…
Reference in a new issue