--- Net2/vm/vm_mmap.c 2018/04/24 18:06:46 1.1.1.2 +++ Net2/vm/vm_mmap.c 2018/04/24 18:09:20 1.1.1.3 @@ -121,8 +121,10 @@ smmap(p, uap, retval) vm_offset_t addr; vm_size_t size; vm_prot_t prot; + vm_prot_t maxprot; caddr_t handle; int mtype, error; + int flags = uap->flags; #ifdef DEBUG if (mmapdebug & MDB_FOLLOW) @@ -133,7 +135,7 @@ smmap(p, uap, retval) /* * Make sure one of the sharing types is specified */ - mtype = uap->flags & MAP_TYPE; + mtype = flags & MAP_TYPE; switch (mtype) { case MAP_FILE: case MAP_ANON: @@ -146,9 +148,11 @@ smmap(p, uap, retval) * Size is implicitly rounded to a page boundary. */ addr = (vm_offset_t) uap->addr; - if ((uap->flags & MAP_FIXED) && (addr & page_mask) || uap->len < 0) + if ((flags & MAP_FIXED) && (addr & page_mask) || uap->len < 0) return(EINVAL); size = (vm_size_t) round_page(uap->len); + if ((flags & MAP_FIXED) && (addr + size > VM_MAXUSER_ADDRESS)) + return EINVAL; /* * XXX if no hint provided for a non-fixed mapping place it after * the end of the largest possible heap. @@ -156,7 +160,7 @@ smmap(p, uap, retval) * There should really be a pmap call to determine a reasonable * location. */ - if (addr == 0 && (uap->flags & MAP_FIXED) == 0) + if (addr == 0 && (flags & MAP_FIXED) == 0) addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ); /* * Mapping file or named anonymous, get fp for validation @@ -185,14 +189,27 @@ smmap(p, uap, retval) * if mapping is shared. */ if ((uap->prot & PROT_READ) && (fp->f_flag & FREAD) == 0 || - ((uap->flags & MAP_SHARED) && + ((flags & MAP_SHARED) && (uap->prot & PROT_WRITE) && (fp->f_flag & FWRITE) == 0)) return(EACCES); + if ((flags & MAP_SHARED) && (fp->f_flag & FWRITE) == 0) + flags = (flags & ~MAP_SHARED) | MAP_PRIVATE; handle = (caddr_t)vp; - } else if (uap->fd != -1) + /* + * Map protections to MACH style + */ + maxprot = VM_PROT_EXECUTE; + if (fp->f_flag & FREAD) + maxprot |= VM_PROT_READ; + if (fp->f_flag & FWRITE) + maxprot |= VM_PROT_WRITE; + } else if (uap->fd != -1) { + maxprot = VM_PROT_ALL; handle = (caddr_t)fp; - else + } else { + maxprot = VM_PROT_ALL; handle = NULL; + } /* * Map protections to MACH style */ @@ -204,8 +221,8 @@ smmap(p, uap, retval) if (uap->prot & PROT_EXEC) prot |= VM_PROT_EXECUTE; - error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, - uap->flags, handle, (vm_offset_t)uap->pos); + error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot, + flags, handle, (vm_offset_t)uap->pos); if (error == 0) *retval = (int) addr; return(error); @@ -306,6 +323,8 @@ munmap(p, uap, retval) size = (vm_size_t) round_page(uap->len); if (size == 0) return(0); + if (addr + size >= VM_MAXUSER_ADDRESS) + return EINVAL; if (!vm_map_is_allocated(&p->p_vmspace->vm_map, addr, addr+size, FALSE)) return(EINVAL); @@ -409,11 +428,12 @@ mincore(p, uap, retval) * MAP_FILE: a vnode pointer * MAP_ANON: NULL or a file pointer */ -vm_mmap(map, addr, size, prot, flags, handle, foff) +vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff) register vm_map_t map; register vm_offset_t *addr; register vm_size_t size; vm_prot_t prot; + vm_prot_t maxprot; register int flags; caddr_t handle; /* XXX should be vp */ vm_offset_t foff; @@ -474,6 +494,13 @@ vm_mmap(map, addr, size, prot, flags, ha goto out; } /* + * The object of unnamed anonymous regions was just created + * find it for pager_cache. + */ + if (handle == NULL) + object = vm_object_lookup(pager); + + /* * Don't cache anonymous objects. * Loses the reference gained by vm_pager_allocate. */ @@ -625,13 +652,24 @@ vm_mmap(map, addr, size, prot, flags, ha * entirely correct. Maybe the maximum protection should be based * on the object permissions where it makes sense (e.g. a vnode). * - * Changed my mind: leave max prot at VM_PROT_ALL. + * XXX Changed my mind: leave max prot at VM_PROT_ALL. + * Changed again: indeed set maximum protection based on + * object permissions. */ - if (prot != VM_PROT_ALL) { rv = vm_map_protect(map, *addr, *addr+size, prot, FALSE); if (rv != KERN_SUCCESS) { (void) vm_deallocate(map, *addr, size); goto out; + } + /* + * We only need to set max_protection in case it's + * unequal to its default, which is VM_PROT_DEFAULT. + */ + if(maxprot != VM_PROT_DEFAULT) { + rv = vm_map_protect(map, *addr, *addr+size, maxprot, TRUE); + if (rv != KERN_SUCCESS) { + (void) vm_deallocate(map, *addr, size); + goto out; } } /*