Skip to content

Commit b46064a

Browse files
rmurphy-armjoergroedel
authored andcommitted
iommu: Handle race with default domain setup
It turns out that deferred default domain creation leaves a subtle race window during iommu_device_register() wherein a client driver may asynchronously probe in parallel and get as far as performing DMA API operations with dma-direct, only to be switched to iommu-dma underfoot once the default domain attachment finally happens, with obviously disastrous consequences. Even the wonky of_iommu_configure() path is at risk, since iommu_fwspec_init() will no longer defer client probe as the instance ops are (necessarily) already registered, and the "replay" iommu_probe_device() call can see dev->iommu_group already set and so think there's nothing to do either. Fortunately we already have the right tool in the right place in the form of iommu_device_use_default_domain(), which just needs to ensure that said default domain is actually ready to *be* used. Deferring the client probe shouldn't have too much impact, given that this only happens while the IOMMU driver is probing, and thus due to kick the deferred probe list again once it finishes. Reported-by: Charan Teja Kalla <[email protected]> Fixes: 98ac73f ("iommu: Require a default_domain for all iommu drivers") Reviewed-by: Jason Gunthorpe <[email protected]> Signed-off-by: Robin Murphy <[email protected]> Link: https://lore.kernel.org/r/e88b94c9b575034a2c98a48b3d383654cbda7902.1740753261.git.robin.murphy@arm.com Signed-off-by: Joerg Roedel <[email protected]>
1 parent 29c6e1c commit b46064a

File tree

1 file changed

+5
-0
lines changed

1 file changed

+5
-0
lines changed

drivers/iommu/iommu.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3084,6 +3084,11 @@ int iommu_device_use_default_domain(struct device *dev)
30843084
return 0;
30853085

30863086
mutex_lock(&group->mutex);
3087+
/* We may race against bus_iommu_probe() finalising groups here */
3088+
if (!group->default_domain) {
3089+
ret = -EPROBE_DEFER;
3090+
goto unlock_out;
3091+
}
30873092
if (group->owner_cnt) {
30883093
if (group->domain != group->default_domain || group->owner ||
30893094
!xa_empty(&group->pasid_array)) {

0 commit comments

Comments
 (0)