diff options
author | David Howells <dhowells@redhat.com> | 2019-06-19 16:10:15 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-06-19 16:10:15 +0100 |
commit | 896f1950e5944532b971d880a6bae7fba3b6a8d3 (patch) | |
tree | 8bf2eddc61af7f782bdd579e87fa0f7760ea5ced /security | |
parent | e59428f721ee096d8a020504ea908a6f0d952735 (diff) |
keys: Provide request_key_rcu()
Provide a request_key_rcu() function that can be used to request a key
under RCU conditions. It can only search and check permissions; it cannot
allocate a new key, upcall or wait for an upcall to complete. It may
return a partially constructed key.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'security')
-rw-r--r-- | security/keys/request_key.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index bf1d223ec21c..b4b3677657d6 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -756,3 +756,47 @@ struct key *request_key_async_with_auxdata(struct key_type *type, callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA); } EXPORT_SYMBOL(request_key_async_with_auxdata); + +/** + * request_key_rcu - Request key from RCU-read-locked context + * @type: The type of key we want. + * @description: The name of the key we want. + * + * Request a key from a context that we may not sleep in (such as RCU-mode + * pathwalk). Keys under construction are ignored. + * + * Return a pointer to the found key if successful, -ENOKEY if we couldn't find + * a key or some other error if the key found was unsuitable or inaccessible. + */ +struct key *request_key_rcu(struct key_type *type, const char *description) +{ + struct keyring_search_context ctx = { + .index_key.type = type, + .index_key.description = description, + .index_key.desc_len = strlen(description), + .cred = current_cred(), + .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 | + KEYRING_SEARCH_SKIP_EXPIRED), + }; + struct key *key; + key_ref_t key_ref; + + kenter("%s,%s", type->name, description); + + /* search all the process keyrings for a key */ + key_ref = search_process_keyrings_rcu(&ctx); + if (IS_ERR(key_ref)) { + key = ERR_CAST(key_ref); + if (PTR_ERR(key_ref) == -EAGAIN) + key = ERR_PTR(-ENOKEY); + } else { + key = key_ref_to_ptr(key_ref); + } + + kleave(" = %p", key); + return key; +} +EXPORT_SYMBOL(request_key_rcu); |