diff options
author | David Howells <dhowells@redhat.com> | 2007-10-16 23:29:46 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-17 08:42:57 -0700 |
commit | 76181c134f87479fa13bf2548ddf2999055d34d4 (patch) | |
tree | 34694341c190e7ecdd3111ee48e4b98602ff012f /security/keys/key.c | |
parent | 398c95bdf2c24d7866692a40ba04425aef238cdd (diff) | |
download | kernel-crypto-76181c134f87479fa13bf2548ddf2999055d34d4.tar.gz kernel-crypto-76181c134f87479fa13bf2548ddf2999055d34d4.tar.xz kernel-crypto-76181c134f87479fa13bf2548ddf2999055d34d4.zip |
KEYS: Make request_key() and co fundamentally asynchronous
Make request_key() and co fundamentally asynchronous to make it easier for
NFS to make use of them. There are now accessor functions that do
asynchronous constructions, a wait function to wait for construction to
complete, and a completion function for the key type to indicate completion
of construction.
Note that the construction queue is now gone. Instead, keys under
construction are linked in to the appropriate keyring in advance, and that
anyone encountering one must wait for it to be complete before they can use
it. This is done automatically for userspace.
The following auxiliary changes are also made:
(1) Key type implementation stuff is split from linux/key.h into
linux/key-type.h.
(2) AF_RXRPC provides a way to allocate null rxrpc-type keys so that AFS does
not need to call key_instantiate_and_link() directly.
(3) Adjust the debugging macros so that they're -Wformat checked even if
they are disabled, and make it so they can be enabled simply by defining
__KDEBUG to be consistent with other code of mine.
(3) Documentation.
[alan@lxorguk.ukuu.org.uk: keys: missing word in documentation]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index 01bbc6d9d19..fdd5ca6d89f 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -1,6 +1,6 @@ -/* key.c: basic authentication token and access key management +/* Basic authentication token and access key management * - * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -34,7 +34,7 @@ static void key_cleanup(struct work_struct *work); static DECLARE_WORK(key_cleanup_task, key_cleanup); /* we serialise key instantiation and link */ -DECLARE_RWSEM(key_construction_sem); +DEFINE_MUTEX(key_construction_mutex); /* any key who's type gets unegistered will be re-typed to this */ static struct key_type key_type_dead = { @@ -104,7 +104,7 @@ struct key_user *key_user_lookup(uid_t uid) candidate->qnkeys = 0; candidate->qnbytes = 0; spin_lock_init(&candidate->lock); - INIT_LIST_HEAD(&candidate->consq); + mutex_init(&candidate->cons_lock); rb_link_node(&candidate->node, parent, p); rb_insert_color(&candidate->node, &key_user_tree); @@ -418,7 +418,7 @@ static int __key_instantiate_and_link(struct key *key, awaken = 0; ret = -EBUSY; - down_write(&key_construction_sem); + mutex_lock(&key_construction_mutex); /* can't instantiate twice */ if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { @@ -443,11 +443,11 @@ static int __key_instantiate_and_link(struct key *key, } } - up_write(&key_construction_sem); + mutex_unlock(&key_construction_mutex); /* wake up anyone waiting for a key to be constructed */ if (awaken) - wake_up_all(&request_key_conswq); + wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); return ret; @@ -500,7 +500,7 @@ int key_negate_and_link(struct key *key, if (keyring) down_write(&keyring->sem); - down_write(&key_construction_sem); + mutex_lock(&key_construction_mutex); /* can't instantiate twice */ if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { @@ -525,14 +525,14 @@ int key_negate_and_link(struct key *key, key_revoke(instkey); } - up_write(&key_construction_sem); + mutex_unlock(&key_construction_mutex); if (keyring) up_write(&keyring->sem); /* wake up anyone waiting for a key to be constructed */ if (awaken) - wake_up_all(&request_key_conswq); + wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); return ret; @@ -899,12 +899,14 @@ void key_revoke(struct key *key) { key_check(key); - /* make sure no one's trying to change or use the key when we mark - * it */ - down_write(&key->sem); - set_bit(KEY_FLAG_REVOKED, &key->flags); - - if (key->type->revoke) + /* make sure no one's trying to change or use the key when we mark it + * - we tell lockdep that we might nest because we might be revoking an + * authorisation key whilst holding the sem on a key we've just + * instantiated + */ + down_write_nested(&key->sem, 1); + if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) && + key->type->revoke) key->type->revoke(key); up_write(&key->sem); |