Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 000d3996 authored by Marc Zyngier's avatar Marc Zyngier Committed by Christoffer Dall
Browse files

ARM: KVM: sanitize freeing of HYP page tables



Instead of trying to free everything from PAGE_OFFSET to the
top of memory, use the virt_addr_valid macro to check the
upper limit.

Also do the same for the vmalloc region where the IO mappings
are allocated.

Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarChristoffer Dall <cdall@cs.columbia.edu>
parent 6190920a
Loading
Loading
Loading
Loading
+26 −18
Original line number Diff line number Diff line
@@ -85,27 +85,18 @@ static void free_ptes(pmd_t *pmd, unsigned long addr)
	}
}

/**
 * free_hyp_pmds - free a Hyp-mode level-2 tables and child level-3 tables
 *
 * Assumes this is a page table used strictly in Hyp-mode and therefore contains
 * only mappings in the kernel memory area, which is above PAGE_OFFSET.
 */
void free_hyp_pmds(void)
static void free_hyp_pgd_entry(unsigned long addr)
{
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;
	unsigned long addr;

	mutex_lock(&kvm_hyp_pgd_mutex);
	for (addr = PAGE_OFFSET; addr != 0; addr += PGDIR_SIZE) {
	unsigned long hyp_addr = KERN_TO_HYP(addr);

	pgd = hyp_pgd + pgd_index(hyp_addr);
	pud = pud_offset(pgd, hyp_addr);

	if (pud_none(*pud))
			continue;
		return;
	BUG_ON(pud_bad(*pud));

	pmd = pmd_offset(pud, hyp_addr);
@@ -113,6 +104,23 @@ void free_hyp_pmds(void)
	pmd_free(NULL, pmd);
	pud_clear(pud);
}

/**
 * free_hyp_pmds - free a Hyp-mode level-2 tables and child level-3 tables
 *
 * Assumes this is a page table used strictly in Hyp-mode and therefore contains
 * either mappings in the kernel memory area (above PAGE_OFFSET), or
 * device mappings in the vmalloc range (from VMALLOC_START to VMALLOC_END).
 */
void free_hyp_pmds(void)
{
	unsigned long addr;

	mutex_lock(&kvm_hyp_pgd_mutex);
	for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
		free_hyp_pgd_entry(addr);
	for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
		free_hyp_pgd_entry(addr);
	mutex_unlock(&kvm_hyp_pgd_mutex);
}