X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3e170ce000f1506b7b5d2c5c7faec85ceabb573d..7e41aa883dd258f888d0470250eead40a53ef1f5:/bsd/kern/mach_loader.c diff --git a/bsd/kern/mach_loader.c b/bsd/kern/mach_loader.c index b5666e881..d4f084e31 100644 --- a/bsd/kern/mach_loader.c +++ b/bsd/kern/mach_loader.c @@ -82,6 +82,8 @@ #include #include /* for kIOReturnNotPrivileged */ +#include + /* * XXX vm/pmap.h should not treat these prototypes as MACH_KERNEL_PRIVATE * when KERNEL is defined. @@ -89,8 +91,6 @@ extern pmap_t pmap_create(ledger_t ledger, vm_map_size_t size, boolean_t is_64bit); -extern kern_return_t machine_thread_neon_state_initialize(thread_t thread); - /* XXX should have prototypes in a shared header file */ extern int get_map_nentries(vm_map_t); @@ -118,7 +118,9 @@ static load_result_t load_result_null = { .uuid = { 0 }, .min_vm_addr = MACH_VM_MAX_ADDRESS, .max_vm_addr = MACH_VM_MIN_ADDRESS, - .cs_end_offset = 0 + .cs_end_offset = 0, + .threadstate = NULL, + .threadstate_sz = 0 }; /* @@ -201,7 +203,8 @@ static load_return_t load_threadstate( thread_t thread, uint32_t *ts, - uint32_t total_size + uint32_t total_size, + load_result_t * ); static load_return_t @@ -296,7 +299,7 @@ load_machfile( struct image_params *imgp, struct mach_header *header, thread_t thread, - vm_map_t new_map, + vm_map_t *mapp, load_result_t *result ) { @@ -304,11 +307,9 @@ load_machfile( off_t file_offset = imgp->ip_arch_offset; off_t macho_size = imgp->ip_arch_size; off_t file_size = imgp->ip_vattr->va_data_size; - + vm_map_t new_map = *mapp; pmap_t pmap = 0; /* protected by create_map */ vm_map_t map; - vm_map_t old_map; - task_t old_task = TASK_NULL; /* protected by create_map */ load_result_t myresult; load_return_t lret; boolean_t create_map = FALSE; @@ -326,7 +327,6 @@ load_machfile( if (new_map == VM_MAP_NULL) { create_map = TRUE; - old_task = current_task(); } /* @@ -337,7 +337,6 @@ load_machfile( */ if (spawn) { create_map = TRUE; - old_task = get_threadtask(thread); } if (create_map) { @@ -431,22 +430,13 @@ load_machfile( } } - /* - * Commit to new map. - * - * Swap the new map for the old, which consumes our new map - * reference but each leaves us responsible for the old_map reference. - * That lets us get off the pmap associated with it, and - * then we can release it. - */ - - if (create_map) { + if (create_map) { /* * If this is an exec, then we are going to destroy the old * task, and it's correct to halt it; if it's spawn, the * task is not yet running, and it makes no sense. */ - if (!spawn) { + if (!spawn) { /* * Mark the task as halting and start the other * threads towards terminating themselves. Then @@ -478,8 +468,7 @@ load_machfile( kqueue_dealloc(p->p_wqkqueue); p->p_wqkqueue = NULL; } - old_map = swap_task_map(old_task, thread, map, !spawn); - vm_map_deallocate(old_map); + *mapp = map; } return(LOAD_SUCCESS); } @@ -996,6 +985,14 @@ unprotect_dsmos_segment( (uint64_t) map_addr, (uint64_t) (map_addr + map_size), __FUNCTION__, vp->v_name); #endif /* DEVELOPMENT || DEBUG */ + + /* The DSMOS pager can only be used by apple signed code */ + struct cs_blob * blob = csvnode_get_blob(vp, file_off); + if( blob == NULL || !blob->csb_platform_binary || blob->csb_platform_path) + { + return LOAD_FAILURE; + } + kr = vm_map_apple_protected(map, map_addr, map_addr + map_size, @@ -1527,13 +1524,6 @@ load_main( /* kernel does *not* use entryoff from LC_MAIN. Dyld uses it. */ result->needs_dynlinker = TRUE; result->using_lcmain = TRUE; - - ret = thread_state_initialize( thread ); - if (ret != KERN_SUCCESS) { - return(LOAD_FAILURE); - } - - result->unixproc = TRUE; result->thread_count++; @@ -1604,13 +1594,12 @@ load_unixthread( result->entry_point += slide; ret = load_threadstate(thread, - (uint32_t *)(((vm_offset_t)tcp) + - sizeof(struct thread_command)), - tcp->cmdsize - sizeof(struct thread_command)); + (uint32_t *)(((vm_offset_t)tcp) + sizeof(struct thread_command)), + tcp->cmdsize - sizeof(struct thread_command), + result); if (ret != LOAD_SUCCESS) return (ret); - result->unixproc = TRUE; result->thread_count++; @@ -1622,72 +1611,56 @@ load_return_t load_threadstate( thread_t thread, uint32_t *ts, - uint32_t total_size + uint32_t total_size, + load_result_t *result ) { - kern_return_t ret; uint32_t size; int flavor; uint32_t thread_size; - uint32_t *local_ts; - uint32_t local_ts_size; + uint32_t *local_ts = NULL; + uint32_t local_ts_size = 0; + int ret; - local_ts = NULL; - local_ts_size = 0; + (void)thread; - ret = thread_state_initialize( thread ); - if (ret != KERN_SUCCESS) { - ret = LOAD_FAILURE; - goto done; - } - if (total_size > 0) { local_ts_size = total_size; local_ts = kalloc(local_ts_size); if (local_ts == NULL) { - ret = LOAD_FAILURE; - goto done; + return LOAD_FAILURE; } memcpy(local_ts, ts, local_ts_size); ts = local_ts; } /* - * Set the new thread state; iterate through the state flavors in - * the mach-o file. + * Validate the new thread state; iterate through the state flavors in + * the Mach-O file. + * XXX: we should validate the machine state here, to avoid failing at + * activation time where we can't bail out cleanly. */ while (total_size > 0) { flavor = *ts++; size = *ts++; - if (UINT32_MAX-2 < size || - UINT32_MAX/sizeof(uint32_t) < size+2) { - ret = LOAD_BADMACHO; - goto done; - } - thread_size = (size+2)*sizeof(uint32_t); - if (thread_size > total_size) { + + if (os_add_overflow(size, UINT32_C(2), &thread_size) || + os_mul_overflow(thread_size, (uint32_t)sizeof(uint32_t), &thread_size) || + os_sub_overflow(total_size, thread_size, &total_size)) { ret = LOAD_BADMACHO; - goto done; - } - total_size -= thread_size; - /* - * Third argument is a kernel space pointer; it gets cast - * to the appropriate type in machine_thread_set_state() - * based on the value of flavor. - */ - ret = thread_setstatus(thread, flavor, (thread_state_t)ts, size); - if (ret != KERN_SUCCESS) { - ret = LOAD_FAILURE; - goto done; + goto bad; } + ts += size; /* ts is a (uint32_t *) */ } - ret = LOAD_SUCCESS; -done: - if (local_ts != NULL) { + result->threadstate = local_ts; + result->threadstate_sz = local_ts_size; + return LOAD_SUCCESS; + +bad: + if (local_ts) { kfree(local_ts, local_ts_size); - local_ts = NULL; } return ret; } @@ -1916,7 +1889,14 @@ load_dylinker( } } - if (ret == LOAD_SUCCESS) { + if (ret == LOAD_SUCCESS) { + if (result->threadstate) { + /* don't use the app's threadstate if we have a dyld */ + kfree(result->threadstate, result->threadstate_sz); + } + result->threadstate = myresult->threadstate; + result->threadstate_sz = myresult->threadstate_sz; + result->dynlinker = TRUE; result->entry_point = myresult->entry_point; result->validentry = myresult->validentry;