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; }
static inline kern_return_t _voucher_create_mach_voucher(const mach_voucher_attr_recipe_data_t *recipes, size_t recipes_size, mach_voucher_t *kvp) { kern_return_t kr; mach_port_t mhp = _dispatch_get_mach_host_port(); mach_voucher_t kv = MACH_VOUCHER_NULL; mach_voucher_attr_raw_recipe_array_t kvr; mach_voucher_attr_recipe_size_t kvr_size; kvr = (mach_voucher_attr_raw_recipe_array_t)recipes; kvr_size = (mach_voucher_attr_recipe_size_t)recipes_size; kr = host_create_mach_voucher(mhp, kvr, kvr_size, &kv); DISPATCH_VERIFY_MIG(kr); if (!kr) { _dispatch_kvoucher_debug("create", kv); _dispatch_voucher_debug_machport(kv); } *kvp = kv; return kr; }