Skip to content

Commit

Permalink
KEYS: Do preallocation for __key_link()
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: James Morris <[email protected]>
  • Loading branch information
dhowells authored and James Morris committed May 6, 2010
1 parent 043b4d4 commit f70e2e0
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 130 deletions.
11 changes: 10 additions & 1 deletion security/keys/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,16 @@ extern wait_queue_head_t request_key_conswq;
extern struct key_type *key_type_lookup(const char *type);
extern void key_type_put(struct key_type *ktype);

extern int __key_link(struct key *keyring, struct key *key);
extern int __key_link_begin(struct key *keyring,
const struct key_type *type,
const char *description,
struct keyring_list **_prealloc);
extern int __key_link_check_live_key(struct key *keyring, struct key *key);
extern void __key_link(struct key *keyring, struct key *key,
struct keyring_list **_prealloc);
extern void __key_link_end(struct key *keyring,
struct key_type *type,
struct keyring_list *prealloc);

extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
const struct key_type *type,
Expand Down
45 changes: 29 additions & 16 deletions security/keys/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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);

Expand All @@ -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)
Expand All @@ -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() */

Expand Down Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand All @@ -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);
Expand Down
Loading

0 comments on commit f70e2e0

Please sign in to comment.