From f199fc0bfe220dfd66c349ba09df798e17b0c888 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Tue, 25 Feb 2014 15:04:02 +0100 Subject: [PATCH] VM: fix corruption from recursive PDE allocation Change-Id: I6176b849fefca4bed3e92648b0d72ff47658915c --- servers/vm/pagetable.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/servers/vm/pagetable.c b/servers/vm/pagetable.c index 192fcd6c6..489249626 100644 --- a/servers/vm/pagetable.c +++ b/servers/vm/pagetable.c @@ -487,6 +487,7 @@ static int pt_ptalloc(pt_t *pt, int pde, u32_t flags) /* Allocate a page table and write its address into the page directory. */ int i; phys_bytes pt_phys; + u32_t *p; /* Argument must make sense. */ assert(pde >= 0 && pde < ARCH_VM_DIR_ENTRIES); @@ -498,9 +499,18 @@ static int pt_ptalloc(pt_t *pt, int pde, u32_t flags) assert(!(pt->pt_dir[pde] & ARCH_VM_PDE_PRESENT)); assert(!pt->pt_pt[pde]); - /* Get storage for the page table. */ - if(!(pt->pt_pt[pde] = vm_allocpage(&pt_phys, VMP_PAGETABLE))) + /* Get storage for the page table. The allocation call may in fact + * recursively create the directory entry as a side effect. In that + * case, we free the newly allocated page and do nothing else. + */ + if (!(p = vm_allocpage(&pt_phys, VMP_PAGETABLE))) return ENOMEM; + if (pt->pt_pt[pde]) { + vm_freepages((vir_bytes) p, 1); + assert(pt->pt_pt[pde]); + return OK; + } + pt->pt_pt[pde] = p; for(i = 0; i < ARCH_VM_PT_ENTRIES; i++) pt->pt_pt[pde][i] = 0; /* Empty entry. */ -- 2.44.0