예제 #1
0
/*
 * join the named keyring as the session keyring if possible, or attempt to
 * create a new one of that name if not
 * - if the name is NULL, an empty anonymous keyring is installed instead
 * - named session keyring joining is done with a semaphore held
 */
long join_session_keyring(const char *name)
{
	struct task_struct *tsk = current;
	unsigned long flags;
	struct key *keyring;
	long ret;

	/* if no name is provided, install an anonymous keyring */
	if (!name) {
		ret = install_session_keyring(tsk, NULL);
		if (ret < 0)
			goto error;

		spin_lock_irqsave(&tsk->sighand->siglock, flags);
		ret = tsk->signal->session_keyring->serial;
		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
		goto error;
	}

	/* allow the user to join or create a named keyring */
	down(&key_session_sem);

	/* look for an existing keyring of this name */
	keyring = find_keyring_by_name(name, 0);
	if (PTR_ERR(keyring) == -ENOKEY) {
		/* not found - try and create a new one */
		keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL);
		if (IS_ERR(keyring)) {
			ret = PTR_ERR(keyring);
			goto error;
		}
	}
	else if (IS_ERR(keyring)) {
		ret = PTR_ERR(keyring);
		goto error2;
	}

	/* we've got a keyring - now to install it */
	ret = install_session_keyring(tsk, keyring);
	if (ret < 0)
		goto error2;

	ret = keyring->serial;
	key_put(keyring);

 error2:
	up(&key_session_sem);
 error:
	return ret;

} /* end join_session_keyring() */
예제 #2
0
/*
 * join the named keyring as the session keyring if possible, or attempt to
 * create a new one of that name if not
 * - if the name is NULL, an empty anonymous keyring is installed instead
 * - named session keyring joining is done with a semaphore held
 */
long join_session_keyring(const char *name)
{
	struct task_struct *tsk = current;
	struct key *keyring;
	long ret;

	/* if no name is provided, install an anonymous keyring */
	if (!name) {
		ret = install_session_keyring(tsk, NULL);
		if (ret < 0)
			goto error;

		rcu_read_lock();
		ret = rcu_dereference(tsk->signal->session_keyring)->serial;
		rcu_read_unlock();
		goto error;
	}

	/* allow the user to join or create a named keyring */
	mutex_lock(&key_session_mutex);

	/* look for an existing keyring of this name */
	keyring = find_keyring_by_name(name, 0);
	if (PTR_ERR(keyring) == -ENOKEY) {
		/* not found - try and create a new one */
		keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
					KEY_ALLOC_IN_QUOTA, NULL);
		if (IS_ERR(keyring)) {
			ret = PTR_ERR(keyring);
			goto error2;
		}
	}
	else if (IS_ERR(keyring)) {
		ret = PTR_ERR(keyring);
		goto error2;
	}

	/* we've got a keyring - now to install it */
	ret = install_session_keyring(tsk, keyring);
	if (ret < 0)
		goto error2;

	ret = keyring->serial;
	key_put(keyring);

error2:
	mutex_unlock(&key_session_mutex);
error:
	return ret;

} /* end join_session_keyring() */
예제 #3
0
/*
 * lookup a key given a key ID from userspace with a given permissions mask
 * - don't create special keyrings unless so requested
 * - partially constructed keys aren't found unless requested
 */
struct key *lookup_user_key(key_serial_t id, int create, int partial,
			    key_perm_t perm)
{
	struct task_struct *tsk = current;
	unsigned long flags;
	struct key *key;
	int ret;

	key = ERR_PTR(-ENOKEY);

	switch (id) {
	case KEY_SPEC_THREAD_KEYRING:
		if (!tsk->thread_keyring) {
			if (!create)
				goto error;

			ret = install_thread_keyring(tsk);
			if (ret < 0) {
				key = ERR_PTR(ret);
				goto error;
			}
		}

		key = tsk->thread_keyring;
		atomic_inc(&key->usage);
		break;

	case KEY_SPEC_PROCESS_KEYRING:
		if (!tsk->signal->process_keyring) {
			if (!create)
				goto error;

			ret = install_process_keyring(tsk);
			if (ret < 0) {
				key = ERR_PTR(ret);
				goto error;
			}
		}

		key = tsk->signal->process_keyring;
		atomic_inc(&key->usage);
		break;

	case KEY_SPEC_SESSION_KEYRING:
		if (!tsk->signal->session_keyring) {
			/* always install a session keyring upon access if one
			 * doesn't exist yet */
			ret = install_session_keyring(
			       tsk, tsk->user->session_keyring);
			if (ret < 0)
				goto error;
		}

		spin_lock_irqsave(&tsk->sighand->siglock, flags);
		key = tsk->signal->session_keyring;
		atomic_inc(&key->usage);
		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
		break;

	case KEY_SPEC_USER_KEYRING:
		key = tsk->user->uid_keyring;
		atomic_inc(&key->usage);
		break;

	case KEY_SPEC_USER_SESSION_KEYRING:
		key = tsk->user->session_keyring;
		atomic_inc(&key->usage);
		break;

	case KEY_SPEC_GROUP_KEYRING:
		/* group keyrings are not yet supported */
		key = ERR_PTR(-EINVAL);
		goto error;

	default:
		key = ERR_PTR(-EINVAL);
		if (id < 1)
			goto error;

		key = key_lookup(id);
		if (IS_ERR(key))
			goto error;
		break;
	}

	/* check the status and permissions */
	if (perm) {
		ret = key_validate(key);
		if (ret < 0)
			goto invalid_key;
	}

	ret = -EIO;
	if (!partial && !(key->flags & KEY_FLAG_INSTANTIATED))
		goto invalid_key;

	ret = -EACCES;
	if (!key_permission(key, perm))
		goto invalid_key;

 error:
	return key;

 invalid_key:
	key_put(key);
	key = ERR_PTR(ret);
	goto error;

} /* end lookup_user_key() */
예제 #4
0
/*
 * lookup a key given a key ID from userspace with a given permissions mask
 * - don't create special keyrings unless so requested
 * - partially constructed keys aren't found unless requested
 */
key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
			  int create, int partial, key_perm_t perm)
{
	key_ref_t key_ref, skey_ref;
	struct key *key;
	int ret;

	if (!context)
		context = current;

	key_ref = ERR_PTR(-ENOKEY);

	switch (id) {
	case KEY_SPEC_THREAD_KEYRING:
		if (!context->thread_keyring) {
			if (!create)
				goto error;

			ret = install_thread_keyring(context);
			if (ret < 0) {
				key = ERR_PTR(ret);
				goto error;
			}
		}

		key = context->thread_keyring;
		atomic_inc(&key->usage);
		key_ref = make_key_ref(key, 1);
		break;

	case KEY_SPEC_PROCESS_KEYRING:
		if (!context->signal->process_keyring) {
			if (!create)
				goto error;

			ret = install_process_keyring(context);
			if (ret < 0) {
				key = ERR_PTR(ret);
				goto error;
			}
		}

		key = context->signal->process_keyring;
		atomic_inc(&key->usage);
		key_ref = make_key_ref(key, 1);
		break;

	case KEY_SPEC_SESSION_KEYRING:
		if (!context->signal->session_keyring) {
			/* always install a session keyring upon access if one
			 * doesn't exist yet */
			ret = install_session_keyring(
				context, context->user->session_keyring);
			if (ret < 0)
				goto error;
		}

		rcu_read_lock();
		key = rcu_dereference(context->signal->session_keyring);
		atomic_inc(&key->usage);
		rcu_read_unlock();
		key_ref = make_key_ref(key, 1);
		break;

	case KEY_SPEC_USER_KEYRING:
		key = context->user->uid_keyring;
		atomic_inc(&key->usage);
		key_ref = make_key_ref(key, 1);
		break;

	case KEY_SPEC_USER_SESSION_KEYRING:
		key = context->user->session_keyring;
		atomic_inc(&key->usage);
		key_ref = make_key_ref(key, 1);
		break;

	case KEY_SPEC_GROUP_KEYRING:
		/* group keyrings are not yet supported */
		key = ERR_PTR(-EINVAL);
		goto error;

	case KEY_SPEC_REQKEY_AUTH_KEY:
		key = context->request_key_auth;
		if (!key)
			goto error;

		atomic_inc(&key->usage);
		key_ref = make_key_ref(key, 1);
		break;

	default:
		key_ref = ERR_PTR(-EINVAL);
		if (id < 1)
			goto error;

		key = key_lookup(id);
		if (IS_ERR(key)) {
			key_ref = ERR_PTR(PTR_ERR(key));
			goto error;
		}

		key_ref = make_key_ref(key, 0);

		/* check to see if we possess the key */
		skey_ref = search_process_keyrings(key->type, key,
						   lookup_user_key_possessed,
						   current);

		if (!IS_ERR(skey_ref)) {
			key_put(key);
			key_ref = skey_ref;
		}

		break;
	}

	/* check the status */
	if (perm) {
		ret = key_validate(key);
		if (ret < 0)
			goto invalid_key;
	}

	ret = -EIO;
	if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
		goto invalid_key;

	/* check the permissions */
	ret = key_task_permission(key_ref, context, perm);
	if (ret < 0)
		goto invalid_key;

error:
	return key_ref;

invalid_key:
	key_ref_put(key_ref);
	key_ref = ERR_PTR(ret);
	goto error;

} /* end lookup_user_key() */