Esempio n. 1
0
/*
 * request a key (allow async construction)
 * - search the process's keyrings
 * - check the list of keys being created or updated
 * - call out to userspace for a key if supplementary info was provided
 */
struct key *request_key_async(struct key_type *type,
			      const char *description,
			      const char *callout_info)
{
	return request_key_and_link(type, description, callout_info, NULL,
				    NULL, KEY_ALLOC_IN_QUOTA);
}
Esempio n. 2
0
/*
 * request a key with auxiliary data for the upcaller (allow async construction)
 * - search the process's keyrings
 * - check the list of keys being created or updated
 * - call out to userspace for a key if supplementary info was provided
 */
struct key *request_key_async_with_auxdata(struct key_type *type,
					   const char *description,
					   const char *callout_info,
					   void *aux)
{
	return request_key_and_link(type, description, callout_info, aux,
				    NULL, KEY_ALLOC_IN_QUOTA);
}
Esempio n. 3
0
/*
 * request a key
 * - search the process's keyrings
 * - check the list of keys being created or updated
 * - call out to userspace for a key if supplementary info was provided
 * - waits uninterruptible for creation to complete
 */
struct key *request_key(struct key_type *type,
			const char *description,
			const char *callout_info)
{
	struct key *key;
	int ret;

	key = request_key_and_link(type, description, callout_info, NULL,
				   NULL, KEY_ALLOC_IN_QUOTA);
	if (!IS_ERR(key)) {
		ret = wait_for_key_construction(key, false);
		if (ret < 0) {
			key_put(key);
			return ERR_PTR(ret);
		}
	}
	return key;
}
Esempio n. 4
0
/**
 * request_key_with_auxdata - Request a key with auxiliary data for the upcaller
 * @type: The type of key we want.
 * @description: The searchable description of the key.
 * @callout_info: The data to pass to the instantiation upcall (or NULL).
 * @callout_len: The length of callout_info.
 * @aux: Auxiliary data for the upcall.
 *
 * As for request_key_and_link() except that it does not add the returned key
 * to a keyring if found and new keys are always allocated in the user's quota.
 *
 * Furthermore, it then works as wait_for_key_construction() to wait for the
 * completion of keys undergoing construction with a non-interruptible wait.
 */
struct key *request_key_with_auxdata(struct key_type *type,
				     const char *description,
				     const void *callout_info,
				     size_t callout_len,
				     void *aux)
{
	struct key *key;
	int ret;

	key = request_key_and_link(type, description, callout_info, callout_len,
				   aux, NULL, KEY_ALLOC_IN_QUOTA);
	if (!IS_ERR(key)) {
		ret = wait_for_key_construction(key, false);
		if (ret < 0) {
			key_put(key);
			return ERR_PTR(ret);
		}
	}
	return key;
}
Esempio n. 5
0
/*
 * Search the process keyrings and keyring trees linked from those for a
 * matching key.  Keyrings must have appropriate Search permission to be
 * searched.
 *
 * If a key is found, it will be attached to the destination keyring if there's
 * one specified and the serial number of the key will be returned.
 *
 * If no key is found, /sbin/request-key will be invoked if _callout_info is
 * non-NULL in an attempt to create a key.  The _callout_info string will be
 * passed to /sbin/request-key to aid with completing the request.  If the
 * _callout_info string is "" then it will be changed to "-".
 */
SYSCALL_DEFINE4(request_key, const char __user *, _type,
		const char __user *, _description,
		const char __user *, _callout_info,
		key_serial_t, destringid)
{
	struct key_type *ktype;
	struct key *key;
	key_ref_t dest_ref;
	size_t callout_len;
	char type[32], *description, *callout_info;
	long ret;

	/* pull the type into kernel space */
	ret = key_get_type_from_user(type, _type, sizeof(type));
	if (ret < 0)
		goto error;

	/* pull the description into kernel space */
	description = strndup_user(_description, PAGE_SIZE);
	if (IS_ERR(description)) {
		ret = PTR_ERR(description);
		goto error;
	}

	/* pull the callout info into kernel space */
	callout_info = NULL;
	callout_len = 0;
	if (_callout_info) {
		callout_info = strndup_user(_callout_info, PAGE_SIZE);
		if (IS_ERR(callout_info)) {
			ret = PTR_ERR(callout_info);
			goto error2;
		}
		callout_len = strlen(callout_info);
	}

	/* get the destination keyring if specified */
	dest_ref = NULL;
	if (destringid) {
		dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
					   KEY_WRITE);
		if (IS_ERR(dest_ref)) {
			ret = PTR_ERR(dest_ref);
			goto error3;
		}
	}

	/* find the key type */
	ktype = key_type_lookup(type);
	if (IS_ERR(ktype)) {
		ret = PTR_ERR(ktype);
		goto error4;
	}

	/* do the search */
	key = request_key_and_link(ktype, description, callout_info,
				   callout_len, NULL, key_ref_to_ptr(dest_ref),
				   KEY_ALLOC_IN_QUOTA);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
		goto error5;
	}

	/* wait for the key to finish being constructed */
	ret = wait_for_key_construction(key, 1);
	if (ret < 0)
		goto error6;

	ret = key->serial;

error6:
 	key_put(key);
error5:
	key_type_put(ktype);
error4:
	key_ref_put(dest_ref);
error3:
	kfree(callout_info);
error2:
	kfree(description);
error:
	return ret;
}
Esempio n. 6
0
/*
 * search the process keyrings for a matching key
 * - nested keyrings may also be searched if they have Search permission
 * - if a key is found, it will be attached to the destination keyring if
 *   there's one specified
 * - /sbin/request-key will be invoked if _callout_info is non-NULL
 *   - the _callout_info string will be passed to /sbin/request-key
 *   - if the _callout_info string is empty, it will be rendered as "-"
 * - implements request_key()
 */
asmlinkage long sys_request_key(const char __user *_type,
				const char __user *_description,
				const char __user *_callout_info,
				key_serial_t destringid)
{
	struct key_type *ktype;
	struct key *key;
	key_ref_t dest_ref;
	char type[32], *description, *callout_info;
	long dlen, ret;

	/* pull the type into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EPERM;
	if (type[0] == '.')
		goto error;

	/* pull the description into kernel space */
	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* pull the callout info into kernel space */
	callout_info = NULL;
	if (_callout_info) {
		ret = -EFAULT;
		dlen = strnlen_user(_callout_info, PAGE_SIZE - 1);
		if (dlen <= 0)
			goto error2;

		ret = -EINVAL;
		if (dlen > PAGE_SIZE - 1)
			goto error2;

		ret = -ENOMEM;
		callout_info = kmalloc(dlen + 1, GFP_KERNEL);
		if (!callout_info)
			goto error2;

		ret = -EFAULT;
		if (copy_from_user(callout_info, _callout_info, dlen + 1) != 0)
			goto error3;
	}

	/* get the destination keyring if specified */
	dest_ref = NULL;
	if (destringid) {
		dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
		if (IS_ERR(dest_ref)) {
			ret = PTR_ERR(dest_ref);
			goto error3;
		}
	}

	/* find the key type */
	ktype = key_type_lookup(type);
	if (IS_ERR(ktype)) {
		ret = PTR_ERR(ktype);
		goto error4;
	}

	/* do the search */
	key = request_key_and_link(ktype, description, callout_info,
				   key_ref_to_ptr(dest_ref));
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
		goto error5;
	}

	ret = key->serial;

 	key_put(key);
 error5:
	key_type_put(ktype);
 error4:
	key_ref_put(dest_ref);
 error3:
	kfree(callout_info);
 error2:
	kfree(description);
 error:
	return ret;

} /* end sys_request_key() */