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

Commit fac84939 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

x86: cpa, strict range check in try_preserve_large_page()



Right now, we check only the first 4k page for static required protections.
This does not take overlapping regions into account. So we might end up
setting the wrong permissions/protections for other parts of this large page.

This can be optimized further, but correctness is the important part.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent b1d95f4e
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -253,10 +253,10 @@ static int
try_preserve_large_page(pte_t *kpte, unsigned long address,
			struct cpa_data *cpa)
{
	unsigned long nextpage_addr, numpages, pmask, psize, flags;
	unsigned long nextpage_addr, numpages, pmask, psize, flags, addr;
	pte_t new_pte, old_pte, *tmp;
	pgprot_t old_prot, new_prot;
	int do_split = 1;
	int i, do_split = 1;
	unsigned int level;

	spin_lock_irqsave(&pgd_lock, flags);
@@ -303,6 +303,19 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
	pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
	new_prot = static_protections(new_prot, address);

	/*
	 * We need to check the full range, whether
	 * static_protection() requires a different pgprot for one of
	 * the pages in the range we try to preserve:
	 */
	addr = address + PAGE_SIZE;
	for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE) {
		pgprot_t chk_prot = static_protections(new_prot, addr);

		if (pgprot_val(chk_prot) != pgprot_val(new_prot))
			goto out_unlock;
	}

	/*
	 * If there are no changes, return. maxpages has been updated
	 * above: