Skip to content

Commit

Permalink
x86: cpa, strict range check in try_preserve_large_page()
Browse files Browse the repository at this point in the history
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: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Thomas Gleixner committed Feb 9, 2008
1 parent b1d95f4 commit fac8493
Showing 1 changed file with 15 additions and 2 deletions.
17 changes: 15 additions & 2 deletions arch/x86/mm/pageattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit fac8493

Please sign in to comment.