Unmap pages mapped during a failed fill_vmr() master origin/master current
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 6 Nov 2019 18:25:25 +0000 (13:25 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 6 Nov 2019 18:43:32 +0000 (13:43 -0500)
If we get part of the way through filling the VMR with the parent's
contents, but then run out of memory, we were leaving the old,
successful PTE mappings behind.  The VMR would be freed and never
added to the proc's list, so we wouldn't unmap it during __proc_free().
However, our assert would catch that the process still has mapped pages
that weren't a part of any VMR.

I'm not 100% that this is what happened with syzkaller, but it's a
likely scenario, especially since other bugs it found recently are due
to running low/out of memory.

Reported-by: syzbot+28ec6ca66d7b660fbf4d@syzkaller.appspotmail.com
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/mm.c

index b5249ed..648745a 100644 (file)
@@ -573,6 +573,15 @@ static int fill_vmr(struct proc *p, struct proc *new_p, struct vm_region *vmr)
                        foc_decref(vmr->__vm_foc);
                }
        }
+       if (ret < 0) {
+               /* Need to undo any mappings we left behind.  We don't know
+                * where we died, but we can just blast the entire region */
+               spin_lock(&new_p->pte_lock);
+               env_user_mem_walk(new_p, (void*)vmr->vm_base,
+                                 vmr->vm_end - vmr->vm_base,
+                                 __vmr_free_pgs, NULL);
+               spin_unlock(&new_p->pte_lock);
+       }
        return ret;
 }