keys: Add a 'recurse' flag for keyring searches
authorDavid Howells <dhowells@redhat.com>
Wed, 26 Jun 2019 20:02:32 +0000 (21:02 +0100)
committerDavid Howells <dhowells@redhat.com>
Wed, 26 Jun 2019 20:02:32 +0000 (21:02 +0100)
Add a 'recurse' flag for keyring searches so that the flag can be omitted
and recursion disabled, thereby allowing just the nominated keyring to be
searched and none of the children.

Signed-off-by: David Howells <dhowells@redhat.com>
14 files changed:
Documentation/security/keys/core.rst
certs/blacklist.c
crypto/asymmetric_keys/asymmetric_type.c
include/linux/key.h
lib/digsig.c
net/rxrpc/security.c
security/integrity/digsig_asymmetric.c
security/keys/internal.h
security/keys/keyctl.c
security/keys/keyring.c
security/keys/proc.c
security/keys/process_keys.c
security/keys/request_key.c
security/keys/request_key_auth.c

index a0e245f..ae930ae 100644 (file)
@@ -1162,11 +1162,13 @@ payload contents" for more information.
 
        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
index 3a507b9..181cb7f 100644 (file)
@@ -128,7 +128,7 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
        *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;
index 69a0788..084027e 100644 (file)
@@ -87,7 +87,7 @@ struct key *find_asymmetric_key(struct key *keyring,
        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);
index fb2debc..ff10273 100644 (file)
@@ -341,7 +341,8 @@ extern int keyring_clear(struct key *keyring);
 
 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);
index 3b0a579..3782af4 100644 (file)
@@ -221,7 +221,7 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen,
                /* 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
index c4479af..2cfc712 100644 (file)
@@ -148,7 +148,7 @@ found_service:
 
        /* 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));
index 9908087..358f614 100644 (file)
@@ -39,7 +39,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
                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);
@@ -51,7 +51,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
                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
index 4305414..aa36129 100644 (file)
@@ -127,6 +127,7 @@ struct keyring_search_context {
 #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);
 
index 9f418e6..169409b 100644 (file)
@@ -762,7 +762,7 @@ long keyctl_keyring_search(key_serial_t ringid,
        }
 
        /* 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);
 
index a5ee3b4..20891cd 100644 (file)
@@ -685,6 +685,9 @@ descend_to_keyring:
         * 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;
@@ -885,13 +888,15 @@ key_ref_t keyring_search_rcu(key_ref_t keyring_ref,
  * @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,
@@ -906,6 +911,8 @@ key_ref_t keyring_search(key_ref_t keyring,
        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)
@@ -1176,7 +1183,8 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
                .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();
index f081dce..b4f5ba5 100644 (file)
@@ -170,7 +170,8 @@ static int proc_keys_show(struct seq_file *m, void *v)
                .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);
index f8ffb06..b07f768 100644 (file)
@@ -531,7 +531,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
        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;
index 36c55ef..1ffd380 100644 (file)
@@ -569,7 +569,8 @@ struct key *request_key_and_link(struct key_type *type,
                .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;
index 99ed7a8..f613987 100644 (file)
@@ -252,7 +252,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
                .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;