diff options
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index 9a6108aefae9..764f4c57913e 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -281,11 +281,12 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL); if (!key->index_key.description) goto no_memory_3; + key->index_key.type = type; + key_set_index_key(&key->index_key); refcount_set(&key->usage, 1); init_rwsem(&key->sem); lockdep_set_class(&key->sem, &type->lock_class); - key->index_key.type = type; key->user = user; key->quotalen = quotalen; key->datalen = type->def_datalen; @@ -312,6 +313,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, goto security_error; /* publish the key by giving it a serial number */ + refcount_inc(&key->domain_tag->usage); atomic_inc(&user->nkeys); key_alloc_serial(key); @@ -455,7 +457,7 @@ static int __key_instantiate_and_link(struct key *key, /* disable the authorisation key */ if (authkey) - key_revoke(authkey); + key_invalidate(authkey); if (prep->expiry != TIME64_MAX) { key->expiry = prep->expiry; @@ -496,7 +498,7 @@ int key_instantiate_and_link(struct key *key, struct key *authkey) { struct key_preparsed_payload prep; - struct assoc_array_edit *edit; + struct assoc_array_edit *edit = NULL; int ret; memset(&prep, 0, sizeof(prep)); @@ -511,10 +513,14 @@ int key_instantiate_and_link(struct key *key, } if (keyring) { - ret = __key_link_begin(keyring, &key->index_key, &edit); + ret = __key_link_lock(keyring, &key->index_key); if (ret < 0) goto error; + ret = __key_link_begin(keyring, &key->index_key, &edit); + if (ret < 0) + goto error_link_end; + if (keyring->restrict_link && keyring->restrict_link->check) { struct key_restriction *keyres = keyring->restrict_link; @@ -566,7 +572,7 @@ int key_reject_and_link(struct key *key, struct key *keyring, struct key *authkey) { - struct assoc_array_edit *edit; + struct assoc_array_edit *edit = NULL; int ret, awaken, link_ret = 0; key_check(key); @@ -579,7 +585,12 @@ int key_reject_and_link(struct key *key, if (keyring->restrict_link) return -EPERM; - link_ret = __key_link_begin(keyring, &key->index_key, &edit); + link_ret = __key_link_lock(keyring, &key->index_key); + if (link_ret == 0) { + link_ret = __key_link_begin(keyring, &key->index_key, &edit); + if (link_ret < 0) + __key_link_end(keyring, &key->index_key, edit); + } } mutex_lock(&key_construction_mutex); @@ -603,7 +614,7 @@ int key_reject_and_link(struct key *key, /* disable the authorisation key */ if (authkey) - key_revoke(authkey); + key_invalidate(authkey); } mutex_unlock(&key_construction_mutex); @@ -806,7 +817,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, .description = description, }; struct key_preparsed_payload prep; - struct assoc_array_edit *edit; + struct assoc_array_edit *edit = NULL; const struct cred *cred = current_cred(); struct key *keyring, *key = NULL; key_ref_t key_ref; @@ -855,13 +866,20 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, goto error_free_prep; } index_key.desc_len = strlen(index_key.description); + key_set_index_key(&index_key); - ret = __key_link_begin(keyring, &index_key, &edit); + ret = __key_link_lock(keyring, &index_key); if (ret < 0) { key_ref = ERR_PTR(ret); goto error_free_prep; } + ret = __key_link_begin(keyring, &index_key, &edit); + if (ret < 0) { + key_ref = ERR_PTR(ret); + goto error_link_end; + } + if (restrict_link && restrict_link->check) { ret = restrict_link->check(keyring, index_key.type, &prep.payload, restrict_link->key); |