X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/316670eb35587141e969394ae8537d66b9211e80..d190cdc3f5544636abb56dc1874be391d3e1b148:/osfmk/ipc/mach_kernelrpc.c diff --git a/osfmk/ipc/mach_kernelrpc.c b/osfmk/ipc/mach_kernelrpc.c index 75244966f..1b50efbb7 100644 --- a/osfmk/ipc/mach_kernelrpc.c +++ b/osfmk/ipc/mach_kernelrpc.c @@ -30,9 +30,12 @@ #include #include #include +#include +#include #include #include #include +#include #include int @@ -93,6 +96,58 @@ done: return (rv); } +int +_kernelrpc_mach_vm_map_trap(struct _kernelrpc_mach_vm_map_trap_args *args) +{ + mach_vm_offset_t addr; + task_t task = port_name_to_task(args->target); + int rv = MACH_SEND_INVALID_DEST; + + if (task != current_task()) + goto done; + + if (copyin(args->addr, (char *)&addr, sizeof (addr))) + goto done; + + rv = mach_vm_map(task->map, &addr, args->size, args->mask, args->flags, + IPC_PORT_NULL, 0, FALSE, args->cur_protection, VM_PROT_ALL, + VM_INHERIT_DEFAULT); + if (rv == KERN_SUCCESS) + rv = copyout(&addr, args->addr, sizeof (addr)); + +done: + if (task) + task_deallocate(task); + return (rv); +} + +int +_kernelrpc_mach_vm_purgable_control_trap( + struct _kernelrpc_mach_vm_purgable_control_trap_args *args) +{ + int state; + task_t task = port_name_to_task(args->target); + int rv = MACH_SEND_INVALID_DEST; + + if (task != current_task()) + goto done; + + if (copyin(args->state, (char *)&state, sizeof (state))) + goto done; + + rv = mach_vm_purgable_control(task->map, + args->address, + args->control, + &state); + if (rv == KERN_SUCCESS) + rv = copyout(&state, args->state, sizeof (state)); + +done: + if (task) + task_deallocate(task); + return (rv); +} + int _kernelrpc_mach_port_allocate_trap(struct _kernelrpc_mach_port_allocate_args *args) { @@ -201,6 +256,11 @@ _kernelrpc_mach_port_insert_right_trap(struct _kernelrpc_mach_port_insert_right_ disp = ipc_object_copyin_type(args->polyPoly); rv = mach_port_insert_right(task->itk_space, args->name, port, disp); + if (rv != KERN_SUCCESS) { + if (IO_VALID((ipc_object_t)port)) { + ipc_object_destroy((ipc_object_t)port, disp); + } + } done: if (task) @@ -242,3 +302,194 @@ done: task_deallocate(task); return (rv); } + +int +_kernelrpc_mach_port_construct_trap(struct _kernelrpc_mach_port_construct_args *args) +{ + task_t task = port_name_to_task(args->target); + mach_port_name_t name; + int rv = MACH_SEND_INVALID_DEST; + mach_port_options_t options; + + if (copyin(args->options, (char *)&options, sizeof (options))) { + rv = MACH_SEND_INVALID_DATA; + goto done; + } + + if (task != current_task()) + goto done; + + rv = mach_port_construct(task->itk_space, &options, args->context, &name); + if (rv == KERN_SUCCESS) + rv = copyout(&name, args->name, sizeof (name)); + +done: + if (task) + task_deallocate(task); + return (rv); +} + +int +_kernelrpc_mach_port_destruct_trap(struct _kernelrpc_mach_port_destruct_args *args) +{ + task_t task = port_name_to_task(args->target); + int rv = MACH_SEND_INVALID_DEST; + + if (task != current_task()) + goto done; + + rv = mach_port_destruct(task->itk_space, args->name, args->srdelta, args->guard); + +done: + if (task) + task_deallocate(task); + return (rv); +} + +int +_kernelrpc_mach_port_guard_trap(struct _kernelrpc_mach_port_guard_args *args) +{ + task_t task = port_name_to_task(args->target); + int rv = MACH_SEND_INVALID_DEST; + + if (task != current_task()) + goto done; + + rv = mach_port_guard(task->itk_space, args->name, args->guard, args->strict); + +done: + if (task) + task_deallocate(task); + return (rv); +} + +int +_kernelrpc_mach_port_unguard_trap(struct _kernelrpc_mach_port_unguard_args *args) +{ + task_t task = port_name_to_task(args->target); + int rv = MACH_SEND_INVALID_DEST; + + if (task != current_task()) + goto done; + + rv = mach_port_unguard(task->itk_space, args->name, args->guard); + +done: + if (task) + task_deallocate(task); + return (rv); +} + +kern_return_t +host_create_mach_voucher_trap(struct host_create_mach_voucher_args *args) +{ + host_t host = port_name_to_host(args->host); + ipc_voucher_t new_voucher = IV_NULL; + ipc_port_t voucher_port = IPC_PORT_NULL; + mach_port_name_t voucher_name = 0; + kern_return_t kr = 0; + + if (host == HOST_NULL) + return MACH_SEND_INVALID_DEST; + + if (args->recipes_size < 0) + return KERN_INVALID_ARGUMENT; + else if (args->recipes_size > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) + return MIG_ARRAY_TOO_LARGE; + + if (args->recipes_size < MACH_VOUCHER_TRAP_STACK_LIMIT) { + /* keep small recipes on the stack for speed */ + uint8_t krecipes[args->recipes_size]; + if (copyin(args->recipes, (void *)krecipes, args->recipes_size)) { + kr = KERN_MEMORY_ERROR; + goto done; + } + kr = host_create_mach_voucher(host, krecipes, args->recipes_size, &new_voucher); + } else { + uint8_t *krecipes = kalloc((vm_size_t)args->recipes_size); + if (!krecipes) { + kr = KERN_RESOURCE_SHORTAGE; + goto done; + } + + if (copyin(args->recipes, (void *)krecipes, args->recipes_size)) { + kfree(krecipes, (vm_size_t)args->recipes_size); + kr = KERN_MEMORY_ERROR; + goto done; + } + + kr = host_create_mach_voucher(host, krecipes, args->recipes_size, &new_voucher); + kfree(krecipes, (vm_size_t)args->recipes_size); + } + + if (kr == 0) { + voucher_port = convert_voucher_to_port(new_voucher); + voucher_name = ipc_port_copyout_send(voucher_port, current_space()); + + kr = copyout(&voucher_name, args->voucher, sizeof(voucher_name)); + } + +done: + return kr; +} + +kern_return_t +mach_voucher_extract_attr_recipe_trap(struct mach_voucher_extract_attr_recipe_args *args) +{ + ipc_voucher_t voucher = IV_NULL; + kern_return_t kr = KERN_SUCCESS; + mach_msg_type_number_t sz = 0; + + if (copyin(args->recipe_size, (void *)&sz, sizeof(sz))) + return KERN_MEMORY_ERROR; + + if (sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) + return MIG_ARRAY_TOO_LARGE; + + voucher = convert_port_name_to_voucher(args->voucher_name); + if (voucher == IV_NULL) + return MACH_SEND_INVALID_DEST; + + mach_msg_type_number_t __assert_only max_sz = sz; + + if (sz < MACH_VOUCHER_TRAP_STACK_LIMIT) { + /* keep small recipes on the stack for speed */ + uint8_t krecipe[sz]; + if (copyin(args->recipe, (void *)krecipe, sz)) { + kr = KERN_MEMORY_ERROR; + goto done; + } + kr = mach_voucher_extract_attr_recipe(voucher, args->key, + (mach_voucher_attr_raw_recipe_t)krecipe, &sz); + assert(sz <= max_sz); + + if (kr == KERN_SUCCESS && sz > 0) + kr = copyout(krecipe, (void *)args->recipe, sz); + } else { + uint8_t *krecipe = kalloc((vm_size_t)sz); + if (!krecipe) { + kr = KERN_RESOURCE_SHORTAGE; + goto done; + } + + if (copyin(args->recipe, (void *)krecipe, args->recipe_size)) { + kfree(krecipe, (vm_size_t)sz); + kr = KERN_MEMORY_ERROR; + goto done; + } + + kr = mach_voucher_extract_attr_recipe(voucher, args->key, + (mach_voucher_attr_raw_recipe_t)krecipe, &sz); + assert(sz <= max_sz); + + if (kr == KERN_SUCCESS && sz > 0) + kr = copyout(krecipe, (void *)args->recipe, sz); + kfree(krecipe, (vm_size_t)sz); + } + + kr = copyout(&sz, args->recipe_size, sizeof(sz)); + +done: + ipc_voucher_release(voucher); + return kr; +}