diff --git a/crypto/algapi.c b/crypto/algapi.c index 7c41e7405c41a4392791cc4a01a22cce52f983b0..56c62e2858d56a9eee11b9167fe8362a71a7c6c1 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -149,6 +149,9 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg) if (q == alg) goto err; + if (crypto_is_moribund(q)) + continue; + if (crypto_is_larval(q)) { if (!strcmp(alg->cra_driver_name, q->cra_driver_name)) goto err; @@ -197,7 +200,7 @@ void crypto_alg_tested(const char *name, int err) down_write(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!crypto_is_larval(q)) + if (crypto_is_moribund(q) || !crypto_is_larval(q)) continue; test = (struct crypto_larval *)q; @@ -210,6 +213,7 @@ void crypto_alg_tested(const char *name, int err) goto unlock; found: + q->cra_flags |= CRYPTO_ALG_DEAD; alg = test->adult; if (err || list_empty(&alg->cra_list)) goto complete; diff --git a/crypto/api.c b/crypto/api.c index 9975a7bd246c21d4d7e3152249ffefdb38812ee5..efe77df6863f4378f4f0da414591f940870b76ea 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -557,34 +557,34 @@ err: return ERR_PTR(err); } EXPORT_SYMBOL_GPL(crypto_alloc_tfm); - + /* - * crypto_free_tfm - Free crypto transform + * crypto_destroy_tfm - Free crypto transform + * @mem: Start of tfm slab * @tfm: Transform to free * - * crypto_free_tfm() frees up the transform and any associated resources, + * This function frees up the transform and any associated resources, * then drops the refcount on the associated algorithm. */ -void crypto_free_tfm(struct crypto_tfm *tfm) +void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm) { struct crypto_alg *alg; int size; - if (unlikely(!tfm)) + if (unlikely(!mem)) return; alg = tfm->__crt_alg; - size = sizeof(*tfm) + alg->cra_ctxsize; + size = ksize(mem); if (!tfm->exit && alg->cra_exit) alg->cra_exit(tfm); crypto_exit_ops(tfm); crypto_mod_put(alg); - memset(tfm, 0, size); - kfree(tfm); + memset(mem, 0, size); + kfree(mem); } - -EXPORT_SYMBOL_GPL(crypto_free_tfm); +EXPORT_SYMBOL_GPL(crypto_destroy_tfm); int crypto_has_alg(const char *name, u32 type, u32 mask) { diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index 9aeeb52004a5399d0a9b7a3484044b5de1e3083c..3de89a424401c1918818145a3d27df627c99f7ef 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -54,7 +54,8 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out, struct page *page; page = sg_page(walk->sg) + ((walk->offset - 1) >> PAGE_SHIFT); - flush_dcache_page(page); + if (!PageSlab(page)) + flush_dcache_page(page); } if (more) { diff --git a/crypto/shash.c b/crypto/shash.c index c9df367332ffd1f122b1d675bcb434b936848bc4..d5a2b619c55f79e3b7cbff1f1d06d3048364b49c 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -388,10 +388,15 @@ static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm) struct shash_desc *desc = crypto_tfm_ctx(tfm); struct crypto_shash *shash; + if (!crypto_mod_get(calg)) + return -EAGAIN; + shash = __crypto_shash_cast(crypto_create_tfm( calg, &crypto_shash_type)); - if (IS_ERR(shash)) + if (IS_ERR(shash)) { + crypto_mod_put(calg); return PTR_ERR(shash); + } desc->tfm = shash; tfm->exit = crypto_exit_shash_ops_compat; diff --git a/include/crypto/hash.h b/include/crypto/hash.h index cd16d6e668ce78a523a7865f747d5078ad0ecd76..d797e119e3d5e9677a60457670ed097982916691 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -222,7 +222,7 @@ static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm) static inline void crypto_free_shash(struct crypto_shash *tfm) { - crypto_free_tfm(crypto_shash_tfm(tfm)); + crypto_destroy_tfm(tfm, crypto_shash_tfm(tfm)); } static inline unsigned int crypto_shash_alignmask( diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 3bacd71509fb1ce7197ac675044807a2d76f2fd1..1f2e9020acc667d5f0dd0f2e501e6f85f0fff140 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -552,7 +552,12 @@ struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, const struct crypto_type *frontend, u32 type, u32 mask); struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask); -void crypto_free_tfm(struct crypto_tfm *tfm); +void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm); + +static inline void crypto_free_tfm(struct crypto_tfm *tfm) +{ + return crypto_destroy_tfm(tfm, tfm); +} int alg_test(const char *driver, const char *alg, u32 type, u32 mask);