aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/algapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/algapi.c')
-rw-r--r--crypto/algapi.c42
1 files changed, 19 insertions, 23 deletions
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 83b04e0884b1..2d0a1c64ce39 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -64,6 +64,8 @@ static int crypto_check_alg(struct crypto_alg *alg)
64 if (alg->cra_priority < 0) 64 if (alg->cra_priority < 0)
65 return -EINVAL; 65 return -EINVAL;
66 66
67 atomic_set(&alg->cra_refcnt, 1);
68
67 return crypto_set_driver_name(alg); 69 return crypto_set_driver_name(alg);
68} 70}
69 71
@@ -99,10 +101,9 @@ static struct list_head *crypto_more_spawns(struct crypto_alg *alg,
99 return &n->list == stack ? top : &n->inst->alg.cra_users; 101 return &n->list == stack ? top : &n->inst->alg.cra_users;
100} 102}
101 103
102static void crypto_remove_spawn(struct crypto_spawn *spawn, 104static void crypto_remove_instance(struct crypto_instance *inst,
103 struct list_head *list) 105 struct list_head *list)
104{ 106{
105 struct crypto_instance *inst = spawn->inst;
106 struct crypto_template *tmpl = inst->tmpl; 107 struct crypto_template *tmpl = inst->tmpl;
107 108
108 if (crypto_is_dead(&inst->alg)) 109 if (crypto_is_dead(&inst->alg))
@@ -167,7 +168,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
167 if (spawn->alg) 168 if (spawn->alg)
168 list_move(&spawn->list, &spawn->alg->cra_users); 169 list_move(&spawn->list, &spawn->alg->cra_users);
169 else 170 else
170 crypto_remove_spawn(spawn, list); 171 crypto_remove_instance(spawn->inst, list);
171 } 172 }
172} 173}
173EXPORT_SYMBOL_GPL(crypto_remove_spawns); 174EXPORT_SYMBOL_GPL(crypto_remove_spawns);
@@ -188,7 +189,6 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
188 189
189 ret = -EEXIST; 190 ret = -EEXIST;
190 191
191 atomic_set(&alg->cra_refcnt, 1);
192 list_for_each_entry(q, &crypto_alg_list, cra_list) { 192 list_for_each_entry(q, &crypto_alg_list, cra_list) {
193 if (q == alg) 193 if (q == alg)
194 goto err; 194 goto err;
@@ -523,7 +523,10 @@ int crypto_register_instance(struct crypto_template *tmpl,
523 523
524 err = crypto_check_alg(&inst->alg); 524 err = crypto_check_alg(&inst->alg);
525 if (err) 525 if (err)
526 goto err; 526 return err;
527
528 if (unlikely(!crypto_mod_get(&inst->alg)))
529 return -EAGAIN;
527 530
528 inst->alg.cra_module = tmpl->module; 531 inst->alg.cra_module = tmpl->module;
529 inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE; 532 inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
@@ -545,37 +548,30 @@ unlock:
545 goto err; 548 goto err;
546 549
547 crypto_wait_for_test(larval); 550 crypto_wait_for_test(larval);
551
552 /* Remove instance if test failed */
553 if (!(inst->alg.cra_flags & CRYPTO_ALG_TESTED))
554 crypto_unregister_instance(inst);
548 err = 0; 555 err = 0;
549 556
550err: 557err:
558 crypto_mod_put(&inst->alg);
551 return err; 559 return err;
552} 560}
553EXPORT_SYMBOL_GPL(crypto_register_instance); 561EXPORT_SYMBOL_GPL(crypto_register_instance);
554 562
555int crypto_unregister_instance(struct crypto_alg *alg) 563int crypto_unregister_instance(struct crypto_instance *inst)
556{ 564{
557 int err; 565 LIST_HEAD(list);
558 struct crypto_instance *inst = (void *)alg;
559 struct crypto_template *tmpl = inst->tmpl;
560 LIST_HEAD(users);
561
562 if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
563 return -EINVAL;
564
565 BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
566 566
567 down_write(&crypto_alg_sem); 567 down_write(&crypto_alg_sem);
568 568
569 hlist_del_init(&inst->list); 569 crypto_remove_spawns(&inst->alg, &list, NULL);
570 err = crypto_remove_alg(alg, &users); 570 crypto_remove_instance(inst, &list);
571 571
572 up_write(&crypto_alg_sem); 572 up_write(&crypto_alg_sem);
573 573
574 if (err) 574 crypto_remove_final(&list);
575 return err;
576
577 tmpl->free(inst);
578 crypto_remove_final(&users);
579 575
580 return 0; 576 return 0;
581} 577}