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>
This commit is contained in:
committed by
James Morris
parent
043b4d40f5
commit
f70e2e0619
@ -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);
|
||||
|
Reference in New Issue
Block a user