Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65757a25 authored by Mehul Raninga's avatar Mehul Raninga
Browse files

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: default avatarMehul Raninga <quic_mraninga@quicinc.com>
parent 4e18d32a
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
// 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);
}