| From 57afb3ef9c61992e6f30ff32e1d1e9452cff354f Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 12 Dec 2025 10:32:44 -0800 |
| Subject: accel/amdxdna: Fix potential NULL pointer dereference in context |
| cleanup |
| |
| From: Lizhi Hou <lizhi.hou@amd.com> |
| |
| [ Upstream commit 97f27573837ef96b4ba42af463cc800cab615c0e ] |
| |
| aie_destroy_context() is invoked during error handling in |
| aie2_create_context(). However, aie_destroy_context() assumes that the |
| context's mailbox channel pointer is non-NULL. If mailbox channel |
| creation fails, the pointer remains NULL and calling aie_destroy_context() |
| can lead to a NULL pointer dereference. |
| |
| In aie2_create_context(), replace aie_destroy_context() with a function |
| which request firmware to remove the context created previously. |
| |
| Fixes: be462c97b7df ("accel/amdxdna: Add hardware context") |
| Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org> |
| Signed-off-by: Lizhi Hou <lizhi.hou@amd.com> |
| Link: https://patch.msgid.link/20251212183244.1826318-1-lizhi.hou@amd.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/accel/amdxdna/aie2_message.c | 46 ++++++++++++++++------------ |
| 1 file changed, 26 insertions(+), 20 deletions(-) |
| |
| diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c |
| index 4660e8297ed80..932d495230511 100644 |
| --- a/drivers/accel/amdxdna/aie2_message.c |
| +++ b/drivers/accel/amdxdna/aie2_message.c |
| @@ -184,6 +184,19 @@ int aie2_query_firmware_version(struct amdxdna_dev_hdl *ndev, |
| return 0; |
| } |
| |
| +static int aie2_destroy_context_req(struct amdxdna_dev_hdl *ndev, u32 id) |
| +{ |
| + DECLARE_AIE2_MSG(destroy_ctx, MSG_OP_DESTROY_CONTEXT); |
| + struct amdxdna_dev *xdna = ndev->xdna; |
| + int ret; |
| + |
| + req.context_id = id; |
| + ret = aie2_send_mgmt_msg_wait(ndev, &msg); |
| + if (ret) |
| + XDNA_WARN(xdna, "Destroy context failed, ret %d", ret); |
| + |
| + return ret; |
| +} |
| int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx) |
| { |
| DECLARE_AIE2_MSG(create_ctx, MSG_OP_CREATE_CONTEXT); |
| @@ -206,7 +219,8 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct |
| return ret; |
| |
| hwctx->fw_ctx_id = resp.context_id; |
| - WARN_ONCE(hwctx->fw_ctx_id == -1, "Unexpected context id"); |
| + if (WARN_ON_ONCE(hwctx->fw_ctx_id == -1)) |
| + return -EINVAL; |
| |
| cq_pair = &resp.cq_pair[0]; |
| x2i.mb_head_ptr_reg = AIE2_MBOX_OFF(ndev, cq_pair->x2i_q.head_addr); |
| @@ -221,34 +235,32 @@ int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwct |
| |
| ret = pci_irq_vector(to_pci_dev(xdna->ddev.dev), resp.msix_id); |
| if (ret == -EINVAL) { |
| - XDNA_ERR(xdna, "not able to create channel"); |
| - goto out_destroy_context; |
| + XDNA_ERR(xdna, "Alloc IRQ failed %d", ret); |
| + goto del_ctx_req; |
| } |
| |
| intr_reg = i2x.mb_head_ptr_reg + 4; |
| hwctx->priv->mbox_chann = xdna_mailbox_create_channel(ndev->mbox, &x2i, &i2x, |
| intr_reg, ret); |
| if (!hwctx->priv->mbox_chann) { |
| - XDNA_ERR(xdna, "not able to create channel"); |
| + XDNA_ERR(xdna, "Not able to create channel"); |
| ret = -EINVAL; |
| - goto out_destroy_context; |
| + goto del_ctx_req; |
| } |
| |
| - XDNA_DBG(xdna, "%s mailbox channel irq: %d, msix_id: %d", |
| - hwctx->name, ret, resp.msix_id); |
| - XDNA_DBG(xdna, "%s created fw ctx %d pasid %d", hwctx->name, |
| - hwctx->fw_ctx_id, hwctx->client->pasid); |
| + XDNA_DBG(xdna, "Mailbox channel irq: %d, msix_id: %d", ret, resp.msix_id); |
| + XDNA_DBG(xdna, "Created fw ctx %d pasid %d", hwctx->fw_ctx_id, hwctx->client->pasid); |
| |
| return 0; |
| |
| -out_destroy_context: |
| - aie2_destroy_context(ndev, hwctx); |
| +del_ctx_req: |
| + aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); |
| + hwctx->fw_ctx_id = -1; |
| return ret; |
| } |
| |
| int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx) |
| { |
| - DECLARE_AIE2_MSG(destroy_ctx, MSG_OP_DESTROY_CONTEXT); |
| struct amdxdna_dev *xdna = ndev->xdna; |
| int ret; |
| |
| @@ -256,15 +268,9 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc |
| return 0; |
| |
| xdna_mailbox_stop_channel(hwctx->priv->mbox_chann); |
| - |
| - req.context_id = hwctx->fw_ctx_id; |
| - ret = aie2_send_mgmt_msg_wait(ndev, &msg); |
| - if (ret) |
| - XDNA_WARN(xdna, "%s destroy context failed, ret %d", hwctx->name, ret); |
| - |
| + ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id); |
| xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann); |
| - XDNA_DBG(xdna, "%s destroyed fw ctx %d", hwctx->name, |
| - hwctx->fw_ctx_id); |
| + XDNA_DBG(xdna, "Destroyed fw ctx %d", hwctx->fw_ctx_id); |
| hwctx->priv->mbox_chann = NULL; |
| hwctx->fw_ctx_id = -1; |
| |
| -- |
| 2.53.0 |
| |