]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
accel/amdxdna: Fix notifier_wq lifetime race during device removal
authorLizhi Hou <lizhi.hou@amd.com>
Thu, 11 Jun 2026 05:51:49 +0000 (22:51 -0700)
committerLizhi Hou <lizhi.hou@amd.com>
Mon, 29 Jun 2026 17:34:48 +0000 (10:34 -0700)
amdxdna_remove() destroys notifier_wq. If amdxdna_gem_obj_free() is
called after device removal, it may attempt to flush notifier_wq,
resulting in a use-after-free.

Fix the race by allocating notifier_wq with
drmm_alloc_ordered_workqueue(), so its lifetime is managed by DRM and
remains valid until all managed resources are released.

Fixes: e486147c912f ("accel/amdxdna: Add BO import and export")
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260611055150.3070216-2-lizhi.hou@amd.com
drivers/accel/amdxdna/amdxdna_pci_drv.c

index 5937666829407aca3858a520494ca59c2a29e2de..e94d8290a80738ed11a574d8ea46c7ecab576eab 100644 (file)
@@ -392,9 +392,9 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (ret)
                return ret;
 
-       xdna->notifier_wq = alloc_ordered_workqueue("notifier_wq", WQ_MEM_RECLAIM);
-       if (!xdna->notifier_wq) {
-               ret = -ENOMEM;
+       xdna->notifier_wq = drmm_alloc_ordered_workqueue(ddev, "notifier_wq", WQ_MEM_RECLAIM);
+       if (IS_ERR(xdna->notifier_wq)) {
+               ret = PTR_ERR(xdna->notifier_wq);
                goto iommu_fini;
        }
 
@@ -403,7 +403,7 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        mutex_unlock(&xdna->dev_lock);
        if (ret) {
                XDNA_ERR(xdna, "Hardware init failed, ret %d", ret);
-               goto destroy_notifier_wq;
+               goto iommu_fini;
        }
 
        ret = amdxdna_sysfs_init(xdna);
@@ -427,8 +427,6 @@ failed_dev_fini:
        mutex_lock(&xdna->dev_lock);
        xdna->dev_info->ops->fini(xdna);
        mutex_unlock(&xdna->dev_lock);
-destroy_notifier_wq:
-       destroy_workqueue(xdna->notifier_wq);
 iommu_fini:
        amdxdna_iommu_fini(xdna);
        return ret;
@@ -439,8 +437,6 @@ static void amdxdna_remove(struct pci_dev *pdev)
        struct amdxdna_dev *xdna = pci_get_drvdata(pdev);
        struct amdxdna_client *client;
 
-       destroy_workqueue(xdna->notifier_wq);
-
        drm_dev_unplug(&xdna->ddev);
        amdxdna_sysfs_fini(xdna);