crypto: api - Do not zap spawn->alg
Currently when a spawn is removed we will zap its alg field. This is racy because the spawn could belong to an unregistered instance which may dereference the spawn->alg field. This patch fixes this by keeping spawn->alg constant and instead adding a new spawn->dead field to indicate that a spawn is going away. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Родитель
73669cc556
Коммит
4f87ee118d
|
@ -93,15 +93,17 @@ static struct list_head *crypto_more_spawns(struct crypto_alg *alg,
|
|||
if (!spawn)
|
||||
return NULL;
|
||||
|
||||
n = list_next_entry(spawn, list);
|
||||
|
||||
if (spawn->alg && &n->list != stack && !n->alg)
|
||||
n->alg = (n->list.next == stack) ? alg :
|
||||
&list_next_entry(n, list)->inst->alg;
|
||||
|
||||
n = list_prev_entry(spawn, list);
|
||||
list_move(&spawn->list, secondary_spawns);
|
||||
|
||||
return &n->list == stack ? top : &n->inst->alg.cra_users;
|
||||
if (list_is_last(&n->list, stack))
|
||||
return top;
|
||||
|
||||
n = list_next_entry(n, list);
|
||||
if (!spawn->dead)
|
||||
n->dead = false;
|
||||
|
||||
return &n->inst->alg.cra_users;
|
||||
}
|
||||
|
||||
static void crypto_remove_instance(struct crypto_instance *inst,
|
||||
|
@ -160,7 +162,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
|
|||
if (&inst->alg == nalg)
|
||||
break;
|
||||
|
||||
spawn->alg = NULL;
|
||||
spawn->dead = true;
|
||||
spawns = &inst->alg.cra_users;
|
||||
|
||||
/*
|
||||
|
@ -179,7 +181,7 @@ void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
|
|||
&secondary_spawns)));
|
||||
|
||||
list_for_each_entry_safe(spawn, n, &secondary_spawns, list) {
|
||||
if (spawn->alg)
|
||||
if (!spawn->dead)
|
||||
list_move(&spawn->list, &spawn->alg->cra_users);
|
||||
else
|
||||
crypto_remove_instance(spawn->inst, list);
|
||||
|
@ -670,7 +672,7 @@ EXPORT_SYMBOL_GPL(crypto_grab_spawn);
|
|||
void crypto_drop_spawn(struct crypto_spawn *spawn)
|
||||
{
|
||||
down_write(&crypto_alg_sem);
|
||||
if (spawn->alg)
|
||||
if (!spawn->dead)
|
||||
list_del(&spawn->list);
|
||||
up_write(&crypto_alg_sem);
|
||||
}
|
||||
|
@ -682,7 +684,7 @@ static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
|
|||
|
||||
down_read(&crypto_alg_sem);
|
||||
alg = spawn->alg;
|
||||
if (alg && !crypto_mod_get(alg)) {
|
||||
if (!spawn->dead && !crypto_mod_get(alg)) {
|
||||
alg->cra_flags |= CRYPTO_ALG_DYING;
|
||||
alg = NULL;
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ struct crypto_spawn {
|
|||
struct crypto_instance *inst;
|
||||
const struct crypto_type *frontend;
|
||||
u32 mask;
|
||||
bool dead;
|
||||
};
|
||||
|
||||
struct crypto_queue {
|
||||
|
|
Загрузка…
Ссылка в новой задаче