⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process_keys.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * search the process keyrings for the first matching key * - we use the supplied match function to see if the description (or other *   feature of interest) matches * - we return -EAGAIN if we didn't find any matching key * - we return -ENOKEY if we found only negative matching keys */key_ref_t search_process_keyrings(struct key_type *type,				  const void *description,				  key_match_func_t match,				  struct task_struct *context){	struct request_key_auth *rka;	key_ref_t key_ref, ret, err;	might_sleep();	/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were	 * searchable, but we failed to find a key or we found a negative key;	 * otherwise we want to return a sample error (probably -EACCES) if	 * none of the keyrings were searchable	 *	 * in terms of priority: success > -ENOKEY > -EAGAIN > other error	 */	key_ref = NULL;	ret = NULL;	err = ERR_PTR(-EAGAIN);	/* search the thread keyring first */	if (context->thread_keyring) {		key_ref = keyring_search_aux(			make_key_ref(context->thread_keyring, 1),			context, type, description, match);		if (!IS_ERR(key_ref))			goto found;		switch (PTR_ERR(key_ref)) {		case -EAGAIN: /* no key */			if (ret)				break;		case -ENOKEY: /* negative key */			ret = key_ref;			break;		default:			err = key_ref;			break;		}	}	/* search the process keyring second */	if (context->signal->process_keyring) {		key_ref = keyring_search_aux(			make_key_ref(context->signal->process_keyring, 1),			context, type, description, match);		if (!IS_ERR(key_ref))			goto found;		switch (PTR_ERR(key_ref)) {		case -EAGAIN: /* no key */			if (ret)				break;		case -ENOKEY: /* negative key */			ret = key_ref;			break;		default:			err = key_ref;			break;		}	}	/* search the session keyring */	if (context->signal->session_keyring) {		rcu_read_lock();		key_ref = keyring_search_aux(			make_key_ref(rcu_dereference(					     context->signal->session_keyring),				     1),			context, type, description, match);		rcu_read_unlock();		if (!IS_ERR(key_ref))			goto found;		switch (PTR_ERR(key_ref)) {		case -EAGAIN: /* no key */			if (ret)				break;		case -ENOKEY: /* negative key */			ret = key_ref;			break;		default:			err = key_ref;			break;		}	}	/* or search the user-session keyring */	else {		key_ref = keyring_search_aux(			make_key_ref(context->user->session_keyring, 1),			context, type, description, match);		if (!IS_ERR(key_ref))			goto found;		switch (PTR_ERR(key_ref)) {		case -EAGAIN: /* no key */			if (ret)				break;		case -ENOKEY: /* negative key */			ret = key_ref;			break;		default:			err = key_ref;			break;		}	}	/* if this process has an instantiation authorisation key, then we also	 * search the keyrings of the process mentioned there	 * - we don't permit access to request_key auth keys via this method	 */	if (context->request_key_auth &&	    context == current &&	    type != &key_type_request_key_auth	    ) {		/* defend against the auth key being revoked */		down_read(&context->request_key_auth->sem);		if (key_validate(context->request_key_auth) == 0) {			rka = context->request_key_auth->payload.data;			key_ref = search_process_keyrings(type, description,							  match, rka->context);			up_read(&context->request_key_auth->sem);			if (!IS_ERR(key_ref))				goto found;			switch (PTR_ERR(key_ref)) {			case -EAGAIN: /* no key */				if (ret)					break;			case -ENOKEY: /* negative key */				ret = key_ref;				break;			default:				err = key_ref;				break;			}		} else {			up_read(&context->request_key_auth->sem);		}	}	/* no key - decide on the error we're going to go for */	key_ref = ret ? ret : err;found:	return key_ref;} /* end search_process_keyrings() *//*****************************************************************************//* * see if the key we're looking at is the target key */static int lookup_user_key_possessed(const struct key *key, const void *target){	return key == target;} /* end lookup_user_key_possessed() *//*****************************************************************************//* * 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;	}	if (!partial) {		ret = wait_for_key_construction(key, true);		switch (ret) {		case -ERESTARTSYS:			goto invalid_key;		default:			if (perm)				goto invalid_key;		case 0:			break;		}	} else 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() *//*****************************************************************************//* * 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() */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -