From: David van Moolenbroek Date: Tue, 25 Feb 2014 14:04:02 +0000 (+0100) Subject: VM: fix corruption from recursive PDE allocation X-Git-Tag: v3.3.0~412 X-Git-Url: http://zhaoyanbai.com/repos/man.rndc-confgen.html?a=commitdiff_plain;h=f199fc0bfe220dfd66c349ba09df798e17b0c888;p=minix.git VM: fix corruption from recursive PDE allocation Change-Id: I6176b849fefca4bed3e92648b0d72ff47658915c --- 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. */