Commit dcf49dbc authored by David Howells's avatar David Howells

keys: Add a 'recurse' flag for keyring searches

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: default avatarDavid Howells <dhowells@redhat.com>
parent 355ef8e1
...@@ -1162,11 +1162,13 @@ payload contents" for more information. ...@@ -1162,11 +1162,13 @@ payload contents" for more information.
key_ref_t keyring_search(key_ref_t keyring_ref, key_ref_t keyring_search(key_ref_t keyring_ref,
const struct key_type *type, 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 This searches the specified keyring only (recurse == false) or keyring tree
is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful, (recurse == true) specified for a matching key. Error ENOKEY is returned
the returned key will need to be released. 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 The possession attribute from the keyring reference is used to control
access through the permissions mask and is propagated to the returned key access through the permissions mask and is propagated to the returned key
......
...@@ -128,7 +128,7 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type) ...@@ -128,7 +128,7 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
*p = 0; *p = 0;
kref = keyring_search(make_key_ref(blacklist_keyring, true), kref = keyring_search(make_key_ref(blacklist_keyring, true),
&key_type_blacklist, buffer); &key_type_blacklist, buffer, false);
if (!IS_ERR(kref)) { if (!IS_ERR(kref)) {
key_ref_put(kref); key_ref_put(kref);
ret = -EKEYREJECTED; ret = -EKEYREJECTED;
......
...@@ -87,7 +87,7 @@ struct key *find_asymmetric_key(struct key *keyring, ...@@ -87,7 +87,7 @@ struct key *find_asymmetric_key(struct key *keyring,
pr_debug("Look up: \"%s\"\n", req); pr_debug("Look up: \"%s\"\n", req);
ref = keyring_search(make_key_ref(keyring, 1), ref = keyring_search(make_key_ref(keyring, 1),
&key_type_asymmetric, req); &key_type_asymmetric, req, true);
if (IS_ERR(ref)) if (IS_ERR(ref))
pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
kfree(req); kfree(req);
......
...@@ -341,7 +341,8 @@ extern int keyring_clear(struct key *keyring); ...@@ -341,7 +341,8 @@ extern int keyring_clear(struct key *keyring);
extern key_ref_t keyring_search(key_ref_t keyring, extern key_ref_t keyring_search(key_ref_t keyring,
struct key_type *type, struct key_type *type,
const char *description); const char *description,
bool recurse);
extern int keyring_add_key(struct key *keyring, extern int keyring_add_key(struct key *keyring,
struct key *key); struct key *key);
......
...@@ -221,7 +221,7 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen, ...@@ -221,7 +221,7 @@ int digsig_verify(struct key *keyring, const char *sig, int siglen,
/* search in specific keyring */ /* search in specific keyring */
key_ref_t kref; key_ref_t kref;
kref = keyring_search(make_key_ref(keyring, 1UL), kref = keyring_search(make_key_ref(keyring, 1UL),
&key_type_user, name); &key_type_user, name, true);
if (IS_ERR(kref)) if (IS_ERR(kref))
key = ERR_CAST(kref); key = ERR_CAST(kref);
else else
......
...@@ -148,7 +148,7 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn) ...@@ -148,7 +148,7 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
/* look through the service's keyring */ /* look through the service's keyring */
kref = keyring_search(make_key_ref(rx->securities, 1UL), kref = keyring_search(make_key_ref(rx->securities, 1UL),
&key_type_rxrpc_s, kdesc); &key_type_rxrpc_s, kdesc, true);
if (IS_ERR(kref)) { if (IS_ERR(kref)) {
read_unlock(&local->services_lock); read_unlock(&local->services_lock);
_leave(" = %ld [search]", PTR_ERR(kref)); _leave(" = %ld [search]", PTR_ERR(kref));
......
...@@ -39,7 +39,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) ...@@ -39,7 +39,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
key_ref_t kref; key_ref_t kref;
kref = keyring_search(make_key_ref(key, 1), kref = keyring_search(make_key_ref(key, 1),
&key_type_asymmetric, name); &key_type_asymmetric, name, true);
if (!IS_ERR(kref)) { if (!IS_ERR(kref)) {
pr_err("Key '%s' is in ima_blacklist_keyring\n", name); pr_err("Key '%s' is in ima_blacklist_keyring\n", name);
return ERR_PTR(-EKEYREJECTED); return ERR_PTR(-EKEYREJECTED);
...@@ -51,7 +51,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) ...@@ -51,7 +51,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
key_ref_t kref; key_ref_t kref;
kref = keyring_search(make_key_ref(keyring, 1), kref = keyring_search(make_key_ref(keyring, 1),
&key_type_asymmetric, name); &key_type_asymmetric, name, true);
if (IS_ERR(kref)) if (IS_ERR(kref))
key = ERR_CAST(kref); key = ERR_CAST(kref);
else else
......
...@@ -127,6 +127,7 @@ struct keyring_search_context { ...@@ -127,6 +127,7 @@ struct keyring_search_context {
#define KEYRING_SEARCH_NO_CHECK_PERM 0x0008 /* Don't check permissions */ #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_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_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); int (*iterator)(const void *object, void *iterator_data);
......
...@@ -762,7 +762,7 @@ long keyctl_keyring_search(key_serial_t ringid, ...@@ -762,7 +762,7 @@ long keyctl_keyring_search(key_serial_t ringid,
} }
/* do the search */ /* 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)) { if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref); ret = PTR_ERR(key_ref);
......
...@@ -685,6 +685,9 @@ static bool search_nested_keyrings(struct key *keyring, ...@@ -685,6 +685,9 @@ static bool search_nested_keyrings(struct key *keyring,
* Non-keyrings avoid the leftmost branch of the root entirely (root * Non-keyrings avoid the leftmost branch of the root entirely (root
* slots 1-15). * slots 1-15).
*/ */
if (!(ctx->flags & KEYRING_SEARCH_RECURSE))
goto not_this_keyring;
ptr = READ_ONCE(keyring->keys.root); ptr = READ_ONCE(keyring->keys.root);
if (!ptr) if (!ptr)
goto not_this_keyring; goto not_this_keyring;
...@@ -885,13 +888,15 @@ key_ref_t keyring_search_rcu(key_ref_t keyring_ref, ...@@ -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. * @keyring: The root of the keyring tree to be searched.
* @type: The type of keyring we want to find. * @type: The type of keyring we want to find.
* @description: The name of the 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 * As keyring_search_rcu() above, but using the current task's credentials and
* type's default matching function and preferred search method. * type's default matching function and preferred search method.
*/ */
key_ref_t keyring_search(key_ref_t keyring, key_ref_t keyring_search(key_ref_t keyring,
struct key_type *type, struct key_type *type,
const char *description) const char *description,
bool recurse)
{ {
struct keyring_search_context ctx = { struct keyring_search_context ctx = {
.index_key.type = type, .index_key.type = type,
...@@ -906,6 +911,8 @@ key_ref_t keyring_search(key_ref_t keyring, ...@@ -906,6 +911,8 @@ key_ref_t keyring_search(key_ref_t keyring,
key_ref_t key; key_ref_t key;
int ret; int ret;
if (recurse)
ctx.flags |= KEYRING_SEARCH_RECURSE;
if (type->match_preparse) { if (type->match_preparse) {
ret = type->match_preparse(&ctx.match_data); ret = type->match_preparse(&ctx.match_data);
if (ret < 0) if (ret < 0)
...@@ -1176,7 +1183,8 @@ static int keyring_detect_cycle(struct key *A, struct key *B) ...@@ -1176,7 +1183,8 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
.flags = (KEYRING_SEARCH_NO_STATE_CHECK | .flags = (KEYRING_SEARCH_NO_STATE_CHECK |
KEYRING_SEARCH_NO_UPDATE_TIME | KEYRING_SEARCH_NO_UPDATE_TIME |
KEYRING_SEARCH_NO_CHECK_PERM | KEYRING_SEARCH_NO_CHECK_PERM |
KEYRING_SEARCH_DETECT_TOO_DEEP), KEYRING_SEARCH_DETECT_TOO_DEEP |
KEYRING_SEARCH_RECURSE),
}; };
rcu_read_lock(); rcu_read_lock();
......
...@@ -170,7 +170,8 @@ static int proc_keys_show(struct seq_file *m, void *v) ...@@ -170,7 +170,8 @@ static int proc_keys_show(struct seq_file *m, void *v)
.match_data.cmp = lookup_user_key_possessed, .match_data.cmp = lookup_user_key_possessed,
.match_data.raw_data = key, .match_data.raw_data = key,
.match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, .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); key_ref = make_key_ref(key, 0);
......
...@@ -531,7 +531,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, ...@@ -531,7 +531,8 @@ key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
struct keyring_search_context ctx = { struct keyring_search_context ctx = {
.match_data.cmp = lookup_user_key_possessed, .match_data.cmp = lookup_user_key_possessed,
.match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, .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 request_key_auth *rka;
struct key *key; struct key *key;
......
...@@ -569,7 +569,8 @@ struct key *request_key_and_link(struct key_type *type, ...@@ -569,7 +569,8 @@ struct key *request_key_and_link(struct key_type *type,
.match_data.raw_data = description, .match_data.raw_data = description,
.match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
.flags = (KEYRING_SEARCH_DO_STATE_CHECK | .flags = (KEYRING_SEARCH_DO_STATE_CHECK |
KEYRING_SEARCH_SKIP_EXPIRED), KEYRING_SEARCH_SKIP_EXPIRED |
KEYRING_SEARCH_RECURSE),
}; };
struct key *key; struct key *key;
key_ref_t key_ref; key_ref_t key_ref;
......
...@@ -252,7 +252,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) ...@@ -252,7 +252,8 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
.match_data.cmp = key_default_cmp, .match_data.cmp = key_default_cmp,
.match_data.raw_data = description, .match_data.raw_data = description,
.match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, .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; struct key *authkey;
key_ref_t authkey_ref; key_ref_t authkey_ref;
......
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