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 a0e245f9576f76993214c09222391747f7c5122b..ae930ae9d590804e8a63d88e07bfc3fb4a8b4ccf 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 3a507b9e2568a27e9d2e4359fc4fbdc3218dda4b..181cb7fa95400625363eb5cfd9e6347832b81998 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 69a0788a7de5d08eddc6ad82451f2515ed94f6d4..084027ef31214c6314e58fe5bbbededf269838c3 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 fb2debcacea0e105df572e74b2ab27296a1481af..ff102731b3dbd7b228055c978ae1fd7a431b325b 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 3b0a579bdcdf8c9ea15abae32df8be3ae69cd4cc..3782af401c685c92f5f224beb61cf24fcf957ee7 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 c4479afe8ae70999e0ba472b760e4cd26ccd19e1..2cfc7125bc41edb4baf26cc66e8ac834f81bbeeb 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 99080871eb9f5161f97d6e1571a7ce51555cbe02..358f614811e8440279d0cca92024b3b112b069b1 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 4305414795ae1e47ecfcf767348f7e74a5c807da..aa361299a3ecd7f11d0df630a1bb3f539b46f02e 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 9f418e66f067d1c3c6d588ec8a270419f3b0234d..169409b611b0189cd2eeafc7a63eca5a0adb6b01 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 a5ee3b4d2eb8f2cbe78f53761036d46b8d3beb49..20891cd198f041e65bcdcb32934199b5f2e55a74 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 f081dceae3b9b45c6db33a5de31d25e8cbc792bd..b4f5ba56b9cb996b655ef569c335cc2215944062 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 f8ffb06d0297d2151d7ad4f01922589dea3344ab..b07f768d23dcf738e9fb463e6583d3807c8bed56 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 36c55ef47b9ee1c853bd6a50bb4f844271017520..1ffd3803ce29d3a4dadc26e3a2a136825334d589 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 99ed7a8a273df6662e780bd721aa0728e8f1cf9d..f613987e8a63091729adf1adbdbc76b4846ac08e 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;