aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-04-08 07:31:36 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2007-05-02 00:38:32 -0400
commita73e69965fa2647faa36caf40f4132b9c99d61fd (patch)
tree8c138eaeb2daeb58d5634961607d37d258729349 /crypto
parentcf02f5da9437201d57d93f529839dd40aac8b5f9 (diff)
[CRYPTO] api: Do not remove users unless new algorithm matches
As it is whenever a new algorithm with the same name is registered users of the old algorithm will be removed so that they can take advantage of the new algorithm. This presents a problem when the new algorithm is not equivalent to the old algorithm. In particular, the new algorithm might only function on top of the existing one. Hence we should not remove users unless they can make use of the new algorithm. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/algapi.c65
1 files changed, 39 insertions, 26 deletions
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 1c2185b5b005..f137a432061f 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -84,36 +84,47 @@ static void crypto_destroy_instance(struct crypto_alg *alg)
84 crypto_tmpl_put(tmpl); 84 crypto_tmpl_put(tmpl);
85} 85}
86 86
87static void crypto_remove_spawns(struct list_head *spawns, 87static void crypto_remove_spawn(struct crypto_spawn *spawn,
88 struct list_head *list) 88 struct list_head *list,
89 struct list_head *secondary_spawns)
89{ 90{
90 struct crypto_spawn *spawn, *n; 91 struct crypto_instance *inst = spawn->inst;
92 struct crypto_template *tmpl = inst->tmpl;
91 93
92 list_for_each_entry_safe(spawn, n, spawns, list) { 94 list_del_init(&spawn->list);
93 struct crypto_instance *inst = spawn->inst; 95 spawn->alg = NULL;
94 struct crypto_template *tmpl = inst->tmpl;
95 96
96 list_del_init(&spawn->list); 97 if (crypto_is_dead(&inst->alg))
97 spawn->alg = NULL; 98 return;
98 99
99 if (crypto_is_dead(&inst->alg)) 100 inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
100 continue; 101 if (!tmpl || !crypto_tmpl_get(tmpl))
102 return;
103
104 crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
105 list_move(&inst->alg.cra_list, list);
106 hlist_del(&inst->list);
107 inst->alg.cra_destroy = crypto_destroy_instance;
108
109 list_splice(&inst->alg.cra_users, secondary_spawns);
110}
111
112static void crypto_remove_spawns(struct list_head *spawns,
113 struct list_head *list, u32 new_type)
114{
115 struct crypto_spawn *spawn, *n;
116 LIST_HEAD(secondary_spawns);
101 117
102 inst->alg.cra_flags |= CRYPTO_ALG_DEAD; 118 list_for_each_entry_safe(spawn, n, spawns, list) {
103 if (!tmpl || !crypto_tmpl_get(tmpl)) 119 if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
104 continue; 120 continue;
105 121
106 crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); 122 crypto_remove_spawn(spawn, list, &secondary_spawns);
107 list_move(&inst->alg.cra_list, list); 123 }
108 hlist_del(&inst->list);
109 inst->alg.cra_destroy = crypto_destroy_instance;
110 124
111 if (!list_empty(&inst->alg.cra_users)) { 125 while (!list_empty(&secondary_spawns)) {
112 if (&n->list == spawns) 126 list_for_each_entry_safe(spawn, n, &secondary_spawns, list)
113 n = list_entry(inst->alg.cra_users.next, 127 crypto_remove_spawn(spawn, list, &secondary_spawns);
114 typeof(*n), list);
115 __list_splice(&inst->alg.cra_users, spawns->prev);
116 }
117 } 128 }
118} 129}
119 130
@@ -164,7 +175,7 @@ static int __crypto_register_alg(struct crypto_alg *alg,
164 q->cra_priority > alg->cra_priority) 175 q->cra_priority > alg->cra_priority)
165 continue; 176 continue;
166 177
167 crypto_remove_spawns(&q->cra_users, list); 178 crypto_remove_spawns(&q->cra_users, list, alg->cra_flags);
168 } 179 }
169 180
170 list_add(&alg->cra_list, &crypto_alg_list); 181 list_add(&alg->cra_list, &crypto_alg_list);
@@ -214,7 +225,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
214 225
215 crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); 226 crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
216 list_del_init(&alg->cra_list); 227 list_del_init(&alg->cra_list);
217 crypto_remove_spawns(&alg->cra_users, list); 228 crypto_remove_spawns(&alg->cra_users, list, alg->cra_flags);
218 229
219 return 0; 230 return 0;
220} 231}
@@ -351,11 +362,12 @@ err:
351EXPORT_SYMBOL_GPL(crypto_register_instance); 362EXPORT_SYMBOL_GPL(crypto_register_instance);
352 363
353int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, 364int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
354 struct crypto_instance *inst) 365 struct crypto_instance *inst, u32 mask)
355{ 366{
356 int err = -EAGAIN; 367 int err = -EAGAIN;
357 368
358 spawn->inst = inst; 369 spawn->inst = inst;
370 spawn->mask = mask;
359 371
360 down_write(&crypto_alg_sem); 372 down_write(&crypto_alg_sem);
361 if (!crypto_is_moribund(alg)) { 373 if (!crypto_is_moribund(alg)) {
@@ -494,7 +506,8 @@ struct crypto_instance *crypto_alloc_instance(const char *name,
494 goto err_free_inst; 506 goto err_free_inst;
495 507
496 spawn = crypto_instance_ctx(inst); 508 spawn = crypto_instance_ctx(inst);
497 err = crypto_init_spawn(spawn, alg, inst); 509 err = crypto_init_spawn(spawn, alg, inst,
510 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
498 511
499 if (err) 512 if (err)
500 goto err_free_inst; 513 goto err_free_inst;