Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c7e372c authored by Jann Horn's avatar Jann Horn Committed by James Morris
Browse files

security: don't use RCU accessors for cred->session_keyring



sparse complains that a bunch of places in kernel/cred.c access
cred->session_keyring without the RCU helpers required by the __rcu
annotation.

cred->session_keyring is written in the following places:

 - prepare_kernel_cred() [in a new cred struct]
 - keyctl_session_to_parent() [in a new cred struct]
 - prepare_creds [in a new cred struct, via memcpy]
 - install_session_keyring_to_cred()
  - from install_session_keyring() on new creds
  - from join_session_keyring() on new creds [twice]
  - from umh_keys_init()
   - from call_usermodehelper_exec_async() on new creds

All of these writes are before the creds are committed; therefore,
cred->session_keyring doesn't need RCU protection.

Remove the __rcu annotation and fix up all existing users that use __rcu.

Signed-off-by: default avatarJann Horn <jannh@google.com>
Signed-off-by: default avatarJames Morris <james.morris@microsoft.com>
parent 1b26fcdb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ struct cred {
#ifdef CONFIG_KEYS
	unsigned char	jit_keyring;	/* default keyring to attach requested
					 * keys to */
	struct key __rcu *session_keyring; /* keyring inherited over fork */
	struct key	*session_keyring; /* keyring inherited over fork */
	struct key	*process_keyring; /* keyring private to this process */
	struct key	*thread_keyring; /* keyring private to this thread */
	struct key	*request_key_auth; /* assumed request_key authority */
+4 −8
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ static int install_process_keyring(void)
 * Install the given keyring as the session keyring of the given credentials
 * struct, replacing the existing one if any.  If the given keyring is NULL,
 * then install a new anonymous session keyring.
 * @cred can not be in use by any task yet.
 *
 * Return: 0 on success; -errno on failure.
 */
@@ -254,7 +255,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)

	/* install the keyring */
	old = cred->session_keyring;
	rcu_assign_pointer(cred->session_keyring, keyring);
	cred->session_keyring = keyring;

	if (old)
		key_put(old);
@@ -392,11 +393,8 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)

	/* search the session keyring */
	if (ctx->cred->session_keyring) {
		rcu_read_lock();
		key_ref = keyring_search_aux(
			make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1),
			ctx);
		rcu_read_unlock();
			make_key_ref(ctx->cred->session_keyring, 1), ctx);

		if (!IS_ERR(key_ref))
			goto found;
@@ -612,10 +610,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
			goto reget_creds;
		}

		rcu_read_lock();
		key = rcu_dereference(ctx.cred->session_keyring);
		key = ctx.cred->session_keyring;
		__key_get(key);
		rcu_read_unlock();
		key_ref = make_key_ref(key, 1);
		break;

+2 −7
Original line number Diff line number Diff line
@@ -142,12 +142,10 @@ static int call_sbin_request_key(struct key *authkey, void *aux)
		prkey = cred->process_keyring->serial;
	sprintf(keyring_str[1], "%d", prkey);

	rcu_read_lock();
	session = rcu_dereference(cred->session_keyring);
	session = cred->session_keyring;
	if (!session)
		session = cred->user->session_keyring;
	sskey = session->serial;
	rcu_read_unlock();

	sprintf(keyring_str[2], "%d", sskey);

@@ -287,10 +285,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring)

			/* fall through */
		case KEY_REQKEY_DEFL_SESSION_KEYRING:
			rcu_read_lock();
			dest_keyring = key_get(
				rcu_dereference(cred->session_keyring));
			rcu_read_unlock();
			dest_keyring = key_get(cred->session_keyring);

			if (dest_keyring)
				break;