Skip to content

Commit

Permalink
keys: Add a 'recurse' flag for keyring searches
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
dhowells committed Jun 26, 2019
1 parent 355ef8e commit dcf49db
Show file tree
Hide file tree
Showing 14 changed files with 34 additions and 18 deletions.
10 changes: 6 additions & 4 deletions Documentation/security/keys/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion certs/blacklist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion crypto/asymmetric_keys/asymmetric_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion include/linux/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion lib/digsig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion net/rxrpc/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
4 changes: 2 additions & 2 deletions security/integrity/digsig_asymmetric.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions security/keys/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion security/keys/keyctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
12 changes: 10 additions & 2 deletions security/keys/keyring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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();
Expand Down
3 changes: 2 additions & 1 deletion security/keys/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion security/keys/process_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion security/keys/request_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion security/keys/request_key_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit dcf49db

Please sign in to comment.