Memory protection and page fault handling
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 23 Feb 2009 09:13:13 +0000 (01:13 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 23 Feb 2009 09:13:13 +0000 (01:13 -0800)
Moved and improved the user memory check function, new panics on kernel
page faults, and processes learn their Env* early on.  User processes
provide some testing.

kern/env.c
kern/init.c
kern/pmap.c
kern/syscall.c
kern/trap.c
lib/libmain.c
user/evilhello.c
user/hello.c

index b086a2d..b800b16 100644 (file)
@@ -218,7 +218,7 @@ segment_alloc(struct Env *e, void *va, size_t len)
        end = ROUNDUP(va + len, PGSIZE);
        if (start >= end)
                panic("Wrap-around in memory allocation addresses!");
        end = ROUNDUP(va + len, PGSIZE);
        if (start >= end)
                panic("Wrap-around in memory allocation addresses!");
-       if ((uint32_t)end > UTOP)
+       if ((uintptr_t)end > UTOP)
                panic("Attempting to map above UTOP!");
        // page_insert/pgdir_walk alloc a page and read/write to it via its address
        // starting from pgdir (e's), so we need to be using e's pgdir
                panic("Attempting to map above UTOP!");
        // page_insert/pgdir_walk alloc a page and read/write to it via its address
        // starting from pgdir (e's), so we need to be using e's pgdir
index f95e590..2abdd67 100644 (file)
@@ -54,6 +54,8 @@ void kernel_init(multiboot_info_t *mboot_info)
        //ENV_CREATE(user_badsegment);
        //ENV_CREATE(user_divzero);
        ENV_CREATE(user_hello);
        //ENV_CREATE(user_badsegment);
        //ENV_CREATE(user_divzero);
        ENV_CREATE(user_hello);
+       ENV_CREATE(user_buggyhello);
+       ENV_CREATE(user_evilhello);
 #endif // TEST*
 
        // We only have one user environment for now, so just run it.
 #endif // TEST*
 
        // We only have one user environment for now, so just run it.
index 9c53cb3..62c6a91 100644 (file)
@@ -853,8 +853,38 @@ static uintptr_t user_mem_check_addr;
 int
 user_mem_check(struct Env *env, const void *va, size_t len, int perm)
 {
 int
 user_mem_check(struct Env *env, const void *va, size_t len, int perm)
 {
-       // LAB 3: Your code here. 
+       // TODO - will need to sort this out wrt page faulting / PTE_P
+       // also could be issues with sleeping and waking up to find pages
+       // are unmapped, though i think the lab ignores this since the 
+       // kernel is uninterruptible
+       void *start, *end;
+       size_t num_pages, i;
+       pte_t *pte;
 
 
+       perm |= PTE_P;
+       start = ROUNDDOWN((void*)va, PGSIZE);
+       end = ROUNDUP((void*)va + len, PGSIZE);
+       if (start >= end) {
+               warn("Blimey!  Wrap around in VM range calculation!");  
+               return -E_FAULT;
+       }
+       num_pages = PPN(end - start);
+       for (i = 0; i < num_pages; i++, start += PGSIZE) {
+               pte = pgdir_walk(env->env_pgdir, start, 0);
+               // ensures the bits we want on are turned on.  if not, E_FAULT
+               if ( !pte || ((*pte & perm) != perm) ) {
+                       if (i = 0)
+                               user_mem_check_addr = (uintptr_t)va;
+                       else
+                               user_mem_check_addr = (uintptr_t)start;
+                       return -E_FAULT;
+               }
+       }
+       // this should never be needed, since the perms should catch it
+       if ((uintptr_t)end >= ULIM) {
+               warn ("I suck - Bug in user permission mappings!");
+               return -E_FAULT;
+       }
        return 0;
 }
 
        return 0;
 }
 
index b0a332b..ff4d85d 100644 (file)
@@ -19,21 +19,7 @@ sys_cputs(const char *s, size_t len)
 {
        // Check that the user has permission to read memory [s, s+len).
        // Destroy the environment if not.
 {
        // Check that the user has permission to read memory [s, s+len).
        // Destroy the environment if not.
-       
-       void *start, *end;
-       size_t num_pages, i;
-       pte_t *pte;
-
-       start = ROUNDDOWN((void*)s, PGSIZE);
-       end = ROUNDUP((void*)s + len, PGSIZE);
-       if (start >= end)
-               env_destroy(curenv);
-       num_pages = PPN(end - start);
-       for (i = 0; i < num_pages; i++, start += PGSIZE) {
-               pte = pgdir_walk(curenv->env_pgdir, start, 0);
-               if ( !pte || !(*pte & PTE_P) || !(*pte & PTE_U) ) 
-                       env_destroy(curenv);
-       }
+       user_mem_assert(curenv, s, len, PTE_U);
 
        // Print the string supplied by the user.
        cprintf("%.*s", len, s);
 
        // Print the string supplied by the user.
        cprintf("%.*s", len, s);
index 8a7187a..3c168a9 100644 (file)
@@ -206,7 +206,9 @@ page_fault_handler(struct Trapframe *tf)
 
        // Handle kernel-mode page faults.
        
 
        // Handle kernel-mode page faults.
        
-       // LAB 3: Your code here.
+       // TODO - one day, we'll want to handle this.
+       if ((tf->tf_cs & 3) == 0)
+               panic("Page Fault in the Kernel!");
 
        // We've already handled kernel-mode exceptions, so if we get here,
        // the page fault happened in user mode.
 
        // We've already handled kernel-mode exceptions, so if we get here,
        // the page fault happened in user mode.
index e5c3bf4..4eb61fb 100644 (file)
@@ -12,8 +12,8 @@ void
 libmain(int argc, char **argv)
 {
        // set env to point at our env structure in envs[].
 libmain(int argc, char **argv)
 {
        // set env to point at our env structure in envs[].
-       // LAB 3: Your code here.
-       env = 0;
+       
+       env = &envs[ENVX(sys_getenvid())];
 
        // save the name of the program so that panic() can use it
        if (argc > 0)
 
        // save the name of the program so that panic() can use it
        if (argc > 0)
index 4663e10..6d6ce39 100644 (file)
@@ -7,6 +7,6 @@ void
 umain(void)
 {
        // try to print the kernel entry point as a string!  mua ha ha!
 umain(void)
 {
        // try to print the kernel entry point as a string!  mua ha ha!
-       sys_cputs((char*)0xf0100020, 100);
+       sys_cputs((char*)0xc0100020, 100);
 }
 
 }
 
index 9df9780..eef92ed 100644 (file)
@@ -5,6 +5,6 @@ void
 umain(void)
 {
        cprintf("goodbye, world!\n");
 umain(void)
 {
        cprintf("goodbye, world!\n");
-       // this is just their way of generating a pagefault...
+       // this is just their way of generating a pagefault..., until now!
        cprintf("i am environment %08x\n", env->env_id);
 }
        cprintf("i am environment %08x\n", env->env_id);
 }