Adds support for DANGEROUS annotation
authorZach Anderson <zra@intrepid.(none)>
Wed, 4 Mar 2009 00:21:31 +0000 (16:21 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 4 Mar 2009 00:21:31 +0000 (16:21 -0800)
Used to mark userspace pointers, which can't be dereferenced
until checked.  Also sorts some Makefrag and pgdir issues.
REBUILD YOUR IVY

kern/Makefrag
kern/env.c
kern/pmap.c
kern/pmap.h
kern/syscall.c

index 1db0863..3b94979 100644 (file)
@@ -6,10 +6,9 @@
 #
 
 OBJDIRS += kern
-#CC=ivycc --save-temps --trace --deputy 
-CC=ivycc 
+CC=ivycc --deputy
 
-KERN_LDFLAGS := $(LDFLAGS) -T kern/kernel.ld -nostdlib
+KERN_LDFLAGS := $(LDFLAGS) -Lobj/ivylib -T kern/kernel.ld -nostdlib
 
 # entry.S must be first, so that it's the first code in the text segment!!!
 #
@@ -72,9 +71,9 @@ $(OBJDIR)/kern/%.o: lib/%.c
        $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $<
 
 # How to build the kernel itself
-$(OBJDIR)/kern/kernel: $(KERN_OBJFILES) $(KERN_BINFILES) kern/kernel.ld
+$(OBJDIR)/kern/kernel: $(KERN_OBJFILES) $(KERN_BINFILES) kern/kernel.ld $(OBJDIR)/ivylib/libivykern.a
        @echo + ld $@
-       $(V)$(LD) -o $@ $(KERN_LDFLAGS) $(KERN_OBJFILES) $(GCC_LIB) -b binary $(KERN_BINFILES)
+       $(V)$(LD) -o $@ $(KERN_LDFLAGS) $(KERN_OBJFILES) -livykern $(GCC_LIB) -b binary $(KERN_BINFILES)
        $(V)$(OBJDUMP) -S $@ > $@.asm
        $(V)$(NM) -n $@ > $@.sym
 
@@ -85,6 +84,9 @@ $(OBJDIR)/kern/bochs.img: $(OBJDIR)/kern/kernel $(OBJDIR)/boot/boot
        $(V)dd if=$(OBJDIR)/boot/boot of=$(OBJDIR)/kern/bochs.img~ conv=notrunc 2>/dev/null
        $(V)dd if=$(OBJDIR)/kern/kernel of=$(OBJDIR)/kern/bochs.img~ seek=1 conv=notrunc 2>/dev/null
        $(V)mv $(OBJDIR)/kern/bochs.img~ $(OBJDIR)/kern/bochs.img
+# brho uses these
+#      $(V)cp $(OBJDIR)/kern/kernel mnt/hdd/texas
+#      $(V)sync
 
 all: $(OBJDIR)/kern/bochs.img
 
index 7b0f698..1c7257c 100644 (file)
@@ -386,6 +386,9 @@ env_free(struct Env *e)
                page_decref(pa2page(pa));
        }
 
+       // need a known good pgdir before releasing the old one
+       lcr3(boot_cr3);
+
        // free the page directory
        pa = e->env_cr3;
        e->env_pgdir = 0;
index 7064ef7..4114aee 100644 (file)
@@ -706,7 +706,7 @@ page_decref(struct Page* pp)
 //
 // Supports returning jumbo (4MB PSE) PTEs.  To create with a jumbo, pass in 2.
 pte_t*
-pgdir_walk(pde_t *pgdir, const void *va, int create)
+pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
 {
        pde_t* the_pde = &pgdir[PDX(va)];
        struct Page* new_table;
@@ -831,7 +831,7 @@ tlb_invalidate(pde_t *pgdir, void *va)
        invlpg(va);
 }
 
-static uintptr_t user_mem_check_addr;
+static void *DANGEROUS user_mem_check_addr;
 
 //
 // Check that an environment is allowed to access the range of memory
@@ -853,14 +853,21 @@ static uintptr_t user_mem_check_addr;
 //
 // Hint: The TA solution uses pgdir_walk.
 //
-int
-user_mem_check(struct Env *env, const void *va, size_t len, int perm)
+
+// zra: I've modified the interface to these two functions so that Ivy can
+// check that user pointers aren't dereferenced. User pointers get the
+// DANGEROUS qualifier. After validation, these functions return a
+// COUNT(len) pointer. user_mem_check now returns NULL on error instead of
+// -E_FAULT.
+
+void *COUNT(len)
+user_mem_check(struct Env *env, const void *DANGEROUS va, size_t len, int perm)
 {
        // 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;
+       void *DANGEROUS start, *DANGEROUS end;
        size_t num_pages, i;
        pte_t *pte;
 
@@ -869,7 +876,7 @@ user_mem_check(struct Env *env, const void *va, size_t len, int perm)
        end = ROUNDUP((void*)va + len, PGSIZE);
        if (start >= end) {
                warn("Blimey!  Wrap around in VM range calculation!");  
-               return -E_FAULT;
+               return NULL;
        }
        num_pages = PPN(end - start);
        for (i = 0; i < num_pages; i++, start += PGSIZE) {
@@ -877,18 +884,18 @@ user_mem_check(struct Env *env, const void *va, size_t len, int perm)
                // 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;
+                               user_mem_check_addr = va;
                        else
-                               user_mem_check_addr = (uintptr_t)start;
-                       return -E_FAULT;
+                               user_mem_check_addr = start;
+                       return NULL;
                }
        }
        // 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 NULL;
        }
-       return 0;
+       return (void *COUNT(len))TC(va);
 }
 
 //
@@ -897,14 +904,17 @@ user_mem_check(struct Env *env, const void *va, size_t len, int perm)
 // If it can, then the function simply returns.
 // If it cannot, 'env' is destroyed.
 //
-void
-user_mem_assert(struct Env *env, const void *va, size_t len, int perm)
+void *COUNT(len)
+user_mem_assert(struct Env *env, const void *DANGEROUS va, size_t len, int perm)
 {
-       if (user_mem_check(env, va, len, perm | PTE_U) < 0) {
+    void *COUNT(len) res = user_mem_check(env,va,len,perm | PTE_U);
+       if (!res) {
                cprintf("[%08x] user_mem_check assertion failure for "
                        "va %08x\n", curenv->env_id, user_mem_check_addr);
                env_destroy(env);       // may not return
+        return NULL;
        }
+    return res;
 }
 
 void
index 0b22383..2ddff47 100644 (file)
@@ -62,8 +62,11 @@ void page_decref(struct Page *pp);
 
 void   tlb_invalidate(pde_t *pgdir, void *va);
 
-int    user_mem_check(struct Env *env, const void *va, size_t len, int perm);
-void   user_mem_assert(struct Env *env, const void *va, size_t len, int perm);
+void *COUNT(len)
+user_mem_check(struct Env *env, const void *DANGEROUS va, size_t len, int perm);
+
+void *COUNT(len)
+user_mem_assert(struct Env *env, const void *DANGEROUS va, size_t len, int perm);
 
 static inline ppn_t
 page2ppn(struct Page *pp)
index a9e2c93..771c922 100644 (file)
@@ -1,8 +1,4 @@
 /* See COPYRIGHT for copyright information. */
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
 #include <inc/x86.h>
 #include <inc/error.h>
 #include <inc/string.h>
 // The string is exactly 'len' characters long.
 // Destroys the environment on memory errors.
 static void
-sys_cputs(const char *s, size_t len)
+sys_cputs(const char *DANGEROUS s, size_t len)
 {
        // Check that the user has permission to read memory [s, s+len).
        // Destroy the environment if not.
-       user_mem_assert(curenv, s, len, PTE_U);
+    char *COUNT(len) _s = user_mem_assert(curenv, s, len, PTE_U);
 
        // Print the string supplied by the user.
-       cprintf("%.*s", len, s);
+       cprintf("%.*s", len, _s);
 }
 
 // Read a character from the system console.
@@ -87,7 +83,7 @@ syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
        
        switch (syscallno) {
                case 0:
-                       sys_cputs((void*)a1, a2);
+                       sys_cputs(a1, a2);
                        return 0;
                case 1:
                        return sys_cgetc();