lkml.org 
[lkml]   [2021]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.12 089/292] iommu/arm-smmu: Fix arm_smmu_device refcount leak in address translation
    Date
    From: Xiyu Yang <xiyuyang19@fudan.edu.cn>

    [ 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@fudan.edu.cn>
    Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
    Reviewed-by: Rob Clark <robdclark@chromium.org>
    Link: https://lore.kernel.org/r/1623293391-17261-1-git-send-email-xiyuyang19@fudan.edu.cn
    Signed-off-by: Will Deacon <will@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/iommu/arm/arm-smmu/arm-smmu.c | 8 ++++++--
    1 file changed, 6 insertions(+), 2 deletions(-)

    diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
    index 128c2c87b4e5..c6ff32797a23 100644
    --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
    +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
    @@ -1268,6 +1268,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)
    @@ -1287,6 +1288,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);
    }

    @@ -1295,12 +1297,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,
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-19 20:10    [W:4.027 / U:0.136 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site