X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=security%2Fkeys%2Fkey.c;h=654d23baf3525ceee6134f75039a4d450fc1edd9;hb=6585b4a71f523485ecf33e7f4569be4095d63699;hp=700400d801dcc1e5360427bfc07c9c722a256c46;hpb=edacf6bb7e7e1b75f2937966a50119439ff78ccb;p=linux-2.6 diff --git a/security/keys/key.c b/security/keys/key.c index 700400d801..654d23baf3 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; @@ -820,7 +820,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key = key_alloc(ktype, description, current->fsuid, current->fsgid, current, perm, flags); if (IS_ERR(key)) { - key_ref = ERR_PTR(PTR_ERR(key)); + key_ref = ERR_CAST(key); goto error_3; } @@ -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); @@ -1001,7 +1003,7 @@ void __init key_init(void) { /* allocate a slab in which we can store keys */ key_jar = kmem_cache_create("key_jar", sizeof(struct key), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); /* add the special key types */ list_add_tail(&key_type_keyring.link, &key_types_list);