| From 1e0bec9bab80af86e9ebb15f1dec3dd163295265 Mon Sep 17 00:00:00 2001 |
| From: Herbert Xu <herbert@gondor.apana.org.au> |
| Date: Sat, 7 Dec 2019 22:15:15 +0800 |
| Subject: [PATCH] crypto: api - Fix race condition in crypto_spawn_alg |
| |
| commit 73669cc556462f4e50376538d77ee312142e8a8a upstream. |
| |
| The function crypto_spawn_alg is racy because it drops the lock |
| before shooting the dying algorithm. The algorithm could disappear |
| altogether before we shoot it. |
| |
| This patch fixes it by moving the shooting into the locked section. |
| |
| Fixes: 6bfd48096ff8 ("[CRYPTO] api: Added spawns") |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/crypto/algapi.c b/crypto/algapi.c |
| index a34baf66cff6..07ba983bf9c7 100644 |
| --- a/crypto/algapi.c |
| +++ b/crypto/algapi.c |
| @@ -711,22 +711,16 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn); |
| static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn) |
| { |
| struct crypto_alg *alg; |
| - struct crypto_alg *alg2; |
| |
| down_read(&crypto_alg_sem); |
| alg = spawn->alg; |
| - alg2 = alg; |
| - if (alg2) |
| - alg2 = crypto_mod_get(alg2); |
| - up_read(&crypto_alg_sem); |
| - |
| - if (!alg2) { |
| - if (alg) |
| - crypto_shoot_alg(alg); |
| - return ERR_PTR(-EAGAIN); |
| + if (alg && !crypto_mod_get(alg)) { |
| + alg->cra_flags |= CRYPTO_ALG_DYING; |
| + alg = NULL; |
| } |
| + up_read(&crypto_alg_sem); |
| |
| - return alg; |
| + return alg ?: ERR_PTR(-EAGAIN); |
| } |
| |
| struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, |
| diff --git a/crypto/api.c b/crypto/api.c |
| index 9f99d0e70384..eda0c56b8615 100644 |
| --- a/crypto/api.c |
| +++ b/crypto/api.c |
| @@ -346,13 +346,12 @@ static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask) |
| return len; |
| } |
| |
| -void crypto_shoot_alg(struct crypto_alg *alg) |
| +static void crypto_shoot_alg(struct crypto_alg *alg) |
| { |
| down_write(&crypto_alg_sem); |
| alg->cra_flags |= CRYPTO_ALG_DYING; |
| up_write(&crypto_alg_sem); |
| } |
| -EXPORT_SYMBOL_GPL(crypto_shoot_alg); |
| |
| struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, |
| u32 mask) |
| diff --git a/crypto/internal.h b/crypto/internal.h |
| index 93df7bec844a..e506a57e2243 100644 |
| --- a/crypto/internal.h |
| +++ b/crypto/internal.h |
| @@ -68,7 +68,6 @@ void crypto_alg_tested(const char *name, int err); |
| void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list, |
| struct crypto_alg *nalg); |
| void crypto_remove_final(struct list_head *list); |
| -void crypto_shoot_alg(struct crypto_alg *alg); |
| struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, |
| u32 mask); |
| void *crypto_create_tfm(struct crypto_alg *alg, |
| -- |
| 2.7.4 |
| |