qcacmn: Fix potential memory leak when post scheduler msg in P2P

To avoid potential memory leak, add flush callback for some of P2P
messages, handle post scheduler messages fail case.

Change-Id: If700eba689bb2423ca84fbba08f7434cc75dbd14
CRs-Fixed: 2341756
This commit is contained in:
Wu Gao
2018-10-30 18:43:57 +08:00
committed by nshrivas
vanhempi d89c5d5d6f
commit 43520acbbf
4 muutettua tiedostoa jossa 192 lisäystä ja 46 poistoa

Näytä tiedosto

@@ -429,6 +429,7 @@ static QDF_STATUS p2p_send_noa_to_pe(struct p2p_noa_info *noa_info)
{
struct p2p_noa_attr *noa_attr;
struct scheduler_msg msg = {0};
QDF_STATUS status;
if (!noa_info) {
p2p_err("noa info is null");
@@ -474,11 +475,16 @@ static QDF_STATUS p2p_send_noa_to_pe(struct p2p_noa_info *noa_info)
msg.type = P2P_NOA_ATTR_IND;
msg.bodyval = 0;
msg.bodyptr = noa_attr;
scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_PE, &msg);
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_PE,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(noa_attr);
p2p_err("post msg fail:%d", status);
}
return QDF_STATUS_SUCCESS;
return status;
}
/**
@@ -1044,6 +1050,72 @@ QDF_STATUS p2p_process_evt(struct scheduler_msg *msg)
return status;
}
QDF_STATUS p2p_msg_flush_callback(struct scheduler_msg *msg)
{
struct tx_action_context *tx_action;
if (!msg || !(msg->bodyptr)) {
p2p_err("invalid msg");
return QDF_STATUS_E_INVAL;
}
p2p_debug("flush msg, type:%d", msg->type);
switch (msg->type) {
case P2P_MGMT_TX:
tx_action = (struct tx_action_context *)msg->bodyptr;
qdf_mem_free(tx_action->buf);
qdf_mem_free(tx_action);
break;
default:
qdf_mem_free(msg->bodyptr);
break;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS p2p_event_flush_callback(struct scheduler_msg *msg)
{
struct p2p_noa_event *noa_event;
struct p2p_rx_mgmt_event *rx_mgmt_event;
struct p2p_tx_conf_event *tx_conf_event;
struct p2p_lo_stop_event *lo_stop_event;
if (!msg || !(msg->bodyptr)) {
p2p_err("invalid msg");
return QDF_STATUS_E_INVAL;
}
p2p_debug("flush event, type:%d", msg->type);
switch (msg->type) {
case P2P_EVENT_NOA:
noa_event = (struct p2p_noa_event *)msg->bodyptr;
qdf_mem_free(noa_event->noa_info);
qdf_mem_free(noa_event);
break;
case P2P_EVENT_RX_MGMT:
rx_mgmt_event = (struct p2p_rx_mgmt_event *)msg->bodyptr;
qdf_mem_free(rx_mgmt_event->rx_mgmt);
qdf_mem_free(rx_mgmt_event);
break;
case P2P_EVENT_MGMT_TX_ACK_CNF:
tx_conf_event = (struct p2p_tx_conf_event *)msg->bodyptr;
qdf_mem_free(tx_conf_event);
qdf_nbuf_free(tx_conf_event->nbuf);
break;
case P2P_EVENT_LO_STOPPED:
lo_stop_event = (struct p2p_lo_stop_event *)msg->bodyptr;
qdf_mem_free(lo_stop_event->lo_event);
qdf_mem_free(lo_stop_event);
break;
default:
qdf_mem_free(msg->bodyptr);
break;
}
return QDF_STATUS_SUCCESS;
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
QDF_STATUS p2p_process_lo_stop(
struct p2p_lo_stop_event *lo_stop_event)

Näytä tiedosto

@@ -445,6 +445,26 @@ QDF_STATUS p2p_process_cmd(struct scheduler_msg *msg);
*/
QDF_STATUS p2p_process_evt(struct scheduler_msg *msg);
/**
* p2p_msg_flush_callback() - Callback used to flush P2P messages
* @msg: message information
*
* This callback will be called when scheduler flush some of P2P messages.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_msg_flush_callback(struct scheduler_msg *msg);
/**
* p2p_event_flush_callback() - Callback used to flush P2P events
* @msg: event information
*
* This callback will be called when scheduler flush some of P2P events.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_event_flush_callback(struct scheduler_msg *msg);
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* p2p_process_lo_stop() - Process lo stop event

Näytä tiedosto

@@ -80,6 +80,7 @@ QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_lo_stop_event *lo_stop_event;
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
QDF_STATUS status;
p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
@@ -116,11 +117,18 @@ QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
msg.type = P2P_EVENT_LO_STOPPED;
msg.bodyptr = lo_stop_event;
msg.callback = p2p_process_evt;
msg.flush_callback = p2p_event_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(lo_stop_event->lo_event);
qdf_mem_free(lo_stop_event);
p2p_err("post msg fail:%d", status);
}
scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF, &msg);
return QDF_STATUS_SUCCESS;
return status;
}
#endif /* FEATURE_P2P_LISTEN_OFFLOAD */
@@ -163,7 +171,7 @@ tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc *psoc,
msg.bodyptr = mac_filter_rsp;
msg.callback = p2p_process_evt;
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
if (status != QDF_STATUS_SUCCESS)
if (QDF_IS_STATUS_ERROR(status))
qdf_mem_free(mac_filter_rsp);
return status;
@@ -261,17 +269,18 @@ QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf,
msg.type = P2P_EVENT_MGMT_TX_ACK_CNF;
msg.bodyptr = tx_conf_event;
msg.callback = p2p_process_evt;
msg.flush_callback = p2p_event_flush_callback;
ret = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF, &msg);
if (ret != QDF_STATUS_SUCCESS) {
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(ret)) {
qdf_mem_free(tx_conf_event);
qdf_mem_free(buf);
p2p_err("failed to post message");
return status;
qdf_nbuf_free(buf);
p2p_err("post msg fail:%d", status);
}
return QDF_STATUS_SUCCESS;
return ret;
}
QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
@@ -286,6 +295,7 @@ QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_vdev *vdev;
uint32_t vdev_id;
uint8_t *pdata;
QDF_STATUS status;
p2p_debug("psoc:%pK, peer:%pK, type:%d", psoc, peer, frm_type);
@@ -349,13 +359,19 @@ QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
msg.type = P2P_EVENT_RX_MGMT;
msg.bodyptr = rx_mgmt_event;
msg.callback = p2p_process_evt;
scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF, &msg);
msg.flush_callback = p2p_event_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(rx_mgmt_event->rx_mgmt);
qdf_mem_free(rx_mgmt_event);
p2p_err("post msg fail:%d", status);
}
qdf_nbuf_free(buf);
return QDF_STATUS_SUCCESS;
return status;
}
QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
@@ -364,6 +380,7 @@ QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_noa_event *noa_event;
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
QDF_STATUS status;
p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
@@ -400,9 +417,16 @@ QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
msg.type = P2P_EVENT_NOA;
msg.bodyptr = noa_event;
msg.callback = p2p_process_evt;
scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF, &msg);
msg.flush_callback = p2p_event_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(noa_event->noa_info);
qdf_mem_free(noa_event);
p2p_err("post msg fail:%d", status);
}
return QDF_STATUS_SUCCESS;
return status;
}

Näytä tiedosto

@@ -141,7 +141,7 @@ QDF_STATUS ucfg_p2p_roc_req(struct wlan_objmgr_psoc *soc,
}
status = qdf_idr_alloc(&p2p_soc_obj->p2p_idr, roc_ctx, &id);
if (status != QDF_STATUS_SUCCESS) {
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(roc_ctx);
p2p_err("failed to alloc idr, status %d", status);
return status;
@@ -159,12 +159,18 @@ QDF_STATUS ucfg_p2p_roc_req(struct wlan_objmgr_psoc *soc,
msg.type = P2P_ROC_REQ;
msg.bodyptr = roc_ctx;
msg.callback = p2p_process_cmd;
scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF, &msg);
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(roc_ctx);
qdf_idr_remove(&p2p_soc_obj->p2p_idr, id);
p2p_err("post msg fail:%d", status);
}
p2p_debug("cookie = 0x%llx", *cookie);
return QDF_STATUS_SUCCESS;
return status;
}
QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
@@ -174,6 +180,7 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
struct p2p_soc_priv_obj *p2p_soc_obj;
struct cancel_roc_context *cancel_roc;
void *roc_ctx = NULL;
QDF_STATUS status;
p2p_debug("soc:%pK, cookie:0x%llx", soc, cookie);
@@ -189,8 +196,9 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
return QDF_STATUS_E_FAILURE;
}
if (QDF_STATUS_SUCCESS != qdf_idr_find(&p2p_soc_obj->p2p_idr,
cookie, &roc_ctx)) {
status = qdf_idr_find(&p2p_soc_obj->p2p_idr,
cookie, &roc_ctx);
if (QDF_IS_STATUS_ERROR(status)) {
p2p_err("invalid id");
return QDF_STATUS_E_INVAL;
}
@@ -206,11 +214,17 @@ QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
msg.type = P2P_CANCEL_ROC_REQ;
msg.bodyptr = cancel_roc;
msg.callback = p2p_process_cmd;
scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF, &msg);
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
return QDF_STATUS_SUCCESS;
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(cancel_roc);
p2p_err("post msg fail:%d", status);
}
return status;
}
QDF_STATUS ucfg_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev)
@@ -342,7 +356,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
else {
status = qdf_idr_alloc(&p2p_soc_obj->p2p_idr,
tx_action, &id);
if (status != QDF_STATUS_SUCCESS) {
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(tx_action);
p2p_err("failed to alloc idr, status :%d", status);
return status;
@@ -373,11 +387,20 @@ QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
msg.type = P2P_MGMT_TX;
msg.bodyptr = tx_action;
msg.callback = p2p_process_cmd;
scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF, &msg);
msg.flush_callback = p2p_msg_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
if (id)
qdf_idr_remove(&p2p_soc_obj->p2p_idr, id);
qdf_mem_free(tx_action->buf);
qdf_mem_free(tx_action);
p2p_err("post msg fail:%d", status);
}
return QDF_STATUS_SUCCESS;
return status;
}
QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
@@ -387,6 +410,7 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
struct p2p_soc_priv_obj *p2p_soc_obj;
struct cancel_roc_context *cancel_tx;
void *tx_ctx;
QDF_STATUS status;
p2p_debug("soc:%pK, cookie:0x%llx", soc, cookie);
@@ -402,8 +426,9 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
return QDF_STATUS_E_FAILURE;
}
if (QDF_STATUS_SUCCESS != qdf_idr_find(&p2p_soc_obj->p2p_idr,
(int32_t)cookie, &tx_ctx)) {
status = qdf_idr_find(&p2p_soc_obj->p2p_idr,
(int32_t)cookie, &tx_ctx);
if (QDF_IS_STATUS_ERROR(status)) {
p2p_debug("invalid id");
return QDF_STATUS_E_INVAL;
}
@@ -420,11 +445,16 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
msg.type = P2P_MGMT_TX_CANCEL;
msg.bodyptr = cancel_tx;
msg.callback = p2p_process_cmd;
scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF, &msg);
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(cancel_tx);
p2p_err("post msg fail: %d", status);
}
return QDF_STATUS_SUCCESS;
return status;
}
bool ucfg_p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,