X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6d2010ae8f7a6078e10b361c6962983bab233e0f..8a3053a07cee346dca737a5670e546fd26a7c9d6:/bsd/kern/kern_mman.c diff --git a/bsd/kern/kern_mman.c b/bsd/kern/kern_mman.c index 979af3e5d..575110d69 100644 --- a/bsd/kern/kern_mman.c +++ b/bsd/kern/kern_mman.c @@ -115,8 +115,11 @@ #include #include +#include + #include #include +#include #include #include @@ -145,8 +148,8 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) int err=0; vm_map_t user_map; kern_return_t result; - mach_vm_offset_t user_addr; - mach_vm_size_t user_size; + vm_map_offset_t user_addr; + vm_map_size_t user_size; vm_object_offset_t pageoff; vm_object_offset_t file_pos; int alloc_flags=0; @@ -161,8 +164,9 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) int fd = uap->fd; int num_retries = 0; - user_addr = (mach_vm_offset_t)uap->addr; - user_size = (mach_vm_size_t) uap->len; + user_map = current_map(); + user_addr = (vm_map_offset_t)uap->addr; + user_size = (vm_map_size_t) uap->len; AUDIT_ARG(addr, user_addr); AUDIT_ARG(len, user_size); @@ -199,15 +203,16 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) * Align the file position to a page boundary, * and save its page offset component. */ - pageoff = (file_pos & PAGE_MASK); + pageoff = (file_pos & vm_map_page_mask(user_map)); file_pos -= (vm_object_offset_t)pageoff; /* Adjust size for rounding (on both ends). */ - user_size += pageoff; /* low end... */ - user_size = mach_vm_round_page(user_size); /* hi end */ + user_size += pageoff; /* low end... */ + user_size = vm_map_round_page(user_size, + vm_map_page_mask(user_map)); /* hi end */ - if ((flags & MAP_JIT) && ((flags & MAP_FIXED) || (flags & MAP_SHARED) || (flags & MAP_FILE))){ + if ((flags & MAP_JIT) && ((flags & MAP_FIXED) || (flags & MAP_SHARED) || !(flags & MAP_ANON))){ return EINVAL; } /* @@ -221,7 +226,7 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) * should be aligned after adjustment by pageoff. */ user_addr -= pageoff; - if (user_addr & PAGE_MASK) + if (user_addr & vm_map_page_mask(user_map)) return (EINVAL); } #ifdef notyet @@ -234,8 +239,10 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) * There should really be a pmap call to determine a reasonable * location. */ - else if (addr < mach_vm_round_page(p->p_vmspace->vm_daddr + MAXDSIZ)) - addr = mach_vm_round_page(p->p_vmspace->vm_daddr + MAXDSIZ); + else if (addr < vm_map_round_page(p->p_vmspace->vm_daddr + MAXDSIZ, + vm_map_page_mask(user_map))) + addr = vm_map_round_page(p->p_vmspace->vm_daddr + MAXDSIZ, + vm_map_page_mask(user_map)); #endif @@ -247,12 +254,11 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) #if CONFIG_MACF /* * Entitlement check. - * Re-enable once mac* is implemented. */ - /*error = mac_proc_check_map_anon(p, user_addr, user_size, prot, flags, &maxprot); + error = mac_proc_check_map_anon(p, user_addr, user_size, prot, flags, &maxprot); if (error) { return EINVAL; - }*/ + } #endif /* MAC */ /* @@ -279,6 +285,9 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) struct vnode_attr va; vfs_context_t ctx = vfs_context_current(); + if (flags & MAP_JIT) + return EINVAL; + /* * Mapping file, get fp for validation. Obtain vnode and make * sure it is of appropriate type. @@ -287,7 +296,8 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) if (err) return(err); fpref = 1; - if(fp->f_fglob->fg_type == DTYPE_PSXSHM) { + switch (FILEGLOB_DTYPE(fp->f_fglob)) { + case DTYPE_PSXSHM: uap->addr = (user_addr_t)user_addr; uap->len = (user_size_t)user_size; uap->prot = prot; @@ -295,9 +305,9 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) uap->pos = file_pos; error = pshm_mmap(p, uap, retval, fp, (off_t)pageoff); goto bad; - } - - if (fp->f_fglob->fg_type != DTYPE_VNODE) { + case DTYPE_VNODE: + break; + default: error = EINVAL; goto bad; } @@ -403,13 +413,10 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) #if CONFIG_PROTECT { - void *cnode; - if ((cnode = cp_get_protected_cnode(vp)) != NULL) { - error = cp_handle_vnop(cnode, CP_READ_ACCESS | CP_WRITE_ACCESS); - if (error) { - (void) vnode_put(vp); - goto bad; - } + error = cp_handle_vnop(vp, CP_READ_ACCESS | CP_WRITE_ACCESS, 0); + if (error) { + (void) vnode_put(vp); + goto bad; } } #endif /* CONFIG_PROTECT */ @@ -429,22 +436,23 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) * We bend a little - round the start and end addresses * to the nearest page boundary. */ - user_size = mach_vm_round_page(user_size); + user_size = vm_map_round_page(user_size, + vm_map_page_mask(user_map)); - if (file_pos & PAGE_MASK_64) { + if (file_pos & vm_map_page_mask(user_map)) { if (!mapanon) (void)vnode_put(vp); error = EINVAL; goto bad; } - user_map = current_map(); - if ((flags & MAP_FIXED) == 0) { alloc_flags |= VM_FLAGS_ANYWHERE; - user_addr = mach_vm_round_page(user_addr); + user_addr = vm_map_round_page(user_addr, + vm_map_page_mask(user_map)); } else { - if (user_addr != mach_vm_trunc_page(user_addr)) { + if (user_addr != vm_map_trunc_page(user_addr, + vm_map_page_mask(user_map))) { if (!mapanon) (void)vnode_put(vp); error = EINVAL; @@ -507,7 +515,7 @@ map_anon_retry: * lack of space between the address and the map's maximum. */ if ((result == KERN_NO_SPACE) && ((flags & MAP_FIXED) == 0) && user_addr && (num_retries++ == 0)) { - user_addr = PAGE_SIZE; + user_addr = vm_map_page_size(user_map); goto map_anon_retry; } } else { @@ -576,7 +584,7 @@ map_file_retry: * lack of space between the address and the map's maximum. */ if ((result == KERN_NO_SPACE) && ((flags & MAP_FIXED) == 0) && user_addr && (num_retries++ == 0)) { - user_addr = PAGE_SIZE; + user_addr = vm_map_page_size(user_map); goto map_file_retry; } } @@ -616,7 +624,6 @@ bad: KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_SC_EXTENDED_INFO, SYS_mmap) | DBG_FUNC_NONE), fd, (uint32_t)(*retval), (uint32_t)user_size, error, 0); KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_SC_EXTENDED_INFO2, SYS_mmap) | DBG_FUNC_NONE), (uint32_t)(*retval >> 32), (uint32_t)(user_size >> 32), (uint32_t)(file_pos >> 32), (uint32_t)file_pos, 0); - return(error); } @@ -637,12 +644,11 @@ msync_nocancel(__unused proc_t p, struct msync_nocancel_args *uap, __unused int3 int rv; vm_sync_t sync_flags=0; + user_map = current_map(); addr = (mach_vm_offset_t) uap->addr; size = (mach_vm_size_t)uap->len; - KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_SC_EXTENDED_INFO, SYS_msync) | DBG_FUNC_NONE), (uint32_t)(addr >> 32), (uint32_t)(size >> 32), 0, 0, 0); - - if (addr & PAGE_MASK_64) { + if (addr & vm_map_page_mask(user_map)) { /* UNIX SPEC: user address is not page-aligned, return EINVAL */ return EINVAL; } @@ -678,7 +684,6 @@ msync_nocancel(__unused proc_t p, struct msync_nocancel_args *uap, __unused int3 sync_flags |= VM_SYNC_CONTIGUOUS; /* complain if holes */ - user_map = current_map(); rv = mach_vm_msync(user_map, addr, size, sync_flags); switch (rv) { @@ -699,16 +704,18 @@ int munmap(__unused proc_t p, struct munmap_args *uap, __unused int32_t *retval) { mach_vm_offset_t user_addr; - mach_vm_size_t user_size; - kern_return_t result; + mach_vm_size_t user_size; + kern_return_t result; + vm_map_t user_map; + user_map = current_map(); user_addr = (mach_vm_offset_t) uap->addr; user_size = (mach_vm_size_t) uap->len; AUDIT_ARG(addr, user_addr); AUDIT_ARG(len, user_size); - if (user_addr & PAGE_MASK_64) { + if (user_addr & vm_map_page_mask(user_map)) { /* UNIX SPEC: user address is not page-aligned, return EINVAL */ return EINVAL; } @@ -721,7 +728,7 @@ munmap(__unused proc_t p, struct munmap_args *uap, __unused int32_t *retval) return EINVAL; } - result = mach_vm_deallocate(current_map(), user_addr, user_size); + result = mach_vm_deallocate(user_map, user_addr, user_size); if (result != KERN_SUCCESS) { return(EINVAL); } @@ -744,11 +751,12 @@ mprotect(__unused proc_t p, struct mprotect_args *uap, __unused int32_t *retval) AUDIT_ARG(len, uap->len); AUDIT_ARG(value32, uap->prot); + user_map = current_map(); user_addr = (mach_vm_offset_t) uap->addr; user_size = (mach_vm_size_t) uap->len; prot = (vm_prot_t)(uap->prot & (VM_PROT_ALL | VM_PROT_TRUSTED)); - if (user_addr & PAGE_MASK_64) { + if (user_addr & vm_map_page_mask(user_map)) { /* UNIX SPEC: user address is not page-aligned, return EINVAL */ return EINVAL; } @@ -766,8 +774,6 @@ mprotect(__unused proc_t p, struct mprotect_args *uap, __unused int32_t *retval) prot |= VM_PROT_READ; #endif /* 3936456 */ - user_map = current_map(); - #if CONFIG_MACF /* * The MAC check for mprotect is of limited use for 2 reasons: @@ -794,9 +800,12 @@ mprotect(__unused proc_t p, struct mprotect_args *uap, __unused int32_t *retval) * mac_proc_check_mprotect() hook above. Otherwise, Codesigning will be * compromised because the check would always succeed and thusly any * process could sign dynamically. */ - result = vm_map_sign(user_map, - vm_map_trunc_page(user_addr), - vm_map_round_page(user_addr+user_size)); + result = vm_map_sign( + user_map, + vm_map_trunc_page(user_addr, + vm_map_page_mask(user_map)), + vm_map_round_page(user_addr+user_size, + vm_map_page_mask(user_map))); switch (result) { case KERN_SUCCESS: break; @@ -943,8 +952,10 @@ mincore(__unused proc_t p, struct mincore_args *uap, __unused int32_t *retval) * Make sure that the addresses presented are valid for user * mode. */ - first_addr = addr = mach_vm_trunc_page(uap->addr); - end = addr + mach_vm_round_page(uap->len); + first_addr = addr = vm_map_trunc_page(uap->addr, + vm_map_page_mask(map)); + end = addr + vm_map_round_page(uap->len, + vm_map_page_mask(map)); if (end < addr) return (EINVAL); @@ -1043,10 +1054,10 @@ mlock(__unused proc_t p, struct mlock_args *uap, __unused int32_t *retvalval) if (size == 0) return (0); - pageoff = (addr & PAGE_MASK); - addr -= pageoff; - size = vm_map_round_page(size+pageoff); user_map = current_map(); + pageoff = (addr & vm_map_page_mask(user_map)); + addr -= pageoff; + size = vm_map_round_page(size+pageoff, vm_map_page_mask(user_map)); /* have to call vm_map_wire directly to pass "I don't know" protections */ result = vm_map_wire(user_map, addr, addr+size, VM_PROT_NONE, TRUE); @@ -1092,7 +1103,6 @@ munlockall(__unused proc_t p, __unused struct munlockall_args *uap, __unused int return(ENOSYS); } -#if !defined(CONFIG_EMBEDDED) /* USV: No! need to obsolete map_fd()! mmap() already supports 64 bits */ kern_return_t map_fd(struct map_fd_args *args) @@ -1134,6 +1144,8 @@ map_fd_funneled( proc_t p = current_proc(); struct vnode_attr vattr; + my_map = current_map(); + /* * Find the inode; verify that it's a regular file. */ @@ -1142,7 +1154,7 @@ map_fd_funneled( if (err) return(err); - if (fp->f_fglob->fg_type != DTYPE_VNODE){ + if (FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_VNODE) { err = KERN_INVALID_ARGUMENT; goto bad; } @@ -1175,14 +1187,11 @@ map_fd_funneled( #if CONFIG_PROTECT /* check for content protection access */ { - void *cnode; - if ((cnode = cp_get_protected_cnode(vp)) != NULL) { - err = cp_handle_vnop(cnode, CP_READ_ACCESS | CP_WRITE_ACCESS); - if (err != 0) { - (void)vnode_put(vp); - goto bad; - } - } + err = cp_handle_vnop(vp, CP_READ_ACCESS | CP_WRITE_ACCESS, 0); + if (err != 0) { + (void) vnode_put(vp); + goto bad; + } } #endif /* CONFIG_PROTECT */ @@ -1198,13 +1207,13 @@ map_fd_funneled( vnode_setattr(vp, &vattr, vfs_context_current()); } - if (offset & PAGE_MASK_64) { + if (offset & vm_map_page_mask(my_map)) { printf("map_fd: file offset not page aligned(%d : %s)\n",p->p_pid, p->p_comm); (void)vnode_put(vp); err = KERN_INVALID_ARGUMENT; goto bad; } - map_size = round_page(size); + map_size = vm_map_round_page(size, vm_map_page_mask(my_map)); /* * Allow user to map in a zero length file. @@ -1224,9 +1233,6 @@ map_fd_funneled( goto bad; } - - my_map = current_map(); - result = vm_map_64( my_map, &map_addr, map_size, (vm_offset_t)0, @@ -1246,7 +1252,7 @@ map_fd_funneled( vm_map_copy_t tmp; if (copyin(CAST_USER_ADDR_T(va), &dst_addr, sizeof (dst_addr)) || - trunc_page(dst_addr) != dst_addr) { + trunc_page(dst_addr) != dst_addr) { (void) vm_map_remove( my_map, map_addr, map_addr + map_size, @@ -1260,9 +1266,13 @@ map_fd_funneled( (vm_map_size_t)map_size, TRUE, &tmp); if (result != KERN_SUCCESS) { - (void) vm_map_remove(my_map, vm_map_trunc_page(map_addr), - vm_map_round_page(map_addr + map_size), - VM_MAP_NO_FLAGS); + (void) vm_map_remove( + my_map, + vm_map_trunc_page(map_addr, + vm_map_page_mask(my_map)), + vm_map_round_page(map_addr + map_size, + vm_map_page_mask(my_map)), + VM_MAP_NO_FLAGS); (void)vnode_put(vp); err = result; goto bad; @@ -1280,9 +1290,13 @@ map_fd_funneled( // K64todo bug compatible now, should fix for 64bit user uint32_t user_map_addr = CAST_DOWN_EXPLICIT(uint32_t, map_addr); if (copyout(&user_map_addr, CAST_USER_ADDR_T(va), sizeof (user_map_addr))) { - (void) vm_map_remove(my_map, vm_map_trunc_page(map_addr), - vm_map_round_page(map_addr + map_size), - VM_MAP_NO_FLAGS); + (void) vm_map_remove( + my_map, + vm_map_trunc_page(map_addr, + vm_map_page_mask(my_map)), + vm_map_round_page(map_addr + map_size, + vm_map_page_mask(my_map)), + VM_MAP_NO_FLAGS); (void)vnode_put(vp); err = KERN_INVALID_ADDRESS; goto bad; @@ -1296,5 +1310,4 @@ bad: fp_drop(p, fd, fp, 0); return (err); } -#endif /* !defined(CONFIG_EMBEDDED) */