From 65757a25d1ac447ba75fc2038529a6618aecd18d Mon Sep 17 00:00:00 2001 From: Mehul Raninga Date: Fri, 15 Mar 2024 10:24:28 +0530 Subject: [PATCH] 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 --- drivers/slimbus/qcom-ngd-ctrl.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c index 09ecd1fb24ae..2244923532f2 100644 --- a/drivers/slimbus/qcom-ngd-ctrl.c +++ b/drivers/slimbus/qcom-ngd-ctrl.c @@ -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 #include @@ -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); }