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: David Howells <dhowells@redhat.com>
This commit is contained in:
David Howells 2019-06-26 21:02:32 +01:00
parent 355ef8e158
commit dcf49dbc80
14 changed files with 34 additions and 18 deletions

View 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

View 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;

View 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);

View 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);

View 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

View File

@ -148,7 +148,7 @@ int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
/* 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));

View 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

View 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);

View 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);

View File

@ -685,6 +685,9 @@ static bool search_nested_keyrings(struct key *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();

View 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);

View 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;

View 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;

View 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;