[PATCH] iommu/exynos: fix NULL pointer dereference on device_link_add() failure

From: Haotian Zhang

Date: Thu Oct 08 2026 - 23:45:59 EST


exynos_iommu_probe_device() stores the result of device_link_add() in
data->link without checking it for failure, although device_link_add()
returns NULL when the supplier is not PM initialized, on a dependency
cycle or on allocation failure. exynos_iommu_release_device() then calls
device_link_del() on that entry unconditionally, and device_link_del()
dereferences link->flags, so a NULL data->link causes a NULL pointer
dereference when the device is released.

Check the returned device link for NULL, unwind the links that were
already created and fail the probe instead.

Fixes: 7a974b29fe5d ("iommu/exynos: Rework runtime PM links management")
Assisted-by: DeepSeek-V4.1-Flash
Signed-off-by: Haotian Zhang <vulab@xxxxxxxxxxx>
---
drivers/iommu/exynos-iommu.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 874d05f4b396..ce0492691ef4 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1403,7 +1403,7 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
{
struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
- struct sysmmu_drvdata *data;
+ struct sysmmu_drvdata *data, *tmp;

if (!has_sysmmu(dev))
return ERR_PTR(-ENODEV);
@@ -1417,6 +1417,11 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
data->link = device_link_add(dev, data->sysmmu,
DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME);
+ if (!data->link) {
+ dev_err(dev, "Unable to link %s\n",
+ dev_name(data->sysmmu));
+ goto err_unlink;
+ }
}

/* There is always at least one entry, see exynos_iommu_of_xlate() */
@@ -1424,6 +1429,13 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
struct sysmmu_drvdata, owner_node);

return &data->iommu;
+
+err_unlink:
+ list_for_each_entry_continue_reverse(tmp, &owner->controllers,
+ owner_node)
+ device_link_del(tmp->link);
+
+ return ERR_PTR(-ENODEV);
}

static void exynos_iommu_release_device(struct device *dev)
--
2.25.1