security/keys/process_keys.c

Source file repositories/reference/linux-study-clean/security/keys/process_keys.c

File Facts

System
Linux kernel
Corpus path
security/keys/process_keys.c
Extension
.c
Size
24236 bytes
Lines
966
Domain
Core OS
Bucket
Security And Isolation
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (IS_ERR(uid_keyring)) {
			ret = PTR_ERR(uid_keyring);
			goto error;
		}
	} else if (IS_ERR(uid_keyring_r)) {
		ret = PTR_ERR(uid_keyring_r);
		goto error;
	} else {
		uid_keyring = key_ref_to_ptr(uid_keyring_r);
	}

	/* Get a default session keyring (which might also exist already) */
	snprintf(buf, sizeof(buf), "_uid_ses.%u", uid);
	session_keyring_r = keyring_search(make_key_ref(reg_keyring, true),
					   &key_type_keyring, buf, false);
	kdebug("_uid_ses %p", session_keyring_r);
	if (session_keyring_r == ERR_PTR(-EAGAIN)) {
		session_keyring = keyring_alloc(buf, cred->user->uid, INVALID_GID,
						cred, user_keyring_perm,
						KEY_ALLOC_UID_KEYRING |
						KEY_ALLOC_IN_QUOTA,
						NULL, NULL);
		if (IS_ERR(session_keyring)) {
			ret = PTR_ERR(session_keyring);
			goto error_release;
		}

		/* We install a link from the user session keyring to
		 * the user keyring.
		 */
		ret = key_link(session_keyring, uid_keyring);
		if (ret < 0)
			goto error_release_session;

		/* And only then link the user-session keyring to the
		 * register.
		 */
		ret = key_link(reg_keyring, session_keyring);
		if (ret < 0)
			goto error_release_session;
	} else if (IS_ERR(session_keyring_r)) {
		ret = PTR_ERR(session_keyring_r);
		goto error_release;
	} else {
		session_keyring = key_ref_to_ptr(session_keyring_r);
	}

	up_write(&user_ns->keyring_sem);

	if (_user_session_keyring)
		*_user_session_keyring = session_keyring;
	else
		key_put(session_keyring);
	if (_user_keyring)
		*_user_keyring = uid_keyring;
	else
		key_put(uid_keyring);
	kleave(" = 0");
	return 0;

error_release_session:
	key_put(session_keyring);
error_release:
	key_put(uid_keyring);
error:
	up_write(&user_ns->keyring_sem);
	kleave(" = %d", ret);
	return ret;
}

/*
 * Get the user session keyring if it exists, but don't create it if it
 * doesn't.
 */
struct key *get_user_session_keyring_rcu(const struct cred *cred)
{
	struct key *reg_keyring = READ_ONCE(cred->user_ns->user_keyring_register);
	key_ref_t session_keyring_r;
	char buf[20];

	struct keyring_search_context ctx = {
		.index_key.type		= &key_type_keyring,
		.index_key.description	= buf,
		.cred			= cred,
		.match_data.cmp		= key_default_cmp,
		.match_data.raw_data	= buf,
		.match_data.lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
		.flags			= KEYRING_SEARCH_DO_STATE_CHECK,
	};

Annotation

Implementation Notes