diff options
Diffstat (limited to 'security/keys/request_key.c')
-rw-r--r-- | security/keys/request_key.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index b4b3677657d6..f289982cb5db 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -22,6 +22,31 @@ #define key_negative_timeout 60 /* default timeout on a negative key's existence */ +static struct key *check_cached_key(struct keyring_search_context *ctx) +{ +#ifdef CONFIG_KEYS_REQUEST_CACHE + struct key *key = current->cached_requested_key; + + if (key && + ctx->match_data.cmp(key, &ctx->match_data) && + !(key->flags & ((1 << KEY_FLAG_INVALIDATED) | + (1 << KEY_FLAG_REVOKED)))) + return key_get(key); +#endif + return NULL; +} + +static void cache_requested_key(struct key *key) +{ +#ifdef CONFIG_KEYS_REQUEST_CACHE + struct task_struct *t = current; + + key_put(t->cached_requested_key); + t->cached_requested_key = key_get(key); + set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); +#endif +} + /** * complete_request_key - Complete the construction of a key. * @authkey: The authorisation key. @@ -562,6 +587,10 @@ struct key *request_key_and_link(struct key_type *type, } } + key = check_cached_key(&ctx); + if (key) + return key; + /* search all the process keyrings for a key */ rcu_read_lock(); key_ref = search_process_keyrings_rcu(&ctx); @@ -587,6 +616,9 @@ struct key *request_key_and_link(struct key_type *type, goto error_free; } } + + /* Only cache the key on immediate success */ + cache_requested_key(key); } else if (PTR_ERR(key_ref) != -EAGAIN) { key = ERR_CAST(key_ref); } else { @@ -786,6 +818,10 @@ struct key *request_key_rcu(struct key_type *type, const char *description) kenter("%s,%s", type->name, description); + key = check_cached_key(&ctx); + if (key) + return key; + /* search all the process keyrings for a key */ key_ref = search_process_keyrings_rcu(&ctx); if (IS_ERR(key_ref)) { @@ -794,6 +830,7 @@ struct key *request_key_rcu(struct key_type *type, const char *description) key = ERR_PTR(-ENOKEY); } else { key = key_ref_to_ptr(key_ref); + cache_requested_key(key); } kleave(" = %p", key); |