mm: Enforce MAP_PRIVATE xor MAP_SHARED (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 1 Aug 2017 21:11:45 +0000 (17:11 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 14 Aug 2017 21:02:20 +0000 (17:02 -0400)
We're only supposed to accept PRIVATE xor SHARED, but we were allowing
neither, and possibly both.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
16 files changed:
kern/src/arsc.c
kern/src/elf.c
kern/src/mm.c
kern/src/ucq.c
tests/vmm/vmrunkernel.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/i386/tls.h
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c
user/parlib/slab.c
user/parlib/ucq.c
user/parlib/vcore.c
user/pthread/pthread.c
user/vmm/biostables.c
user/vmm/memory.c
user/vmm/pagetables.c
user/vmm/sched.c
user/vmm/vthread.c

index d2f0b1c..c25db79 100644 (file)
@@ -35,7 +35,7 @@ syscall_sring_t* sys_init_arsc(struct proc *p)
        void * va;
        // TODO: need to pin this page in the future when swapping happens
        va = do_mmap(p,MMAP_LOWEST_VA, SYSCALLRINGSIZE, PROT_READ | PROT_WRITE,
-                    MAP_ANONYMOUS | MAP_POPULATE, NULL, 0);
+                    MAP_ANONYMOUS | MAP_POPULATE | MAP_PRIVATE, NULL, 0);
        pte_t pte = pgdir_walk(p->env_pgdir, (void*)va, 0);
        assert(pte_walk_okay(pte));
        sring = (syscall_sring_t*) KADDR(pte_get_paddr(pte));
index 18e3fbe..233b202 100644 (file)
@@ -42,7 +42,7 @@ static uintptr_t populate_stack(struct proc *p, int argc, char *argv[],
                                                 int auxc, elf_aux_t auxv[])
 {
        /* Map in pages for p's stack. */
-       int flags = MAP_FIXED | MAP_ANONYMOUS;
+       int flags = MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE;
        uintptr_t stacksz = USTACK_NUM_PAGES*PGSIZE;
        if (do_mmap(p, USTACKTOP-stacksz, stacksz, PROT_READ | PROT_WRITE,
                    flags, NULL, 0) == MAP_FAILED)
@@ -144,7 +144,7 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
        ei->highest_addr = 0;
        off64_t f_off = 0;
        void* phdrs = 0;
-       int mm_perms, mm_flags = MAP_FIXED;
+       int mm_perms, mm_flags;
 
        /* When reading on behalf of the kernel, we need to switch to a ktask so
         * the VFS (and maybe other places) know. (TODO: KFOP) */
@@ -216,7 +216,8 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
                p_flags |= (writable ? ELF_PROT_WRITE : 0);
                /* All mmaps need to be fixed to their VAs.  If the program wants it to
                 * be a writable region, we also need the region to be private. */
-               mm_flags = MAP_FIXED | (p_flags & ELF_PROT_WRITE ? MAP_PRIVATE : 0);
+               mm_flags = MAP_FIXED |
+                          (p_flags & ELF_PROT_WRITE ? MAP_PRIVATE : MAP_SHARED);
 
                if (p_type == ELF_PROG_PHDR)
                        ei->phdr = p_va;
@@ -288,6 +289,7 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pg_num,
                                        /* Need our own populated, private copy of the page so that
                                         * we can zero the remainder - and not zero chunks of the
                                         * real file in the page cache. */
+                                       mm_flags &= ~MAP_SHARED;
                                        mm_flags |= MAP_PRIVATE | MAP_POPULATE;
 
                                        /* Map the final partial page. */
index 351a8cc..91b3d76 100644 (file)
@@ -328,6 +328,7 @@ static int fill_vmr(struct proc *p, struct proc *new_p, struct vm_region *vmr)
        int ret = 0;
 
        if ((!vmr->vm_file) || (vmr->vm_flags & MAP_PRIVATE)) {
+               /* We don't support ANON + SHARED yet */
                assert(!(vmr->vm_flags & MAP_SHARED));
                ret = copy_pages(p, new_p, vmr->vm_base, vmr->vm_end);
        } else {
@@ -422,6 +423,12 @@ void enumerate_vmrs(struct proc *p,
        spin_unlock(&p->vmr_lock);
 }
 
+static bool mmap_flags_priv_ok(int flags)
+{
+       return (flags & (MAP_PRIVATE | MAP_SHARED)) == MAP_PRIVATE ||
+              (flags & (MAP_PRIVATE | MAP_SHARED)) == MAP_SHARED;
+}
+
 /* Error values aren't quite comprehensive - check man mmap() once we do better
  * with the FS.
  *
@@ -436,9 +443,14 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
            int fd, size_t offset)
 {
        struct file *file = NULL;
+
        offset <<= PGSHIFT;
        printd("mmap(addr %x, len %x, prot %x, flags %x, fd %x, off %x)\n", addr,
               len, prot, flags, fd, offset);
+       if (!mmap_flags_priv_ok(flags)) {
+               set_errno(EINVAL);
+               return MAP_FAILED;
+       }
        if (fd >= 0 && (flags & MAP_ANON)) {
                set_errno(EBADF);
                return MAP_FAILED;
@@ -463,7 +475,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
         * We could just have userspace handle this (in glibc's mmap), so we don't
         * need to know about BRK_END, but this will work for now (and may avoid
         * bugs).  Note that this limits mmap(0) a bit.  Keep this in sync with
-        * __do_mmap()'s check.  (Both are necessary).  */
+        * do_mmap()'s check.  (Both are necessary).  */
        if (addr == 0)
                addr = BRK_END;
        /* Still need to enforce this: */
@@ -663,6 +675,7 @@ void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
        len = ROUNDUP(len, PGSIZE);
        struct vm_region *vmr, *vmr_temp;
 
+       assert(mmap_flags_priv_ok(flags));
        /* read/write vmr lock (will change the tree) */
        spin_lock(&p->vmr_lock);
        p->vmr_history++;
index cabf077..fc456f4 100644 (file)
@@ -69,7 +69,8 @@ grab_lock:
                 * the proc_lock, and potentially deadlock the system. */
                new_page = (struct ucq_page*)do_mmap(p, 0, PGSIZE,
                                                     PROT_READ | PROT_WRITE,
-                                                    MAP_ANON | MAP_POPULATE, 0, 0);
+                                                    MAP_ANONYMOUS | MAP_POPULATE |
+                                                    MAP_PRIVATE, NULL, 0);
                assert(new_page);
                assert(!PGOFF(new_page));
        } else {
index 53f7242..584c95d 100644 (file)
@@ -248,7 +248,7 @@ void alloc_intr_pages(void)
        void *pages, *pir;
 
        a_page = mmap((void *)APIC_GPA, PGSIZE, PROT_READ | PROT_WRITE,
-                     MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                     MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        fprintf(stderr, "a_page mmap pointer %p\n", a_page);
 
        if (a_page != (void *)APIC_GPA) {
@@ -261,7 +261,7 @@ void alloc_intr_pages(void)
 
        /* Allocate VAPIC and PIR pages. */
        pages = mmap((void*)0, vm->nr_gpcs * 2 * PGSIZE, PROT_READ | PROT_WRITE,
-                    MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                    MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (pages == MAP_FAILED) {
                perror("Unable to map VAPIC and PIR pages.");
                exit(1);
index 5d7000a..899f3eb 100644 (file)
@@ -473,8 +473,8 @@ static const char* tls_init_tp(void* thrdescr)
         * setting it up...) */
        void *ldt = (void*)__ros_syscall_noerrno(SYS_mmap, 0, sz,
                                                 PROT_READ | PROT_WRITE,
-                                                MAP_ANONYMOUS | MAP_POPULATE,
-                                                -1, 0);
+                                                MAP_ANONYMOUS | MAP_POPULATE |
+                                                MAP_PRIVATE, -1, 0);
     if (ldt == MAP_FAILED)
       return "tls couldn't allocate memory\n";
 
index 4c6fbb6..dbc17d5 100644 (file)
@@ -78,7 +78,7 @@ __internal_setbrk (uintptr_t addr)
     if ((void*)__ros_syscall_noerrno(SYS_mmap, (long)real_brk,
                                         real_new_brk-real_brk,
                                         PROT_READ | PROT_WRITE | PROT_EXEC,
-                                        MAP_FIXED | MAP_ANONYMOUS,
+                                        MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE,
                                         -1, 0) != (void*)real_brk)
       return -1;
   }
index 936981f..7d31652 100644 (file)
@@ -262,7 +262,7 @@ static void kmem_cache_grow(struct kmem_cache *cp)
        if (cp->obj_size <= SLAB_LARGE_CUTOFF) {
                // Just get a single page for small slabs
                a_page = mmap(0, PGSIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
-                             MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                             MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
                assert(a_page != MAP_FAILED);
                // the slab struct is stored at the end of the page
                a_slab = (struct kmem_slab*)(a_page + PGSIZE -
@@ -302,7 +302,7 @@ static void kmem_cache_grow(struct kmem_cache *cp)
                size_t nr_pgs = ROUNDUP(NUM_BUF_PER_SLAB * a_slab->obj_size, PGSIZE) /
                                         PGSIZE;
                void *buf = mmap(0, nr_pgs * PGSIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
-                                MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                                MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
                assert(buf != MAP_FAILED);
                a_slab->num_busy_obj = 0;
                a_slab->num_total_obj = nr_pgs * PGSIZE / a_slab->obj_size;
index dd4328d..42628fb 100644 (file)
@@ -45,7 +45,9 @@ void ucq_init(struct ucq *ucq)
 {
        uintptr_t two_pages = (uintptr_t)mmap(0, PGSIZE * 2,
                                              PROT_WRITE | PROT_READ,
-                                             MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                                             MAP_POPULATE | MAP_ANONYMOUS |
+                                             MAP_PRIVATE, -1, 0);
+
        assert(two_pages);
        ucq_init_raw(ucq, two_pages, two_pages + PGSIZE);
 }
index d2d9ef4..ac0b480 100644 (file)
@@ -103,8 +103,8 @@ static int allocate_vcore_stack(int id)
                return 0; // reuse old stack
 
        void* stackbot = mmap(0, TRANSITION_STACK_SIZE,
-                             PROT_READ|PROT_WRITE|PROT_EXEC,
-                             MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
+                             PROT_READ | PROT_WRITE | PROT_EXEC,
+                             MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 
        if(stackbot == MAP_FAILED)
                return -1; // errno set by mmap
@@ -152,7 +152,8 @@ static void prep_vcore_0(void)
 
        mmap_block = (uintptr_t)mmap(0, PGSIZE * 4,
                                     PROT_WRITE | PROT_READ,
-                                    MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                                    MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE,
+                                    -1, 0);
        assert((void*)mmap_block != MAP_FAILED);
        __prep_vcore(0, mmap_block);
 }
@@ -163,7 +164,8 @@ static void prep_remaining_vcores(void)
 
        mmap_block = (uintptr_t)mmap(0, PGSIZE * 4 * (max_vcores() - 1),
                                     PROT_WRITE | PROT_READ,
-                                    MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                                    MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE,
+                                    -1, 0);
        assert((void*)mmap_block != MAP_FAILED);
        for (int i = 1; i < max_vcores(); i++)
                __prep_vcore(i, mmap_block + 4 * (i - 1) * PGSIZE);
index 7d9fdd8..79108d5 100644 (file)
@@ -444,8 +444,8 @@ static int __pthread_allocate_stack(struct pthread_tcb *pt)
        int force_a_page_fault;
        assert(pt->stacksize);
        void* stackbot = mmap(0, pt->stacksize,
-                             PROT_READ|PROT_WRITE|PROT_EXEC,
-                             MAP_ANONYMOUS, -1, 0);
+                             PROT_READ | PROT_WRITE | PROT_EXEC,
+                             MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (stackbot == MAP_FAILED)
                return -1; // errno set by mmap
        pt->stacktop = stackbot + pt->stacksize;
@@ -547,7 +547,8 @@ void pth_sched_init(void)
        /* Get a block of pages for our per-vcore (but non-VCPD) ev_qs */
        mmap_block = (uintptr_t)mmap(0, PGSIZE * 2 * max_vcores(),
                                     PROT_WRITE | PROT_READ,
-                                    MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                                    MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE,
+                                    -1, 0);
        assert(mmap_block);
        /* Could be smarter and do this on demand (in case we don't actually want
         * max_vcores()). */
@@ -568,7 +569,8 @@ void pth_sched_init(void)
 #if 0   /* One global ev_mbox, separate ev_q per vcore */
        struct event_mbox *sysc_mbox = malloc(sizeof(struct event_mbox));
        uintptr_t two_pages = (uintptr_t)mmap(0, PGSIZE * 2, PROT_WRITE | PROT_READ,
-                                             MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                                             MAP_POPULATE | MAP_ANONYMOUS |
+                                             MAP_PRIVATE, -1, 0);
        printd("Global ucq: %08p\n", &sysc_mbox->ev_msgs);
        assert(sysc_mbox);
        assert(two_pages);
index 6855b65..1ed67da 100644 (file)
@@ -202,7 +202,7 @@ void *setup_biostables(struct virtual_machine *vm,
        // And, sorry, due to the STUPID format of the RSDP for now we need the low
        // 1M.
        low1m = mmap((int*)4096, MiB-4096, PROT_READ | PROT_WRITE,
-                    MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                    MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (low1m != (void *)4096) {
                perror("Unable to mmap low 1m");
                exit(1);
index ebfae19..7469c98 100644 (file)
@@ -127,7 +127,7 @@ void mmap_memory(unsigned long long memstart, unsigned long long memsize)
                r1size = memstart < RESERVED ? RESERVED - memstart : 0;
                r2 = mmap((void *)r2start, memsize - r1size,
                          PROT_READ | PROT_WRITE | PROT_EXEC,
-                         MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                         MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
                if (r2 != (void *)r2start) {
                        fprintf(stderr,
                                "High region: Could not mmap 0x%lx bytes at 0x%lx\n",
@@ -140,7 +140,7 @@ void mmap_memory(unsigned long long memstart, unsigned long long memsize)
 
        r1 = mmap((void *)memstart, r1size,
                      PROT_READ | PROT_WRITE | PROT_EXEC,
-                     MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                     MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (r1 != (void *)memstart) {
                fprintf(stderr, "Low region: Could not mmap 0x%lx bytes at 0x%lx\n",
                        memsize, memstart);
index 2d20ca6..f7da0c5 100644 (file)
@@ -50,7 +50,7 @@ void *setup_paging(unsigned long long memstart, unsigned long long memsize,
         * used to use posix_memalign but that puts them
         * outside EPT-accessible space on some CPUs. */
        p512 = mmap((void *)memstart + memsize, nptp * 4096, PROT_READ | PROT_WRITE,
-                    MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                    MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (p512 == MAP_FAILED) {
                perror("page table page alloc");
                exit(1);
index f93b20f..b44c44f 100644 (file)
@@ -107,7 +107,8 @@ static struct event_queue *setup_sysc_evq(int vcoreid)
 
        mmap_block = (uintptr_t)mmap(0, PGSIZE * 2,
                                     PROT_WRITE | PROT_READ,
-                                    MAP_POPULATE | MAP_ANONYMOUS, -1, 0);
+                                    MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE,
+                                    -1, 0);
        evq = get_eventq_raw();
        assert(mmap_block && evq);
        evq->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR | EVENT_WAKEUP;
@@ -637,7 +638,7 @@ static void *__alloc_stack(size_t stacksize)
        int force_a_page_fault;
        void *stacktop;
        void *stackbot = mmap(0, stacksize, PROT_READ | PROT_WRITE | PROT_EXEC,
-                             MAP_ANONYMOUS, -1, 0);
+                             MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 
        if (stackbot == MAP_FAILED)
                return 0;
index 5ef8d4c..105e32d 100644 (file)
@@ -16,7 +16,7 @@
 static void *page(void *addr, int count)
 {
        void *v;
-       unsigned long flags = MAP_POPULATE | MAP_ANONYMOUS;
+       unsigned long flags = MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE;
 
        if (addr)
                flags |= MAP_FIXED;