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

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
...@@ -138,7 +138,7 @@ struct cred { ...@@ -138,7 +138,7 @@ struct cred {
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
unsigned char jit_keyring; /* default keyring to attach requested unsigned char jit_keyring; /* default keyring to attach requested
* keys to */ * 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 *process_keyring; /* keyring private to this process */
struct key *thread_keyring; /* keyring private to this thread */ struct key *thread_keyring; /* keyring private to this thread */
struct key *request_key_auth; /* assumed request_key authority */ struct key *request_key_auth; /* assumed request_key authority */
......
...@@ -227,6 +227,7 @@ static int install_process_keyring(void) ...@@ -227,6 +227,7 @@ static int install_process_keyring(void)
* Install the given keyring as the session keyring of the given credentials * 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, * struct, replacing the existing one if any. If the given keyring is NULL,
* then install a new anonymous session keyring. * then install a new anonymous session keyring.
* @cred can not be in use by any task yet.
* *
* Return: 0 on success; -errno on failure. * Return: 0 on success; -errno on failure.
*/ */
...@@ -254,7 +255,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) ...@@ -254,7 +255,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
/* install the keyring */ /* install the keyring */
old = cred->session_keyring; old = cred->session_keyring;
rcu_assign_pointer(cred->session_keyring, keyring); cred->session_keyring = keyring;
if (old) if (old)
key_put(old); key_put(old);
...@@ -392,11 +393,8 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) ...@@ -392,11 +393,8 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
/* search the session keyring */ /* search the session keyring */
if (ctx->cred->session_keyring) { if (ctx->cred->session_keyring) {
rcu_read_lock();
key_ref = keyring_search_aux( key_ref = keyring_search_aux(
make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1), make_key_ref(ctx->cred->session_keyring, 1), ctx);
ctx);
rcu_read_unlock();
if (!IS_ERR(key_ref)) if (!IS_ERR(key_ref))
goto found; goto found;
...@@ -612,10 +610,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, ...@@ -612,10 +610,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
goto reget_creds; goto reget_creds;
} }
rcu_read_lock(); key = ctx.cred->session_keyring;
key = rcu_dereference(ctx.cred->session_keyring);
__key_get(key); __key_get(key);
rcu_read_unlock();
key_ref = make_key_ref(key, 1); key_ref = make_key_ref(key, 1);
break; break;
......
...@@ -142,12 +142,10 @@ static int call_sbin_request_key(struct key *authkey, void *aux) ...@@ -142,12 +142,10 @@ static int call_sbin_request_key(struct key *authkey, void *aux)
prkey = cred->process_keyring->serial; prkey = cred->process_keyring->serial;
sprintf(keyring_str[1], "%d", prkey); sprintf(keyring_str[1], "%d", prkey);
rcu_read_lock(); session = cred->session_keyring;
session = rcu_dereference(cred->session_keyring);
if (!session) if (!session)
session = cred->user->session_keyring; session = cred->user->session_keyring;
sskey = session->serial; sskey = session->serial;
rcu_read_unlock();
sprintf(keyring_str[2], "%d", sskey); sprintf(keyring_str[2], "%d", sskey);
...@@ -287,10 +285,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) ...@@ -287,10 +285,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring)
/* fall through */ /* fall through */
case KEY_REQKEY_DEFL_SESSION_KEYRING: case KEY_REQKEY_DEFL_SESSION_KEYRING:
rcu_read_lock(); dest_keyring = key_get(cred->session_keyring);
dest_keyring = key_get(
rcu_dereference(cred->session_keyring));
rcu_read_unlock();
if (dest_keyring) if (dest_keyring)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment