Allow file mmaps beyond the end of the file
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 4 Jul 2013 06:02:39 +0000 (23:02 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 11 Jul 2013 02:30:02 +0000 (19:30 -0700)
64 bit glibc libraries have an unaligned 2MB hole in the middle, and
ld.so just maps that extra space in the original mmap call, then
mprotects it to PROT_NONE.  Fair enough.

kern/arch/x86/ros/mmu64.h
kern/arch/x86/trap64.c
kern/src/mm.c

index 6164185..ad6997b 100644 (file)
@@ -94,7 +94,7 @@ typedef unsigned long pde_t;
  *    USTACKTOP        |                              |
  *                     |      Normal User Stack       | RW/RW 256 * PGSIZE
  *                     |                              |
- *                     +------------------------------+ 0x00007f7fffbfb000
+ *                     +------------------------------+ 0x00007f7fffaff000
  *                     |                              |
  *                     |        Empty Memory          |
  *                     |                              |
index 43334f2..cc8beb2 100644 (file)
@@ -136,7 +136,7 @@ void page_fault_handler(struct hw_trapframe *hw_tf)
        enable_irq();
        if ((err = handle_page_fault(current, fault_va, prot))) {
                /* Destroy the faulting process */
-               printk("[%08x] user %s fault va %08x ip %08x on core %d with err %d\n",
+               printk("[%08x] user %s fault va %p ip %p on core %d with err %d\n",
                       current->pid, prot & PROT_READ ? "READ" : "WRITE", fault_va,
                       hw_tf->tf_rip, core_id(), err);
                print_trapframe(hw_tf);
index 60c0cd7..815241f 100644 (file)
@@ -519,9 +519,13 @@ void *__do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                /* TODO: consider locking the file while checking (not as manadatory as
                 * in handle_page_fault() */
                if (nr_pages(offset + len) > nr_pages(file->f_dentry->d_inode->i_size)) {
-                       destroy_vmr(vmr);
-                       set_errno(ESPIPE); /* linux sends a SIGBUS at access time */
-                       return MAP_FAILED;
+                       /* We're allowing them to set up the VMR, though if they attempt to
+                        * fault in any pages beyond the file's limit, they'll fail.  Since
+                        * they might not access the region, we need to make sure POPULATE
+                        * is off.  FYI, 64 bit glibc shared libs map in an extra 2MB of
+                        * unaligned space between their RO and RW sections, but then
+                        * immediately mprotect it to PROT_NONE. */
+                       flags &= ~MAP_POPULATE;
                }
                kref_get(&file->f_kref, 1);
        }