don't panic if a program frees all its memory with sbrk().

if a program sbrk()'s to a non-page-boundary, don't free that page.
corresponding usertests.
This commit is contained in:
Robert Morris 2019-09-20 11:35:27 -04:00
parent ca30cac702
commit 4de161f973
3 changed files with 45 additions and 4 deletions

View file

@ -232,9 +232,7 @@ growproc(int n)
return -1;
}
} else if(n < 0){
if((sz = uvmdealloc(p->pagetable, sz, sz + n)) == 0) {
return -1;
}
sz = uvmdealloc(p->pagetable, sz, sz + n);
}
p->sz = sz;
return 0;

View file

@ -268,7 +268,10 @@ uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
{
if(newsz >= oldsz)
return oldsz;
uvmunmap(pagetable, newsz, oldsz - newsz, 1);
uint64 newup = PGROUNDUP(newsz);
uvmunmap(pagetable, newup, oldsz - newup, 1);
return newsz;
}

View file

@ -1923,6 +1923,45 @@ pgbug(char *s)
exit(0);
}
// does the kernel panic if a process sbrk()s its size to be less than
// a page, or zero?
void
zerosize(char *s)
{
int pid = fork();
if(pid < 0){
printf("fork failed\n");
exit(1);
}
if(pid == 0){
int sz = (uint64) sbrk(0);
// free all user memory; there used to be a bug that
// would not adjust p->sz correctly in this case,
// causing exit() to panic.
sbrk(-sz);
// user page fault here.
exit(0);
}
wait(0);
pid = fork();
if(pid < 0){
printf("fork failed\n");
exit(1);
}
if(pid == 0){
int sz = (uint64) sbrk(0);
// set the break to somewhere in the very first
// page; there used to be a bug that would incorrectly
// free the first page.
sbrk(-(sz - 3500));
exit(0);
}
wait(0);
exit(0);
}
// run each test in its own process. run returns 1 if child's exit()
// indicates success.
int
@ -1961,6 +2000,7 @@ main(int argc, char *argv[])
char *s;
} tests[] = {
{pgbug, "pgbug" },
{zerosize, "zerosize" },
{reparent, "reparent" },
{twochildren, "twochildren"},
{forkfork, "forkfork"},