Merge tag 'keys-request-20190626' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / security / keys / process_keys.c
index a40b336..b99ad2c 100644 (file)
@@ -314,7 +314,8 @@ void key_fsgid_changed(struct cred *new_cred)
 
 /*
  * Search the process keyrings attached to the supplied cred for the first
- * matching key.
+ * matching key under RCU conditions (the caller must be holding the RCU read
+ * lock).
  *
  * The search criteria are the type and the match function.  The description is
  * given to the match function as a parameter, but doesn't otherwise influence
@@ -333,7 +334,7 @@ void key_fsgid_changed(struct cred *new_cred)
  * In the case of a successful return, the possession attribute is set on the
  * returned key reference.
  */
-key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
+key_ref_t search_cred_keyrings_rcu(struct keyring_search_context *ctx)
 {
        key_ref_t key_ref, ret, err;
        const struct cred *cred = ctx->cred;
@@ -351,7 +352,7 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
 
        /* search the thread keyring first */
        if (cred->thread_keyring) {
-               key_ref = keyring_search_aux(
+               key_ref = keyring_search_rcu(
                        make_key_ref(cred->thread_keyring, 1), ctx);
                if (!IS_ERR(key_ref))
                        goto found;
@@ -369,7 +370,7 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
 
        /* search the process keyring second */
        if (cred->process_keyring) {
-               key_ref = keyring_search_aux(
+               key_ref = keyring_search_rcu(
                        make_key_ref(cred->process_keyring, 1), ctx);
                if (!IS_ERR(key_ref))
                        goto found;
@@ -390,7 +391,7 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
 
        /* search the session keyring */
        if (cred->session_keyring) {
-               key_ref = keyring_search_aux(
+               key_ref = keyring_search_rcu(
                        make_key_ref(cred->session_keyring, 1), ctx);
 
                if (!IS_ERR(key_ref))
@@ -411,7 +412,7 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
        }
        /* or search the user-session keyring */
        else if (READ_ONCE(cred->user->session_keyring)) {
-               key_ref = keyring_search_aux(
+               key_ref = keyring_search_rcu(
                        make_key_ref(READ_ONCE(cred->user->session_keyring), 1),
                        ctx);
                if (!IS_ERR(key_ref))
@@ -444,16 +445,16 @@ found:
  * the keys attached to the assumed authorisation key using its credentials if
  * one is available.
  *
- * Return same as search_my_process_keyrings().
+ * The caller must be holding the RCU read lock.
+ *
+ * Return same as search_cred_keyrings_rcu().
  */
-key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
+key_ref_t search_process_keyrings_rcu(struct keyring_search_context *ctx)
 {
        struct request_key_auth *rka;
        key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
 
-       might_sleep();
-
-       key_ref = search_my_process_keyrings(ctx);
+       key_ref = search_cred_keyrings_rcu(ctx);
        if (!IS_ERR(key_ref))
                goto found;
        err = key_ref;
@@ -468,24 +469,17 @@ key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
            ) {
                const struct cred *cred = ctx->cred;
 
-               /* defend against the auth key being revoked */
-               down_read(&cred->request_key_auth->sem);
-
-               if (key_validate(ctx->cred->request_key_auth) == 0) {
+               if (key_validate(cred->request_key_auth) == 0) {
                        rka = ctx->cred->request_key_auth->payload.data[0];
 
+                       //// was search_process_keyrings() [ie. recursive]
                        ctx->cred = rka->cred;
-                       key_ref = search_process_keyrings(ctx);
+                       key_ref = search_cred_keyrings_rcu(ctx);
                        ctx->cred = cred;
 
-                       up_read(&cred->request_key_auth->sem);
-
                        if (!IS_ERR(key_ref))
                                goto found;
-
                        ret = key_ref;
-               } else {
-                       up_read(&cred->request_key_auth->sem);
                }
        }
 
@@ -500,7 +494,6 @@ key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
 found:
        return key_ref;
 }
-
 /*
  * See if the key we're looking at is the target key.
  */
@@ -687,7 +680,9 @@ try_again:
                ctx.index_key                   = key->index_key;
                ctx.match_data.raw_data         = key;
                kdebug("check possessed");
-               skey_ref = search_process_keyrings(&ctx);
+               rcu_read_lock();
+               skey_ref = search_process_keyrings_rcu(&ctx);
+               rcu_read_unlock();
                kdebug("possessed=%p", skey_ref);
 
                if (!IS_ERR(skey_ref)) {