[PATCH V2 1/3] accel/amdxdna: Fix amdxdna_client lifetime race during device removal

From: Lizhi Hou

Date: Mon Jun 08 2026 - 12:22:48 EST


In amdxdna_remove(), all amdxdna_client structures are freed after
calling drm_dev_unplug(). However, drm_dev_unplug() does not force
existing file descriptors to be closed, so amdxdna_drm_close() may be
called after amdxdna_remove() has completed.

As a result, accessing client->pid for debug output in
amdxdna_drm_close() can lead to a use-after-free, since the access is
not protected by drm_dev_enter().

Fix this by moving the debug output after drm_dev_enter(). Similarly,
add the drm_dev_enter() protection for amdxdna_drm_open().

Fixes: be462c97b7df ("accel/amdxdna: Add hardware context")
Signed-off-by: Lizhi Hou <lizhi.hou@xxxxxxx>
---
drivers/accel/amdxdna/amdxdna_pci_drv.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.c b/drivers/accel/amdxdna/amdxdna_pci_drv.c
index 1f066ed8d236..a22c986f1b33 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.c
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.c
@@ -108,10 +108,16 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
{
struct amdxdna_dev *xdna = to_xdna_dev(ddev);
struct amdxdna_client *client;
+ int ret = 0, idx;
+
+ if (!drm_dev_enter(ddev, &idx))
+ return -ENODEV;

client = kzalloc_obj(*client);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ ret = -ENOMEM;
+ goto dev_exit;
+ }

client->pid = pid_nr(rcu_access_pointer(filp->pid));
client->xdna = xdna;
@@ -125,7 +131,8 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
if (!amdxdna_use_carveout(xdna)) {
XDNA_ERR(xdna, "PASID unavailable and carveout not configured");
kfree(client);
- return -EINVAL;
+ ret = -EINVAL;
+ goto dev_exit;
}
}
}
@@ -145,7 +152,11 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp)
client->filp = filp;

XDNA_DBG(xdna, "pid %d opened", client->pid);
- return 0;
+
+dev_exit:
+ drm_dev_exit(idx);
+
+ return ret;
}

static void amdxdna_client_cleanup(struct amdxdna_client *client)
@@ -175,11 +186,10 @@ static void amdxdna_drm_close(struct drm_device *ddev, struct drm_file *filp)
struct amdxdna_dev *xdna = to_xdna_dev(ddev);
int idx;

- XDNA_DBG(xdna, "closing pid %d", client->pid);
-
if (!drm_dev_enter(&xdna->ddev, &idx))
return;

+ XDNA_DBG(xdna, "closing pid %d", client->pid);
mutex_lock(&xdna->dev_lock);
amdxdna_client_cleanup(client);
mutex_unlock(&xdna->dev_lock);
--
2.34.1