Skip to content

Commit

Permalink
[CRYPTO] api: Do not remove users unless new algorithm matches
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
herbertx committed May 2, 2007
1 parent cf02f5d commit a73e699
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 27 deletions.
65 changes: 39 additions & 26 deletions crypto/algapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,36 +84,47 @@ static void crypto_destroy_instance(struct crypto_alg *alg)
crypto_tmpl_put(tmpl);
}

static void crypto_remove_spawns(struct list_head *spawns,
struct list_head *list)
static void crypto_remove_spawn(struct crypto_spawn *spawn,
struct list_head *list,
struct list_head *secondary_spawns)
{
struct crypto_spawn *spawn, *n;
struct crypto_instance *inst = spawn->inst;
struct crypto_template *tmpl = inst->tmpl;

list_for_each_entry_safe(spawn, n, spawns, list) {
struct crypto_instance *inst = spawn->inst;
struct crypto_template *tmpl = inst->tmpl;
list_del_init(&spawn->list);
spawn->alg = NULL;

list_del_init(&spawn->list);
spawn->alg = NULL;
if (crypto_is_dead(&inst->alg))
return;

if (crypto_is_dead(&inst->alg))
continue;
inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
if (!tmpl || !crypto_tmpl_get(tmpl))
return;

crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
list_move(&inst->alg.cra_list, list);
hlist_del(&inst->list);
inst->alg.cra_destroy = crypto_destroy_instance;

list_splice(&inst->alg.cra_users, secondary_spawns);
}

static void crypto_remove_spawns(struct list_head *spawns,
struct list_head *list, u32 new_type)
{
struct crypto_spawn *spawn, *n;
LIST_HEAD(secondary_spawns);

inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
if (!tmpl || !crypto_tmpl_get(tmpl))
list_for_each_entry_safe(spawn, n, spawns, list) {
if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
continue;

crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
list_move(&inst->alg.cra_list, list);
hlist_del(&inst->list);
inst->alg.cra_destroy = crypto_destroy_instance;
crypto_remove_spawn(spawn, list, &secondary_spawns);
}

if (!list_empty(&inst->alg.cra_users)) {
if (&n->list == spawns)
n = list_entry(inst->alg.cra_users.next,
typeof(*n), list);
__list_splice(&inst->alg.cra_users, spawns->prev);
}
while (!list_empty(&secondary_spawns)) {
list_for_each_entry_safe(spawn, n, &secondary_spawns, list)
crypto_remove_spawn(spawn, list, &secondary_spawns);
}
}

Expand Down Expand Up @@ -164,7 +175,7 @@ static int __crypto_register_alg(struct crypto_alg *alg,
q->cra_priority > alg->cra_priority)
continue;

crypto_remove_spawns(&q->cra_users, list);
crypto_remove_spawns(&q->cra_users, list, alg->cra_flags);
}

list_add(&alg->cra_list, &crypto_alg_list);
Expand Down Expand Up @@ -214,7 +225,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)

crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
list_del_init(&alg->cra_list);
crypto_remove_spawns(&alg->cra_users, list);
crypto_remove_spawns(&alg->cra_users, list, alg->cra_flags);

return 0;
}
Expand Down Expand Up @@ -351,11 +362,12 @@ int crypto_register_instance(struct crypto_template *tmpl,
EXPORT_SYMBOL_GPL(crypto_register_instance);

int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
struct crypto_instance *inst)
struct crypto_instance *inst, u32 mask)
{
int err = -EAGAIN;

spawn->inst = inst;
spawn->mask = mask;

down_write(&crypto_alg_sem);
if (!crypto_is_moribund(alg)) {
Expand Down Expand Up @@ -494,7 +506,8 @@ struct crypto_instance *crypto_alloc_instance(const char *name,
goto err_free_inst;

spawn = crypto_instance_ctx(inst);
err = crypto_init_spawn(spawn, alg, inst);
err = crypto_init_spawn(spawn, alg, inst,
CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);

if (err)
goto err_free_inst;
Expand Down
3 changes: 2 additions & 1 deletion include/crypto/algapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct crypto_spawn {
struct list_head list;
struct crypto_alg *alg;
struct crypto_instance *inst;
u32 mask;
};

struct crypto_queue {
Expand Down Expand Up @@ -103,7 +104,7 @@ void crypto_unregister_template(struct crypto_template *tmpl);
struct crypto_template *crypto_lookup_template(const char *name);

int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
struct crypto_instance *inst);
struct crypto_instance *inst, u32 mask);
void crypto_drop_spawn(struct crypto_spawn *spawn);
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
u32 mask);
Expand Down

0 comments on commit a73e699

Please sign in to comment.