| From b469d4c6e1594fe75c74496bc9bcafdc8fd8bfeb Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 3 Mar 2021 17:36:11 +0000 |
| Subject: iommu: Check dev->iommu in iommu_dev_xxx functions |
| |
| From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> |
| |
| [ Upstream commit b9abb19fa5fd2d8a4be61c6cd4b2a48aa1a17f9c ] |
| |
| The device iommu probe/attach might have failed leaving dev->iommu |
| to NULL and device drivers may still invoke these functions resulting |
| in a crash in iommu vendor driver code. |
| |
| Hence make sure we check that. |
| |
| Fixes: a3a195929d40 ("iommu: Add APIs for multiple domains per device") |
| Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> |
| Reviewed-by: Robin Murphy <robin.murphy@arm.com> |
| Link: https://lore.kernel.org/r/20210303173611.520-1-shameerali.kolothum.thodi@huawei.com |
| Signed-off-by: Joerg Roedel <jroedel@suse.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/iommu/iommu.c | 24 +++++++++++++++--------- |
| 1 file changed, 15 insertions(+), 9 deletions(-) |
| |
| diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c |
| index fd5f59373fc6..0e0140454de8 100644 |
| --- a/drivers/iommu/iommu.c |
| +++ b/drivers/iommu/iommu.c |
| @@ -2889,10 +2889,12 @@ EXPORT_SYMBOL_GPL(iommu_dev_has_feature); |
| |
| int iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features feat) |
| { |
| - const struct iommu_ops *ops = dev->bus->iommu_ops; |
| + if (dev->iommu && dev->iommu->iommu_dev) { |
| + const struct iommu_ops *ops = dev->iommu->iommu_dev->ops; |
| |
| - if (ops && ops->dev_enable_feat) |
| - return ops->dev_enable_feat(dev, feat); |
| + if (ops->dev_enable_feat) |
| + return ops->dev_enable_feat(dev, feat); |
| + } |
| |
| return -ENODEV; |
| } |
| @@ -2905,10 +2907,12 @@ EXPORT_SYMBOL_GPL(iommu_dev_enable_feature); |
| */ |
| int iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features feat) |
| { |
| - const struct iommu_ops *ops = dev->bus->iommu_ops; |
| + if (dev->iommu && dev->iommu->iommu_dev) { |
| + const struct iommu_ops *ops = dev->iommu->iommu_dev->ops; |
| |
| - if (ops && ops->dev_disable_feat) |
| - return ops->dev_disable_feat(dev, feat); |
| + if (ops->dev_disable_feat) |
| + return ops->dev_disable_feat(dev, feat); |
| + } |
| |
| return -EBUSY; |
| } |
| @@ -2916,10 +2920,12 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature); |
| |
| bool iommu_dev_feature_enabled(struct device *dev, enum iommu_dev_features feat) |
| { |
| - const struct iommu_ops *ops = dev->bus->iommu_ops; |
| + if (dev->iommu && dev->iommu->iommu_dev) { |
| + const struct iommu_ops *ops = dev->iommu->iommu_dev->ops; |
| |
| - if (ops && ops->dev_feat_enabled) |
| - return ops->dev_feat_enabled(dev, feat); |
| + if (ops->dev_feat_enabled) |
| + return ops->dev_feat_enabled(dev, feat); |
| + } |
| |
| return false; |
| } |
| -- |
| 2.30.2 |
| |