diff options
author | David Howells <dhowells@redhat.com> | 2010-04-30 14:32:39 +0100 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-05-06 22:25:02 +1000 |
commit | f70e2e06196ad4c1c762037da2f75354f6c16b81 (patch) | |
tree | 9632a1e655efb684c87f8c7be6d091fbb1a430e7 /security/keys/key.c | |
parent | 043b4d40f53131c5f72eca2a46555fe35328a930 (diff) |
KEYS: Do preallocation for __key_link()
Do preallocation for __key_link() so that the various callers in request_key.c
can deal with any errors from this source before attempting to construct a key.
This allows them to assume that the actual linkage step is guaranteed to be
successful.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index c70da6fb82ce..c1eac8084ade 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -398,7 +398,8 @@ static int __key_instantiate_and_link(struct key *key, const void *data, size_t datalen, struct key *keyring, - struct key *authkey) + struct key *authkey, + struct keyring_list **_prealloc) { int ret, awaken; @@ -425,7 +426,7 @@ static int __key_instantiate_and_link(struct key *key, /* and link it into the destination keyring */ if (keyring) - ret = __key_link(keyring, key); + __key_link(keyring, key, _prealloc); /* disable the authorisation key */ if (authkey) @@ -453,15 +454,21 @@ int key_instantiate_and_link(struct key *key, struct key *keyring, struct key *authkey) { + struct keyring_list *prealloc; int ret; - if (keyring) - down_write(&keyring->sem); + if (keyring) { + ret = __key_link_begin(keyring, key->type, key->description, + &prealloc); + if (ret < 0) + return ret; + } - ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey); + ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, + &prealloc); if (keyring) - up_write(&keyring->sem); + __key_link_end(keyring, key->type, prealloc); return ret; @@ -478,8 +485,9 @@ int key_negate_and_link(struct key *key, struct key *keyring, struct key *authkey) { + struct keyring_list *prealloc; struct timespec now; - int ret, awaken; + int ret, awaken, link_ret = 0; key_check(key); key_check(keyring); @@ -488,7 +496,8 @@ int key_negate_and_link(struct key *key, ret = -EBUSY; if (keyring) - down_write(&keyring->sem); + link_ret = __key_link_begin(keyring, key->type, + key->description, &prealloc); mutex_lock(&key_construction_mutex); @@ -508,8 +517,8 @@ int key_negate_and_link(struct key *key, ret = 0; /* and link it into the destination keyring */ - if (keyring) - ret = __key_link(keyring, key); + if (keyring && link_ret == 0) + __key_link(keyring, key, &prealloc); /* disable the authorisation key */ if (authkey) @@ -519,13 +528,13 @@ int key_negate_and_link(struct key *key, mutex_unlock(&key_construction_mutex); if (keyring) - up_write(&keyring->sem); + __key_link_end(keyring, key->type, prealloc); /* wake up anyone waiting for a key to be constructed */ if (awaken) wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); - return ret; + return ret == 0 ? link_ret : ret; } /* end key_negate_and_link() */ @@ -749,6 +758,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_perm_t perm, unsigned long flags) { + struct keyring_list *prealloc; const struct cred *cred = current_cred(); struct key_type *ktype; struct key *keyring, *key = NULL; @@ -775,7 +785,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, if (keyring->type != &key_type_keyring) goto error_2; - down_write(&keyring->sem); + ret = __key_link_begin(keyring, ktype, description, &prealloc); + if (ret < 0) + goto error_2; /* if we're going to allocate a new key, we're going to have * to modify the keyring */ @@ -817,7 +829,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, } /* instantiate it and link it into the target keyring */ - ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); + ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, + &prealloc); if (ret < 0) { key_put(key); key_ref = ERR_PTR(ret); @@ -827,7 +840,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); error_3: - up_write(&keyring->sem); + __key_link_end(keyring, ktype, prealloc); error_2: key_type_put(ktype); error: @@ -837,7 +850,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* we found a matching key, so we're going to try to update it * - we can drop the locks first as we have the key pinned */ - up_write(&keyring->sem); + __key_link_end(keyring, ktype, prealloc); key_type_put(ktype); key_ref = __key_update(key_ref, payload, plen); |