From c509fb73a1093a15accd7d43a61645d4b520f6ac Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Wed, 5 Aug 2026 07:43:12 +0800 Subject: [PATCH] iommu/vt-d: Tear down scalable-mode context on probe failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_pasid_setup_sm_context() walks a PCI device’s DMA aliases via pci_for_each_dma_alias() and programs a scalable-mode context entry for each RID. For a device with a dma_alias_mask, the callback is invoked once for the device’s own RID and once for each alias bit, all with the same pci_dev, so device_pasid_table_setup() runs for multiple RIDs. pci_for_each_dma_alias() stops at the first callback error. Therefore, a failure partway through the walk can leave context entries for already processed RIDs present and still pointing to the device’s PASID table. On this error path, intel_iommu_probe_device() currently jumps directly to intel_pasid_free_table(), which frees the PASID table without first tearing down those context entries. The IOMMU may then walk a present context entry whose PASID table pointer references freed memory. intel_iommu_release_device() already performs teardown before freeing the table. Apply the same ordering on the probe failure path. device_pasid_table_teardown() safely handles RIDs that were never programmed: iommu_context_addr() returns NULL when no context table has been allocated, and clearing the Present bit of an already non-present entry is a no-op. So unwind is safe for both the alias that failed and any aliases not yet reached. Fixes: 301f1a80487fd ("iommu/vt-d: Setup scalable mode context entry in probe path") Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260602233426.357499-1-baolu.lu%40linux.intel.com Assisted-by: Claude:claude-opus-5 Signed-off-by: Lu Baolu Signed-off-by: Joerg Roedel --- drivers/iommu/intel/iommu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 9003783d02bc..489bab4999fb 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3333,6 +3333,7 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev) return &iommu->iommu; free_table: + intel_pasid_teardown_sm_context(dev); intel_pasid_free_table(dev); clear_rbtree: device_rbtree_remove(info);