From 371ab7fa96f8e439f4008c973c37aa44ab6ed81e Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Thu, 1 Sep 2011 13:25:34 -0400 Subject: [PATCH] inaccessible page under the user stack page, to help exec deal w/ too-large args --- defs.h | 1 + exec.c | 9 ++++++--- usertests.c | 2 +- vm.c | 13 +++++++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/defs.h b/defs.h index 19d559b..4b3eec9 100644 --- a/defs.h +++ b/defs.h @@ -176,6 +176,7 @@ pde_t* copyuvm(pde_t*, uint); void switchuvm(struct proc*); void switchkvm(void); int copyout(pde_t*, uint, void*, uint); +void clear_pte_u(pde_t *pgdir, char *uva); // number of elements in fixed-size array #define NELEM(x) (sizeof(x)/sizeof((x)[0])) diff --git a/exec.c b/exec.c index dfff3e6..af9e006 100644 --- a/exec.c +++ b/exec.c @@ -49,13 +49,16 @@ exec(char *path, char **argv) iunlockput(ip); ip = 0; - // Allocate a one-page stack at the next page boundary + // Allocate two pages at the next page boundary. + // Make the first inaccessible. + // Use the second as the user stack. sz = PGROUNDUP(sz); - if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) + if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; + clear_pte_u(pgdir, (char*)(sz-2*PGSIZE)); + sp = sz; // Push argument strings, prepare rest of stack in ustack. - sp = sz; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; diff --git a/usertests.c b/usertests.c index 62ce8d7..ed13d80 100644 --- a/usertests.c +++ b/usertests.c @@ -1525,7 +1525,7 @@ bigargtest(void) for(i = 0; i < MAXARG-1; i++) args[i] = "bigargs test: failed\n "; args[MAXARG-1] = 0; - printf(stdout, "bigarg test %d\n", (MAXARG-1)*strlen(args[0])); + printf(stdout, "bigarg test\n"); exec("echo", args); printf(stdout, "bigarg test ok\n"); fd = open("bigarg-ok", O_CREATE); diff --git a/vm.c b/vm.c index 247fede..c717baf 100644 --- a/vm.c +++ b/vm.c @@ -363,3 +363,16 @@ copyout(pde_t *pgdir, uint va, void *p, uint len) } return 0; } + +// Clear PTE_U on a page. Used to create an inaccessible +// page beneath the user stack. +void +clear_pte_u(pde_t *pgdir, char *uva) +{ + pte_t *pte; + + pte = walkpgdir(pgdir, uva, 0); + if(pte == 0) + panic("clear_pte_u"); + *pte &= ~PTE_U; +}