
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC03L1 -------------------------------- During the testing of the SMMU functions related to MPAM, KASAN reports an access fault: BUG: KASAN: global-out-of-bounds in arm_smmu_group_get_mpam Read of size 4 at addr ffffd8dbdf3bf0d8 by task rmdir/9954 Call trace: arm_smmu_group_get_mpam+0x4c/0x150 iommu_group_get_qos_params+0xa8/0xe8 resctrl_arch_match_iommu_closid+0x80/0x118 rdt_move_group_iommus.isra.0+0x198/0x1c0 rdtgroup_rmdir_ctrl+0x58/0x1e8 rdtgroup_rmdir+0x198/0x290 kernfs_iop_rmdir+0xa0/0xe8 vfs_rmdir.part.0+0xd8/0x290 do_rmdir+0x288/0x2e0 The DMA of some devices like the HISI PTT trace can only work under Some devices' DMA (such as Hisi PTT trace) can only work in pass-through mode. Therefore, in the __iommu_domain_alloc(), the SMMU does not allocate a smmu_domain struct for them. Naturally, these types of devices do not support the MPAM feature. Consequently, for devices of type IOMMU_DOMAIN_IDENTITY and IOMMU_DOMAIN_BLOCKED, they are skipped in arm_smmu_group_get_mpam() or returned fail in arm_smmu_group_set_mpam(). Fixes: 587296e12d7d ("iommu/arm-smmu-v3: Add mpam helpers to query and set state") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index f778936d7579..dee6ca2fbdb1 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -4004,6 +4004,7 @@ static int arm_smmu_group_set_mpam(struct iommu_group *group, u16 partid, int i; u32 sid; unsigned long flags; + unsigned int alloc_type; struct arm_smmu_ste *step; struct iommu_domain *domain; struct arm_smmu_device *smmu; @@ -4019,6 +4020,12 @@ static int arm_smmu_group_set_mpam(struct iommu_group *group, u16 partid, struct arm_smmu_master_domain *master_domain; domain = iommu_get_domain_for_group(group); + + alloc_type = domain->type & IOMMU_DOMAIN_ALLOC_FLAGS; + if (alloc_type == IOMMU_DOMAIN_IDENTITY || + alloc_type == IOMMU_DOMAIN_BLOCKED) + return -EINVAL; + smmu_domain = to_smmu_domain(domain); if (!smmu_domain->smmu) @@ -4062,12 +4069,19 @@ static int arm_smmu_group_get_mpam(struct iommu_group *group, u16 *partid, { int err = -EINVAL; unsigned long flags; + unsigned int alloc_type; struct iommu_domain *domain; struct arm_smmu_master *master; struct arm_smmu_domain *smmu_domain; struct arm_smmu_master_domain *master_domain; domain = iommu_get_domain_for_group(group); + + alloc_type = domain->type & IOMMU_DOMAIN_ALLOC_FLAGS; + if (alloc_type == IOMMU_DOMAIN_IDENTITY || + alloc_type == IOMMU_DOMAIN_BLOCKED) + return 0; + smmu_domain = to_smmu_domain(domain); if (!smmu_domain->smmu) -- 2.25.1