Example #1
0
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;
}