OSDN Git Service

iommu/io-pgtable: fix __arm_lpae_free_pgtable leak
authorLiam Mark <lmark@codeaurora.org>
Sun, 16 Aug 2015 04:58:11 +0000 (21:58 -0700)
committerDavid Keitel <dkeitel@codeaurora.org>
Tue, 22 Mar 2016 18:13:52 +0000 (11:13 -0700)
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>
drivers/iommu/io-pgtable-arm.c

index 556c484..582e858 100644 (file)
@@ -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);
 }