aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2013-04-22 00:40:37 -0400
committerRusty Russell <rusty@rustcorp.com.au>2013-04-22 02:01:34 -0400
commit68a644d734e61f38b686cb755bd2a3f43d9372f4 (patch)
treeea2e4f575463a080cbd426338f3666852ea8919d
parent406a590ba105bfb7b67952f0a5f948e0d374e03e (diff)
lguest: check vaddr not pgd for Switcher protection.
We currently assume that the Switcher the top pgd; we want to remove this assumption, so check that vaddr is OK, rather then checking pgd index. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/lguest/page_tables.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index 3b62be160a6e..a2454a24a10c 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -95,13 +95,6 @@ static pgd_t *spgd_addr(struct lg_cpu *cpu, u32 i, unsigned long vaddr)
95{ 95{
96 unsigned int index = pgd_index(vaddr); 96 unsigned int index = pgd_index(vaddr);
97 97
98#ifndef CONFIG_X86_PAE
99 /* We kill any Guest trying to touch the Switcher addresses. */
100 if (index >= SWITCHER_PGD_INDEX) {
101 kill_guest(cpu, "attempt to access switcher pages");
102 index = 0;
103 }
104#endif
105 /* Return a pointer index'th pgd entry for the i'th page table. */ 98 /* Return a pointer index'th pgd entry for the i'th page table. */
106 return &cpu->lg->pgdirs[i].pgdir[index]; 99 return &cpu->lg->pgdirs[i].pgdir[index];
107} 100}
@@ -117,13 +110,6 @@ static pmd_t *spmd_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
117 unsigned int index = pmd_index(vaddr); 110 unsigned int index = pmd_index(vaddr);
118 pmd_t *page; 111 pmd_t *page;
119 112
120 /* We kill any Guest trying to touch the Switcher addresses. */
121 if (pgd_index(vaddr) == SWITCHER_PGD_INDEX &&
122 index >= SWITCHER_PMD_INDEX) {
123 kill_guest(cpu, "attempt to access switcher pages");
124 index = 0;
125 }
126
127 /* You should never call this if the PGD entry wasn't valid */ 113 /* You should never call this if the PGD entry wasn't valid */
128 BUG_ON(!(pgd_flags(spgd) & _PAGE_PRESENT)); 114 BUG_ON(!(pgd_flags(spgd) & _PAGE_PRESENT));
129 page = __va(pgd_pfn(spgd) << PAGE_SHIFT); 115 page = __va(pgd_pfn(spgd) << PAGE_SHIFT);
@@ -323,6 +309,10 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
323 pmd_t gpmd; 309 pmd_t gpmd;
324#endif 310#endif
325 311
312 /* We never demand page the Switcher, so trying is a mistake. */
313 if (vaddr >= switcher_addr)
314 return false;
315
326 /* First step: get the top-level Guest page table entry. */ 316 /* First step: get the top-level Guest page table entry. */
327 if (unlikely(cpu->linear_pages)) { 317 if (unlikely(cpu->linear_pages)) {
328 /* Faking up a linear mapping. */ 318 /* Faking up a linear mapping. */
@@ -495,10 +485,14 @@ static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr)
495{ 485{
496 pgd_t *spgd; 486 pgd_t *spgd;
497 unsigned long flags; 487 unsigned long flags;
498
499#ifdef CONFIG_X86_PAE 488#ifdef CONFIG_X86_PAE
500 pmd_t *spmd; 489 pmd_t *spmd;
501#endif 490#endif
491
492 /* You can't put your stack in the Switcher! */
493 if (vaddr >= switcher_addr)
494 return false;
495
502 /* Look at the current top level entry: is it present? */ 496 /* Look at the current top level entry: is it present? */
503 spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr); 497 spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr);
504 if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) 498 if (!(pgd_flags(*spgd) & _PAGE_PRESENT))
@@ -897,6 +891,12 @@ static void do_set_pte(struct lg_cpu *cpu, int idx,
897void guest_set_pte(struct lg_cpu *cpu, 891void guest_set_pte(struct lg_cpu *cpu,
898 unsigned long gpgdir, unsigned long vaddr, pte_t gpte) 892 unsigned long gpgdir, unsigned long vaddr, pte_t gpte)
899{ 893{
894 /* We don't let you remap the Switcher; we need it to get back! */
895 if (vaddr >= switcher_addr) {
896 kill_guest(cpu, "attempt to set pte into Switcher pages");
897 return;
898 }
899
900 /* 900 /*
901 * Kernel mappings must be changed on all top levels. Slow, but doesn't 901 * Kernel mappings must be changed on all top levels. Slow, but doesn't
902 * happen often. 902 * happen often.
@@ -995,12 +995,7 @@ void page_table_guest_data_init(struct lg_cpu *cpu)
995 * "pgd_index(lg->kernel_address)". This assumes it won't hit the 995 * "pgd_index(lg->kernel_address)". This assumes it won't hit the
996 * Switcher mappings, so check that now. 996 * Switcher mappings, so check that now.
997 */ 997 */
998#ifdef CONFIG_X86_PAE 998 if (cpu->lg->kernel_address >= switcher_addr)
999 if (pgd_index(cpu->lg->kernel_address) == SWITCHER_PGD_INDEX &&
1000 pmd_index(cpu->lg->kernel_address) == SWITCHER_PMD_INDEX)
1001#else
1002 if (pgd_index(cpu->lg->kernel_address) >= SWITCHER_PGD_INDEX)
1003#endif
1004 kill_guest(cpu, "bad kernel address %#lx", 999 kill_guest(cpu, "bad kernel address %#lx",
1005 cpu->lg->kernel_address); 1000 cpu->lg->kernel_address);
1006} 1001}