mm: Enforce MAP_PRIVATE xor MAP_SHARED (XCC) 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>
diff --git a/kern/src/arsc.c b/kern/src/arsc.c index d2f0b1c..c25db79 100644 --- a/kern/src/arsc.c +++ b/kern/src/arsc.c
@@ -35,7 +35,7 @@ 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));
diff --git a/kern/src/elf.c b/kern/src/elf.c index 18e3fbe..233b202 100644 --- a/kern/src/elf.c +++ b/kern/src/elf.c
@@ -42,7 +42,7 @@ 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 @@ 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 @@ 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 @@ /* 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. */
diff --git a/kern/src/mm.c b/kern/src/mm.c index 351a8cc..91b3d76 100644 --- a/kern/src/mm.c +++ b/kern/src/mm.c
@@ -328,6 +328,7 @@ 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 @@ 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 @@ 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 @@ * 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 @@ 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++;
diff --git a/kern/src/ucq.c b/kern/src/ucq.c index cabf077..fc456f4 100644 --- a/kern/src/ucq.c +++ b/kern/src/ucq.c
@@ -69,7 +69,8 @@ * 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 {
diff --git a/tests/vmm/vmrunkernel.c b/tests/vmm/vmrunkernel.c index 53f7242..584c95d 100644 --- a/tests/vmm/vmrunkernel.c +++ b/tests/vmm/vmrunkernel.c
@@ -248,7 +248,7 @@ 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 @@ /* 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);
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/i386/tls.h b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/i386/tls.h index 5d7000a..899f3eb 100644 --- a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/i386/tls.h +++ b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/i386/tls.h
@@ -473,8 +473,8 @@ * 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";
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c index 4c6fbb6..dbc17d5 100644 --- a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c +++ b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sbrk.c
@@ -78,7 +78,7 @@ 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; }
diff --git a/user/parlib/slab.c b/user/parlib/slab.c index 936981f..7d31652 100644 --- a/user/parlib/slab.c +++ b/user/parlib/slab.c
@@ -262,7 +262,7 @@ 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 @@ 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;
diff --git a/user/parlib/ucq.c b/user/parlib/ucq.c index dd4328d..42628fb 100644 --- a/user/parlib/ucq.c +++ b/user/parlib/ucq.c
@@ -45,7 +45,9 @@ { 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); }
diff --git a/user/parlib/vcore.c b/user/parlib/vcore.c index d2d9ef4..ac0b480 100644 --- a/user/parlib/vcore.c +++ b/user/parlib/vcore.c
@@ -103,8 +103,8 @@ 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 @@ 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 @@ 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);
diff --git a/user/pthread/pthread.c b/user/pthread/pthread.c index 7d9fdd8..79108d5 100644 --- a/user/pthread/pthread.c +++ b/user/pthread/pthread.c
@@ -444,8 +444,8 @@ 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 @@ /* 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 @@ #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);
diff --git a/user/vmm/biostables.c b/user/vmm/biostables.c index 6855b65..1ed67da 100644 --- a/user/vmm/biostables.c +++ b/user/vmm/biostables.c
@@ -202,7 +202,7 @@ // 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);
diff --git a/user/vmm/memory.c b/user/vmm/memory.c index ebfae19..7469c98 100644 --- a/user/vmm/memory.c +++ b/user/vmm/memory.c
@@ -127,7 +127,7 @@ 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 @@ 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);
diff --git a/user/vmm/pagetables.c b/user/vmm/pagetables.c index 2d20ca6..f7da0c5 100644 --- a/user/vmm/pagetables.c +++ b/user/vmm/pagetables.c
@@ -50,7 +50,7 @@ * 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);
diff --git a/user/vmm/sched.c b/user/vmm/sched.c index f93b20f..b44c44f 100644 --- a/user/vmm/sched.c +++ b/user/vmm/sched.c
@@ -107,7 +107,8 @@ 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 @@ 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;
diff --git a/user/vmm/vthread.c b/user/vmm/vthread.c index 5ef8d4c..105e32d 100644 --- a/user/vmm/vthread.c +++ b/user/vmm/vthread.c
@@ -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;