Commit 896f1950 authored by David Howells's avatar David Howells

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: default avatarDavid Howells <dhowells@redhat.com>
parent e59428f7
...@@ -1147,6 +1147,16 @@ payload contents" for more information. ...@@ -1147,6 +1147,16 @@ payload contents" for more information.
case error ERESTARTSYS will be returned. case error ERESTARTSYS will be returned.
* To search for a key under RCU conditions, call::
struct key *request_key_rcu(const struct key_type *type,
const char *description);
which is similar to request_key() except that it does not check for keys
that are under construction and it will not call out to userspace to
construct a key if it can't find a match.
* When it is no longer required, the key should be released using:: * When it is no longer required, the key should be released using::
void key_put(struct key *key); void key_put(struct key *key);
......
...@@ -36,6 +36,11 @@ or:: ...@@ -36,6 +36,11 @@ or::
size_t callout_len, size_t callout_len,
void *aux); void *aux);
or::
struct key *request_key_rcu(const struct key_type *type,
const char *description);
Or by userspace invoking the request_key system call:: Or by userspace invoking the request_key system call::
key_serial_t request_key(const char *type, key_serial_t request_key(const char *type,
...@@ -57,6 +62,10 @@ The two async in-kernel calls may return keys that are still in the process of ...@@ -57,6 +62,10 @@ The two async in-kernel calls may return keys that are still in the process of
being constructed. The two non-async ones will wait for construction to being constructed. The two non-async ones will wait for construction to
complete first. complete first.
The request_key_rcu() call is like the in-kernel request_key() call, except
that it doesn't check for keys that are under construction and doesn't attempt
to construct missing keys.
The userspace interface links the key to a keyring associated with the process The userspace interface links the key to a keyring associated with the process
to prevent the key from going away, and returns the serial number of the key to to prevent the key from going away, and returns the serial number of the key to
the caller. the caller.
......
...@@ -274,6 +274,9 @@ extern struct key *request_key(struct key_type *type, ...@@ -274,6 +274,9 @@ extern struct key *request_key(struct key_type *type,
const char *description, const char *description,
const char *callout_info); const char *callout_info);
extern struct key *request_key_rcu(struct key_type *type,
const char *description);
extern struct key *request_key_with_auxdata(struct key_type *type, extern struct key *request_key_with_auxdata(struct key_type *type,
const char *description, const char *description,
const void *callout_info, const void *callout_info,
......
...@@ -756,3 +756,47 @@ struct key *request_key_async_with_auxdata(struct key_type *type, ...@@ -756,3 +756,47 @@ struct key *request_key_async_with_auxdata(struct key_type *type,
callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA); callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA);
} }
EXPORT_SYMBOL(request_key_async_with_auxdata); 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);
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