slimbus: qcom-ngd-ctrl: Avoid accessing deallocated stack

The functions qcom_slim_ngd_xfer_msg and
qcom_slim_ngd_xfer_msg_sync declare a local completion
variable called done. However, this variable is accessed
beyond the scope of these functions.

To address this issue:
1. Instead of keeping done as a local variable,
move it to qcom_slim_ngd_ctrl.
2. Initialize done during the probe phase.
3. Use this variable for handling transfer and
synchronization messages.

Change-Id: If97b71e2db730ab21bfd07479d2737b0546e1f8e
Signed-off-by: Mehul Raninga <quic_mraninga@quicinc.com>
This commit is contained in:
Mehul Raninga 2024-03-15 10:24:28 +05:30
commit 65757a25d1

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
// Copyright (c) 2018, Linaro Limited
// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
#include <linux/irq.h>
#include <linux/kernel.h>
@ -156,6 +157,8 @@ struct qcom_slim_ngd_ctrl {
struct completion reconf;
struct work_struct m_work;
struct workqueue_struct *mwq;
struct completion xfer_done;
struct completion sync_done;
spinlock_t tx_buf_lock;
enum qcom_slim_ngd_state state;
dma_addr_t rx_phys_base;
@ -768,7 +771,6 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
{
struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(sctrl->dev);
DECLARE_COMPLETION_ONSTACK(tx_sent);
DECLARE_COMPLETION_ONSTACK(done);
int ret, timeout, i;
u8 wbuf[SLIM_MSGQ_BUF_LEN];
u8 rbuf[SLIM_MSGQ_BUF_LEN];
@ -777,6 +779,8 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
u8 la = txn->la;
bool usr_msg = false;
reinit_completion(&ctrl->xfer_done);
if (txn->mt == SLIM_MSG_MT_CORE &&
(txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
@ -824,7 +828,7 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
if (txn->mc != SLIM_USR_MC_DISCONNECT_PORT)
wbuf[i++] = txn->msg->wbuf[1];
txn->comp = &done;
txn->comp = &ctrl->xfer_done;
ret = slim_alloc_txn_tid(sctrl, txn);
if (ret) {
dev_err(ctrl->dev, "Unable to allocate TID\n");
@ -876,7 +880,7 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
}
if (usr_msg) {
timeout = wait_for_completion_timeout(&done, HZ);
timeout = wait_for_completion_timeout(&ctrl->xfer_done, HZ);
if (!timeout) {
dev_err(sctrl->dev, "TX timed out:MC:0x%x,mt:0x%x",
txn->mc, txn->mt);
@ -890,18 +894,21 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
static int qcom_slim_ngd_xfer_msg_sync(struct slim_controller *ctrl,
struct slim_msg_txn *txn)
{
DECLARE_COMPLETION_ONSTACK(done);
struct qcom_slim_ngd_ctrl *dev =
container_of(ctrl, struct qcom_slim_ngd_ctrl, ctrl);
int ret, timeout;
reinit_completion(&dev->sync_done);
pm_runtime_get_sync(ctrl->dev);
txn->comp = &done;
txn->comp = &dev->sync_done;
ret = qcom_slim_ngd_xfer_msg(ctrl, txn);
if (ret)
return ret;
timeout = wait_for_completion_timeout(&done, HZ);
timeout = wait_for_completion_timeout(&dev->sync_done, HZ);
if (!timeout) {
dev_err(ctrl->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
txn->mt);
@ -1460,6 +1467,9 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
init_completion(&ctrl->reconf);
init_completion(&ctrl->qmi.qmi_comp);
init_completion(&ctrl->xfer_done);
init_completion(&ctrl->sync_done);
platform_driver_register(&qcom_slim_ngd_driver);
return of_qcom_slim_ngd_register(dev, ctrl);
}