key_ref_t keyring_search(key_ref_t keyring_ref,
                                 const struct key_type *type,
-                                const char *description)
+                                const char *description,
+                                bool recurse)
 
-    This searches the keyring tree specified for a matching key. Error ENOKEY
-    is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful,
-    the returned key will need to be released.
+    This searches the specified keyring only (recurse == false) or keyring tree
+    (recurse == true) specified for a matching key. Error ENOKEY is returned
+    upon failure (use IS_ERR/PTR_ERR to determine). If successful, the returned
+    key will need to be released.
 
     The possession attribute from the keyring reference is used to control
     access through the permissions mask and is propagated to the returned key
 
        *p = 0;
 
        kref = keyring_search(make_key_ref(blacklist_keyring, true),
-                             &key_type_blacklist, buffer);
+                             &key_type_blacklist, buffer, false);
        if (!IS_ERR(kref)) {
                key_ref_put(kref);
                ret = -EKEYREJECTED;
 
        pr_debug("Look up: \"%s\"\n", req);
 
        ref = keyring_search(make_key_ref(keyring, 1),
-                            &key_type_asymmetric, req);
+                            &key_type_asymmetric, req, true);
        if (IS_ERR(ref))
                pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
        kfree(req);
 
 
 extern key_ref_t keyring_search(key_ref_t keyring,
                                struct key_type *type,
-                               const char *description);
+                               const char *description,
+                               bool recurse);
 
 extern int keyring_add_key(struct key *keyring,
                           struct key *key);
 
                /* search in specific keyring */
                key_ref_t kref;
                kref = keyring_search(make_key_ref(keyring, 1UL),
-                                               &key_type_user, name);
+                                     &key_type_user, name, true);
                if (IS_ERR(kref))
                        key = ERR_CAST(kref);
                else
 
 
        /* look through the service's keyring */
        kref = keyring_search(make_key_ref(rx->securities, 1UL),
-                             &key_type_rxrpc_s, kdesc);
+                             &key_type_rxrpc_s, kdesc, true);
        if (IS_ERR(kref)) {
                read_unlock(&local->services_lock);
                _leave(" = %ld [search]", PTR_ERR(kref));
 
                key_ref_t kref;
 
                kref = keyring_search(make_key_ref(key, 1),
-                                    &key_type_asymmetric, name);
+                                     &key_type_asymmetric, name, true);
                if (!IS_ERR(kref)) {
                        pr_err("Key '%s' is in ima_blacklist_keyring\n", name);
                        return ERR_PTR(-EKEYREJECTED);
                key_ref_t kref;
 
                kref = keyring_search(make_key_ref(keyring, 1),
-                                     &key_type_asymmetric, name);
+                                     &key_type_asymmetric, name, true);
                if (IS_ERR(kref))
                        key = ERR_CAST(kref);
                else
 
 #define KEYRING_SEARCH_NO_CHECK_PERM   0x0008  /* Don't check permissions */
 #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010  /* Give an error on excessive depth */
 #define KEYRING_SEARCH_SKIP_EXPIRED    0x0020  /* Ignore expired keys (intention to replace) */
+#define KEYRING_SEARCH_RECURSE         0x0040  /* Search child keyrings also */
 
        int (*iterator)(const void *object, void *iterator_data);
 
 
        }
 
        /* do the search */
-       key_ref = keyring_search(keyring_ref, ktype, description);
+       key_ref = keyring_search(keyring_ref, ktype, description, true);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
 
 
         * Non-keyrings avoid the leftmost branch of the root entirely (root
         * slots 1-15).
         */
+       if (!(ctx->flags & KEYRING_SEARCH_RECURSE))
+               goto not_this_keyring;
+
        ptr = READ_ONCE(keyring->keys.root);
        if (!ptr)
                goto not_this_keyring;
  * @keyring: The root of the keyring tree to be searched.
  * @type: The type of keyring we want to find.
  * @description: The name of the keyring we want to find.
+ * @recurse: True to search the children of @keyring also
  *
  * As keyring_search_rcu() above, but using the current task's credentials and
  * type's default matching function and preferred search method.
  */
 key_ref_t keyring_search(key_ref_t keyring,
                         struct key_type *type,
-                        const char *description)
+                        const char *description,
+                        bool recurse)
 {
        struct keyring_search_context ctx = {
                .index_key.type         = type,
        key_ref_t key;
        int ret;
 
+       if (recurse)
+               ctx.flags |= KEYRING_SEARCH_RECURSE;
        if (type->match_preparse) {
                ret = type->match_preparse(&ctx.match_data);
                if (ret < 0)
                .flags                  = (KEYRING_SEARCH_NO_STATE_CHECK |
                                           KEYRING_SEARCH_NO_UPDATE_TIME |
                                           KEYRING_SEARCH_NO_CHECK_PERM |
-                                          KEYRING_SEARCH_DETECT_TOO_DEEP),
+                                          KEYRING_SEARCH_DETECT_TOO_DEEP |
+                                          KEYRING_SEARCH_RECURSE),
        };
 
        rcu_read_lock();
 
                .match_data.cmp         = lookup_user_key_possessed,
                .match_data.raw_data    = key,
                .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
-               .flags                  = KEYRING_SEARCH_NO_STATE_CHECK,
+               .flags                  = (KEYRING_SEARCH_NO_STATE_CHECK |
+                                          KEYRING_SEARCH_RECURSE),
        };
 
        key_ref = make_key_ref(key, 0);
 
        struct keyring_search_context ctx = {
                .match_data.cmp         = lookup_user_key_possessed,
                .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
-               .flags                  = KEYRING_SEARCH_NO_STATE_CHECK,
+               .flags                  = (KEYRING_SEARCH_NO_STATE_CHECK |
+                                          KEYRING_SEARCH_RECURSE),
        };
        struct request_key_auth *rka;
        struct key *key;
 
                .match_data.raw_data    = description,
                .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
                .flags                  = (KEYRING_SEARCH_DO_STATE_CHECK |
-                                          KEYRING_SEARCH_SKIP_EXPIRED),
+                                          KEYRING_SEARCH_SKIP_EXPIRED |
+                                          KEYRING_SEARCH_RECURSE),
        };
        struct key *key;
        key_ref_t key_ref;
 
                .match_data.cmp         = key_default_cmp,
                .match_data.raw_data    = description,
                .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
-               .flags                  = KEYRING_SEARCH_DO_STATE_CHECK,
+               .flags                  = (KEYRING_SEARCH_DO_STATE_CHECK |
+                                          KEYRING_SEARCH_RECURSE),
        };
        struct key *authkey;
        key_ref_t authkey_ref;