]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iommufd: WARN if an object is aborted with an elevated refcount
authorJason Gunthorpe <jgg@nvidia.com>
Wed, 17 Sep 2025 18:59:59 +0000 (15:59 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 12 Oct 2025 11:01:02 +0000 (13:01 +0200)
[ Upstream commit 53d0584eeb2c85a46c83656246d61a89558d74b3 ]

If something holds a refcount then it is at risk of UAFing. For abort
paths we expect the caller to never share the object with a parallel
thread and to clean up any refcounts it obtained on its own.

Add the missing dec inside iommufd_hwpt_paging_alloc() during error unwind
by making iommufd_hw_pagetable_attach/detach() proper pairs.

Link: https://patch.msgid.link/r/2-v1-02cd136829df+31-iommufd_syz_fput_jgg@nvidia.com
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/iommu/iommufd/device.c
drivers/iommu/iommufd/iommufd_private.h
drivers/iommu/iommufd/main.c

index 86244403b5320e163af3d6491a4aa674582628e0..674f9f244f7b4b38c805b99eba2cb3812db8c294 100644 (file)
@@ -661,6 +661,8 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev, ioasid_t pasid)
                iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
        mutex_unlock(&igroup->lock);
 
+       iommufd_hw_pagetable_put(idev->ictx, hwpt);
+
        /* Caller must destroy hwpt */
        return hwpt;
 }
@@ -1007,7 +1009,6 @@ void iommufd_device_detach(struct iommufd_device *idev, ioasid_t pasid)
        hwpt = iommufd_hw_pagetable_detach(idev, pasid);
        if (!hwpt)
                return;
-       iommufd_hw_pagetable_put(idev->ictx, hwpt);
        refcount_dec(&idev->obj.users);
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_device_detach, "IOMMUFD");
index 9ccc83341f3215e9c7fda7d50669de9601c31755..e68d8d63076a8f1679c7f09e3d58659d64b97760 100644 (file)
@@ -390,9 +390,8 @@ static inline void iommufd_hw_pagetable_put(struct iommufd_ctx *ictx,
        if (hwpt->obj.type == IOMMUFD_OBJ_HWPT_PAGING) {
                struct iommufd_hwpt_paging *hwpt_paging = to_hwpt_paging(hwpt);
 
-               lockdep_assert_not_held(&hwpt_paging->ioas->mutex);
-
                if (hwpt_paging->auto_domain) {
+                       lockdep_assert_not_held(&hwpt_paging->ioas->mutex);
                        iommufd_object_put_and_try_destroy(ictx, &hwpt->obj);
                        return;
                }
index 62a3469bbd37e7637add7c88556593682f7aeace..2b26747ac20217a58043e84121cc62ab53331606 100644 (file)
@@ -62,6 +62,10 @@ void iommufd_object_abort(struct iommufd_ctx *ictx, struct iommufd_object *obj)
        old = xas_store(&xas, NULL);
        xa_unlock(&ictx->objects);
        WARN_ON(old != XA_ZERO_ENTRY);
+
+       if (WARN_ON(!refcount_dec_and_test(&obj->users)))
+               return;
+
        kfree(obj);
 }