Skip to content

Commit a2e7e59

Browse files
rmurphy-armjoergroedel
authored andcommitted
iommu: Avoid more races around device probe
It turns out there are more subtle races beyond just the main part of __iommu_probe_device() itself running in parallel - the dev_iommu_free() on the way out of an unsuccessful probe can still manage to trip up concurrent accesses to a device's fwspec. Thus, extend the scope of iommu_probe_device_lock() to also serialise fwspec creation and initial retrieval. Reported-by: Zhenhua Huang <[email protected]> Link: https://lore.kernel.org/linux-iommu/[email protected]/ Fixes: 01657bc ("iommu: Avoid races around device probe") Signed-off-by: Robin Murphy <[email protected]> Acked-by: Greg Kroah-Hartman <[email protected]> Reviewed-by: André Draszik <[email protected]> Tested-by: André Draszik <[email protected]> Link: https://lore.kernel.org/r/16f433658661d7cadfea51e7c65da95826112a2b.1700071477.git.robin.murphy@arm.com Cc: [email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent a99583e commit a2e7e59

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

drivers/acpi/scan.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1568,17 +1568,22 @@ static const struct iommu_ops *acpi_iommu_configure_id(struct device *dev,
15681568
int err;
15691569
const struct iommu_ops *ops;
15701570

1571+
/* Serialise to make dev->iommu stable under our potential fwspec */
1572+
mutex_lock(&iommu_probe_device_lock);
15711573
/*
15721574
* If we already translated the fwspec there is nothing left to do,
15731575
* return the iommu_ops.
15741576
*/
15751577
ops = acpi_iommu_fwspec_ops(dev);
1576-
if (ops)
1578+
if (ops) {
1579+
mutex_unlock(&iommu_probe_device_lock);
15771580
return ops;
1581+
}
15781582

15791583
err = iort_iommu_configure_id(dev, id_in);
15801584
if (err && err != -EPROBE_DEFER)
15811585
err = viot_iommu_configure(dev);
1586+
mutex_unlock(&iommu_probe_device_lock);
15821587

15831588
/*
15841589
* If we have reason to believe the IOMMU driver missed the initial

drivers/iommu/iommu.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -485,11 +485,12 @@ static void iommu_deinit_device(struct device *dev)
485485
dev_iommu_free(dev);
486486
}
487487

488+
DEFINE_MUTEX(iommu_probe_device_lock);
489+
488490
static int __iommu_probe_device(struct device *dev, struct list_head *group_list)
489491
{
490492
const struct iommu_ops *ops = dev->bus->iommu_ops;
491493
struct iommu_group *group;
492-
static DEFINE_MUTEX(iommu_probe_device_lock);
493494
struct group_device *gdev;
494495
int ret;
495496

@@ -502,17 +503,15 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
502503
* probably be able to use device_lock() here to minimise the scope,
503504
* but for now enforcing a simple global ordering is fine.
504505
*/
505-
mutex_lock(&iommu_probe_device_lock);
506+
lockdep_assert_held(&iommu_probe_device_lock);
506507

507508
/* Device is probed already if in a group */
508-
if (dev->iommu_group) {
509-
ret = 0;
510-
goto out_unlock;
511-
}
509+
if (dev->iommu_group)
510+
return 0;
512511

513512
ret = iommu_init_device(dev, ops);
514513
if (ret)
515-
goto out_unlock;
514+
return ret;
516515

517516
group = dev->iommu_group;
518517
gdev = iommu_group_alloc_device(group, dev);
@@ -548,7 +547,6 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
548547
list_add_tail(&group->entry, group_list);
549548
}
550549
mutex_unlock(&group->mutex);
551-
mutex_unlock(&iommu_probe_device_lock);
552550

553551
if (dev_is_pci(dev))
554552
iommu_dma_set_pci_32bit_workaround(dev);
@@ -562,8 +560,6 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
562560
iommu_deinit_device(dev);
563561
mutex_unlock(&group->mutex);
564562
iommu_group_put(group);
565-
out_unlock:
566-
mutex_unlock(&iommu_probe_device_lock);
567563

568564
return ret;
569565
}
@@ -573,7 +569,9 @@ int iommu_probe_device(struct device *dev)
573569
const struct iommu_ops *ops;
574570
int ret;
575571

572+
mutex_lock(&iommu_probe_device_lock);
576573
ret = __iommu_probe_device(dev, NULL);
574+
mutex_unlock(&iommu_probe_device_lock);
577575
if (ret)
578576
return ret;
579577

@@ -1822,7 +1820,9 @@ static int probe_iommu_group(struct device *dev, void *data)
18221820
struct list_head *group_list = data;
18231821
int ret;
18241822

1823+
mutex_lock(&iommu_probe_device_lock);
18251824
ret = __iommu_probe_device(dev, group_list);
1825+
mutex_unlock(&iommu_probe_device_lock);
18261826
if (ret == -ENODEV)
18271827
ret = 0;
18281828

drivers/iommu/of_iommu.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,20 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
112112
const u32 *id)
113113
{
114114
const struct iommu_ops *ops = NULL;
115-
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
115+
struct iommu_fwspec *fwspec;
116116
int err = NO_IOMMU;
117117

118118
if (!master_np)
119119
return NULL;
120120

121+
/* Serialise to make dev->iommu stable under our potential fwspec */
122+
mutex_lock(&iommu_probe_device_lock);
123+
fwspec = dev_iommu_fwspec_get(dev);
121124
if (fwspec) {
122-
if (fwspec->ops)
125+
if (fwspec->ops) {
126+
mutex_unlock(&iommu_probe_device_lock);
123127
return fwspec->ops;
124-
128+
}
125129
/* In the deferred case, start again from scratch */
126130
iommu_fwspec_free(dev);
127131
}
@@ -155,6 +159,8 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
155159
fwspec = dev_iommu_fwspec_get(dev);
156160
ops = fwspec->ops;
157161
}
162+
mutex_unlock(&iommu_probe_device_lock);
163+
158164
/*
159165
* If we have reason to believe the IOMMU driver missed the initial
160166
* probe for dev, replay it to get things in order.

include/linux/iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,7 @@ static inline void dev_iommu_priv_set(struct device *dev, void *priv)
845845
dev->iommu->priv = priv;
846846
}
847847

848+
extern struct mutex iommu_probe_device_lock;
848849
int iommu_probe_device(struct device *dev);
849850

850851
int iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features f);

0 commit comments

Comments
 (0)