diff options
| author | Liam Mark <lmark@codeaurora.org> | 2015-08-15 21:58:11 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:13:52 -0700 |
| commit | bbca324fc5098a3d529dd752c4e7c22660a90c36 (patch) | |
| tree | 3fe0f66428dbb89b28257899313f65de2d54c3f4 | |
| parent | 837edfc242e8802aabf0c8f33c75aca2b53cdc3b (diff) | |
iommu/io-pgtable: fix __arm_lpae_free_pgtable leak
When unmapping 2MB mappings, which are 2MB aligned, the smmu driver
is leaking the 3rd level page tables.
Fix this leak by updating __arm_lpae_free_pgtable so that it no
longer leaks leaf table entries.
To reproduce this leak simply map and unmap a non-block 2MB mapping
which is 2MB aligned.
Change-Id: Ibdbdb084ceb8d03ebe0a04e8777e3eb9419e9b87
Signed-off-by: Liam Mark <lmark@codeaurora.org>
| -rw-r--r-- | drivers/iommu/io-pgtable-arm.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 556c484951cc..582e858c8cad 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -542,10 +542,6 @@ static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl, arm_lpae_iopte *start, *end; unsigned long table_size; - /* Only leaf entries at the last level */ - if (lvl == ARM_LPAE_MAX_LEVELS - 1) - return; - if (lvl == ARM_LPAE_START_LVL(data)) table_size = data->pgd_size; else @@ -554,6 +550,10 @@ static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl, start = ptep; end = (void *)ptep + table_size; + /* Only leaf entries at the last level */ + if (lvl == ARM_LPAE_MAX_LEVELS - 1) + goto end; + while (ptep != end) { arm_lpae_iopte pte = *ptep++; @@ -563,6 +563,7 @@ static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl, __arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data)); } +end: io_pgtable_free_pages_exact(&data->iop.cfg, data->iop.cookie, start, table_size); } |
