]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu/arm-smmu-v3-iommufd: Require exactly one Stream ID for a vDEVICE
authorNicolin Chen <nicolinc@nvidia.com>
Mon, 6 Jul 2026 05:36:11 +0000 (22:36 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 14 Jul 2026 13:51:57 +0000 (10:51 -0300)
arm_vsmmu_vsid_to_sid() maps a guest's vSID to a single physical Stream ID
taken from master->streams[0], assuming a device has exactly one stream. A
device with several streams gets only its first one mapped, so a guest vSID
invalidation cannot reach the others' ATC and IOTLB entries; a device with
none makes master->streams a ZERO_SIZE_PTR, read out of bounds.

Add an arm_vsmmu_vdevice_init() op to reject the vDEVICE with -EOPNOTSUPP
when master->num_streams is not one, rather than mapping it silently.

Fixes: d68beb276ba26 ("iommu/arm-smmu-v3: Support IOMMU_HWPT_INVALIDATE using a VIOMMU object")
Link: https://patch.msgid.link/r/b15f2b73520f389f3f57881da2f040e7bdc18876.1783311134.git.nicolinc@nvidia.com
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c

index 1e9f7d2de34414e152d043ea015c2680d3bf81ea..85ebfdb3d2a7acece11d06204cca8e74287ceaff 100644 (file)
@@ -297,6 +297,20 @@ unlock:
        return ret;
 }
 
+static int arm_vsmmu_vdevice_init(struct iommufd_vdevice *vdev)
+{
+       struct device *dev = iommufd_vdevice_to_device(vdev);
+       struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+
+       /*
+        * arm_vsmmu_vsid_to_sid() maps a vSID to master->streams[0] alone, so
+        * more streams would leave the rest stale and none reads out of bounds.
+        */
+       if (master->num_streams != 1)
+               return -EOPNOTSUPP;
+       return 0;
+}
+
 /* This is basically iommu_viommu_arm_smmuv3_invalidate in u64 for conversion */
 struct arm_vsmmu_invalidation_cmd {
        union {
@@ -403,6 +417,7 @@ out:
 static const struct iommufd_viommu_ops arm_vsmmu_ops = {
        .alloc_domain_nested = arm_vsmmu_alloc_domain_nested,
        .cache_invalidate = arm_vsmmu_cache_invalidate,
+       .vdevice_init = arm_vsmmu_vdevice_init,
 };
 
 size_t arm_smmu_get_viommu_size(struct device *dev,