mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Abhijit Gangurde <abhijit.gangurde@amd.com>
To: <nikhil.agarwal@amd.com>, <Nipun.Gupta@amd.com>
Cc: <gregkh@linuxfoundation.org>, <linux-kernel@vger.kernel.org>,
	<michal.simek@amd.com>, <git@amd.com>,
	<shubhrajyoti.datta@amd.com>,
	"Abhijit Gangurde" <abhijit.gangurde@amd.com>,
	Prasanna Kumar T S M <ptsm@linux.microsoft.com>
Subject: [PATCH 1/1] cdx: fix use-after-free in cdx_mcdi_process_cmd after timeout
Date: Fri, 7 Aug 2026 12:06:09 +0530	[thread overview]
Message-ID: <20260807063609.2413865-1-abhijit.gangurde@amd.com> (raw)

When an MCDI command times out, cdx_mcdi_timeout_cmd() frees the cmd
via cdx_mcdi_remove_cmd() but does not clear mcdi->seq_held_by[] or
mcdi->db_held_by. If the firmware responds after the timeout,
cdx_mcdi_process_cmd() dereferences the freed cmd pointer leading to a
use-after-free.

clear the seq_held_by and db_held_by in the timeout path, and
add an extra kref to handle the race where the response arrives
concurrently with the timeout handler.

Fixes: eb96b740192b ("cdx: add MCDI protocol interface for firmware interaction")
Co-developed-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
Signed-off-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
---
 drivers/cdx/controller/mcdi.c | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/cdx/controller/mcdi.c b/drivers/cdx/controller/mcdi.c
index 34a07d6f41a0..ef46aeddcf01 100644
--- a/drivers/cdx/controller/mcdi.c
+++ b/drivers/cdx/controller/mcdi.c
@@ -405,6 +405,11 @@ static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd)
 		return;
 
 	mutex_lock(&mcdi->iface_lock);
+	if (cmd->state == MCDI_STATE_FINISHED) {
+		mutex_unlock(&mcdi->iface_lock);
+		return;
+	}
+
 	cdx_mcdi_timeout_cmd(mcdi, cmd, &cleanup_list);
 	mutex_unlock(&mcdi->iface_lock);
 	cdx_mcdi_process_cleanup_list(cdx, &cleanup_list);
@@ -473,6 +478,8 @@ static int cdx_mcdi_rpc_sync(struct cdx_mcdi *cdx, unsigned int cmd,
 	wait_data->outlen = outlen;
 
 	kref_init(&cmd_item->ref);
+	/* Claim an extra ref in case response comes after timeout */
+	kref_get(&cmd_item->ref);
 	cmd_item->quiet = quiet;
 	cmd_item->cookie = (unsigned long)wait_data;
 	cmd_item->completer = &cdx_mcdi_rpc_completer;
@@ -506,6 +513,7 @@ static int cdx_mcdi_rpc_sync(struct cdx_mcdi *cdx, unsigned int cmd,
 
 out:
 	kref_put(&wait_data->ref, cdx_mcdi_blocking_data_release);
+	kref_put(&cmd_item->ref, cdx_mcdi_cmd_release);
 
 	return rc;
 }
@@ -611,17 +619,10 @@ void cdx_mcdi_process_cmd(struct cdx_mcdi *cdx, struct cdx_dword *outbuf, int le
 	mutex_lock(&mcdi->iface_lock);
 	cmd = mcdi->seq_held_by[respseq];
 
-	if (cmd) {
-		if (cmd->state == MCDI_STATE_FINISHED) {
-			mutex_unlock(&mcdi->iface_lock);
-			kref_put(&cmd->ref, cdx_mcdi_cmd_release);
-			return;
-		}
-
+	if (cmd)
 		cdx_mcdi_complete_cmd(mcdi, cmd, outbuf, len, &cleanup_list);
-	} else {
+	else
 		pr_err("MC response unexpected for seq : %0X\n", respseq);
-	}
 
 	mutex_unlock(&mcdi->iface_lock);
 
@@ -734,7 +735,7 @@ static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi,
 		completed = true;
 	}
 
-	/* free sequence number and buffer */
+	/* free sequence number */
 	mcdi->seq_held_by[cmd->seq] = NULL;
 
 	cdx_mcdi_start_or_queue(mcdi, rc != MC_CMD_ERR_QUEUE_FULL);
@@ -759,6 +760,11 @@ static void cdx_mcdi_timeout_cmd(struct cdx_mcdi_iface *mcdi,
 
 	cmd->rc = -ETIMEDOUT;
 	cdx_mcdi_remove_cmd(mcdi, cmd, cleanup_list);
+	/* free sequence number */
+	if (mcdi->seq_held_by[cmd->seq] == cmd)
+		mcdi->seq_held_by[cmd->seq] = NULL;
+	if (mcdi->db_held_by == cmd)
+		mcdi->db_held_by = NULL;
 
 	cdx_mcdi_mode_fail(cdx, cleanup_list);
 }
@@ -821,7 +827,7 @@ cdx_mcdi_rpc_async(struct cdx_mcdi *cdx, unsigned int cmd,
 		   cdx_mcdi_async_completer *complete, unsigned long cookie)
 {
 	struct cdx_mcdi_cmd *cmd_item =
-		kmalloc(sizeof(struct cdx_mcdi_cmd) + inlen, GFP_ATOMIC);
+		kzalloc(sizeof(struct cdx_mcdi_cmd) + inlen, GFP_ATOMIC);
 
 	if (!cmd_item)
 		return -ENOMEM;
-- 
2.44.4


             reply	other threads:[~2026-08-07  6:36 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-07  6:36 Abhijit Gangurde [this message]
2026-08-12 11:56 ` Agarwal, Nikhil

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260807063609.2413865-1-abhijit.gangurde@amd.com \
    --to=abhijit.gangurde@amd.com \
    --cc=Nipun.Gupta@amd.com \
    --cc=git@amd.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michal.simek@amd.com \
    --cc=nikhil.agarwal@amd.com \
    --cc=ptsm@linux.microsoft.com \
    --cc=shubhrajyoti.datta@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®