This is a note to let you know that I've just added the patch titled iommu/arm-smmu: Fix arm_smmu_device refcount leak in address translation to the 5.13-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: iommu-arm-smmu-fix-arm_smmu_device-refcount-leak-in-.patch and it can be found in the queue-5.13 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 57f80c7576760c73fd275f95894c5e75588ad3ae Author: Xiyu Yang <xiyuyang19@xxxxxxxxxxxx> Date: Thu Jun 10 10:49:20 2021 +0800 iommu/arm-smmu: Fix arm_smmu_device refcount leak in address translation [ Upstream commit 7c8f176d6a3fa18aa0f8875da6f7c672ed2a8554 ] The reference counting issue happens in several exception handling paths of arm_smmu_iova_to_phys_hard(). When those error scenarios occur, the function forgets to decrease the refcount of "smmu" increased by arm_smmu_rpm_get(), causing a refcount leak. Fix this issue by jumping to "out" label when those error scenarios occur. Signed-off-by: Xiyu Yang <xiyuyang19@xxxxxxxxxxxx> Signed-off-by: Xin Tan <tanxin.ctf@xxxxxxxxx> Reviewed-by: Rob Clark <robdclark@xxxxxxxxxxxx> Link: https://lore.kernel.org/r/1623293391-17261-1-git-send-email-xiyuyang19@xxxxxxxxxxxx Signed-off-by: Will Deacon <will@xxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index ee6cac9e7c02..1a647e0ea3eb 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -1271,6 +1271,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, u64 phys; unsigned long va, flags; int ret, idx = cfg->cbndx; + phys_addr_t addr = 0; ret = arm_smmu_rpm_get(smmu); if (ret < 0) @@ -1290,6 +1291,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, dev_err(dev, "iova to phys timed out on %pad. Falling back to software table walk.\n", &iova); + arm_smmu_rpm_put(smmu); return ops->iova_to_phys(ops, iova); } @@ -1298,12 +1300,14 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, if (phys & ARM_SMMU_CB_PAR_F) { dev_err(dev, "translation fault!\n"); dev_err(dev, "PAR = 0x%llx\n", phys); - return 0; + goto out; } + addr = (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff); +out: arm_smmu_rpm_put(smmu); - return (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff); + return addr; } static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,