Skip to content

Commit

Permalink
ARM: KVM: Fix unaligned unmap_range leak
Browse files Browse the repository at this point in the history
The unmap_range function did not properly cover the case when the start
address was not aligned to PMD_SIZE or PUD_SIZE and an entire pte table
or pmd table was cleared, causing us to leak memory when incrementing
the addr.

The fix is to always move onto the next page table entry boundary
instead of adding the full size of the VA range covered by the
corresponding table level entry.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
  • Loading branch information
Christoffer Dall committed Aug 8, 2013
1 parent 240e99c commit d3840b2
Showing 1 changed file with 7 additions and 7 deletions.
14 changes: 7 additions & 7 deletions arch/arm/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,37 +132,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
pmd_t *pmd;
pte_t *pte;
unsigned long long addr = start, end = start + size;
u64 range;
u64 next;

while (addr < end) {
pgd = pgdp + pgd_index(addr);
pud = pud_offset(pgd, addr);
if (pud_none(*pud)) {
addr += PUD_SIZE;
addr = pud_addr_end(addr, end);
continue;
}

pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) {
addr += PMD_SIZE;
addr = pmd_addr_end(addr, end);
continue;
}

pte = pte_offset_kernel(pmd, addr);
clear_pte_entry(kvm, pte, addr);
range = PAGE_SIZE;
next = addr + PAGE_SIZE;

/* If we emptied the pte, walk back up the ladder */
if (pte_empty(pte)) {
clear_pmd_entry(kvm, pmd, addr);
range = PMD_SIZE;
next = pmd_addr_end(addr, end);
if (pmd_empty(pmd)) {
clear_pud_entry(kvm, pud, addr);
range = PUD_SIZE;
next = pud_addr_end(addr, end);
}
}

addr += range;
addr = next;
}
}

Expand Down

0 comments on commit d3840b2

Please sign in to comment.