diff options
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 01bbc6d9d19b..fdd5ca6d89fc 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* key.c: basic authentication token and access key management | 1 | /* Basic authentication token and access key management |
2 | * | 2 | * |
3 | * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -34,7 +34,7 @@ static void key_cleanup(struct work_struct *work); | |||
34 | static DECLARE_WORK(key_cleanup_task, key_cleanup); | 34 | static DECLARE_WORK(key_cleanup_task, key_cleanup); |
35 | 35 | ||
36 | /* we serialise key instantiation and link */ | 36 | /* we serialise key instantiation and link */ |
37 | DECLARE_RWSEM(key_construction_sem); | 37 | DEFINE_MUTEX(key_construction_mutex); |
38 | 38 | ||
39 | /* any key who's type gets unegistered will be re-typed to this */ | 39 | /* any key who's type gets unegistered will be re-typed to this */ |
40 | static struct key_type key_type_dead = { | 40 | static struct key_type key_type_dead = { |
@@ -104,7 +104,7 @@ struct key_user *key_user_lookup(uid_t uid) | |||
104 | candidate->qnkeys = 0; | 104 | candidate->qnkeys = 0; |
105 | candidate->qnbytes = 0; | 105 | candidate->qnbytes = 0; |
106 | spin_lock_init(&candidate->lock); | 106 | spin_lock_init(&candidate->lock); |
107 | INIT_LIST_HEAD(&candidate->consq); | 107 | mutex_init(&candidate->cons_lock); |
108 | 108 | ||
109 | rb_link_node(&candidate->node, parent, p); | 109 | rb_link_node(&candidate->node, parent, p); |
110 | rb_insert_color(&candidate->node, &key_user_tree); | 110 | rb_insert_color(&candidate->node, &key_user_tree); |
@@ -418,7 +418,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
418 | awaken = 0; | 418 | awaken = 0; |
419 | ret = -EBUSY; | 419 | ret = -EBUSY; |
420 | 420 | ||
421 | down_write(&key_construction_sem); | 421 | mutex_lock(&key_construction_mutex); |
422 | 422 | ||
423 | /* can't instantiate twice */ | 423 | /* can't instantiate twice */ |
424 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 424 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
@@ -443,11 +443,11 @@ static int __key_instantiate_and_link(struct key *key, | |||
443 | } | 443 | } |
444 | } | 444 | } |
445 | 445 | ||
446 | up_write(&key_construction_sem); | 446 | mutex_unlock(&key_construction_mutex); |
447 | 447 | ||
448 | /* wake up anyone waiting for a key to be constructed */ | 448 | /* wake up anyone waiting for a key to be constructed */ |
449 | if (awaken) | 449 | if (awaken) |
450 | wake_up_all(&request_key_conswq); | 450 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); |
451 | 451 | ||
452 | return ret; | 452 | return ret; |
453 | 453 | ||
@@ -500,7 +500,7 @@ int key_negate_and_link(struct key *key, | |||
500 | if (keyring) | 500 | if (keyring) |
501 | down_write(&keyring->sem); | 501 | down_write(&keyring->sem); |
502 | 502 | ||
503 | down_write(&key_construction_sem); | 503 | mutex_lock(&key_construction_mutex); |
504 | 504 | ||
505 | /* can't instantiate twice */ | 505 | /* can't instantiate twice */ |
506 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 506 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
@@ -525,14 +525,14 @@ int key_negate_and_link(struct key *key, | |||
525 | key_revoke(instkey); | 525 | key_revoke(instkey); |
526 | } | 526 | } |
527 | 527 | ||
528 | up_write(&key_construction_sem); | 528 | mutex_unlock(&key_construction_mutex); |
529 | 529 | ||
530 | if (keyring) | 530 | if (keyring) |
531 | up_write(&keyring->sem); | 531 | up_write(&keyring->sem); |
532 | 532 | ||
533 | /* wake up anyone waiting for a key to be constructed */ | 533 | /* wake up anyone waiting for a key to be constructed */ |
534 | if (awaken) | 534 | if (awaken) |
535 | wake_up_all(&request_key_conswq); | 535 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); |
536 | 536 | ||
537 | return ret; | 537 | return ret; |
538 | 538 | ||
@@ -899,12 +899,14 @@ void key_revoke(struct key *key) | |||
899 | { | 899 | { |
900 | key_check(key); | 900 | key_check(key); |
901 | 901 | ||
902 | /* make sure no one's trying to change or use the key when we mark | 902 | /* make sure no one's trying to change or use the key when we mark it |
903 | * it */ | 903 | * - we tell lockdep that we might nest because we might be revoking an |
904 | down_write(&key->sem); | 904 | * authorisation key whilst holding the sem on a key we've just |
905 | set_bit(KEY_FLAG_REVOKED, &key->flags); | 905 | * instantiated |
906 | 906 | */ | |
907 | if (key->type->revoke) | 907 | down_write_nested(&key->sem, 1); |
908 | if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) && | ||
909 | key->type->revoke) | ||
908 | key->type->revoke(key); | 910 | key->type->revoke(key); |
909 | 911 | ||
910 | up_write(&key->sem); | 912 | up_write(&key->sem); |