1
0
Fork 0

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>
alistair/sunxi64-5.4-dsi
David Howells 2019-06-19 16:10:15 +01:00
parent e59428f721
commit 896f1950e5
4 changed files with 66 additions and 0 deletions

View File

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

View File

@ -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
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.

View File

@ -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,

View File

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