From 2cfe41630a1a4f24d46825aa9656a51a38fb7f7d Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 23 Apr 2025 17:22:31 +0800 Subject: [PATCH] crypto: hash - Fix clone error handling Do not copy the exit function in crypto_clone_tfm as it should only be set after init_tfm or clone_tfm has succeeded. Move the setting into crypto_clone_ahash and crypto_clone_shash instead. Also clone the fb if necessary. Signed-off-by: Herbert Xu --- crypto/ahash.c | 19 +++++++++++++++++-- crypto/api.c | 2 +- crypto/shash.c | 3 +++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/crypto/ahash.c b/crypto/ahash.c index 9b813f7b9177..cc9885d5cfd2 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -877,6 +877,7 @@ struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) { struct hash_alg_common *halg = crypto_hash_alg_common(hash); struct crypto_tfm *tfm = crypto_ahash_tfm(hash); + struct crypto_ahash *fb = NULL; struct crypto_ahash *nhash; struct ahash_alg *alg; int err; @@ -906,22 +907,36 @@ struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) err = PTR_ERR(shash); goto out_free_nhash; } + crypto_ahash_tfm(nhash)->exit = crypto_exit_ahash_using_shash; nhash->using_shash = true; *nctx = shash; return nhash; } + if (ahash_is_async(hash)) { + fb = crypto_clone_ahash(crypto_ahash_fb(hash)); + err = PTR_ERR(fb); + if (IS_ERR(fb)) + goto out_free_nhash; + + crypto_ahash_tfm(nhash)->fb = crypto_ahash_tfm(fb); + } + err = -ENOSYS; alg = crypto_ahash_alg(hash); if (!alg->clone_tfm) - goto out_free_nhash; + goto out_free_fb; err = alg->clone_tfm(nhash, hash); if (err) - goto out_free_nhash; + goto out_free_fb; + + crypto_ahash_tfm(nhash)->exit = crypto_ahash_exit_tfm; return nhash; +out_free_fb: + crypto_free_ahash(fb); out_free_nhash: crypto_free_ahash(nhash); return ERR_PTR(err); diff --git a/crypto/api.c b/crypto/api.c index 172e82f79c69..5cd5ec105bb1 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -570,7 +570,7 @@ void *crypto_clone_tfm(const struct crypto_type *frontend, tfm = (struct crypto_tfm *)(mem + frontend->tfmsize); tfm->crt_flags = otfm->crt_flags; - tfm->exit = otfm->exit; + tfm->fb = tfm; out: return mem; diff --git a/crypto/shash.c b/crypto/shash.c index b6c79a4a044a..c4a724e55d7a 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -413,6 +413,9 @@ struct crypto_shash *crypto_clone_shash(struct crypto_shash *hash) } } + if (alg->exit_tfm) + crypto_shash_tfm(nhash)->exit = crypto_shash_exit_tfm; + return nhash; } EXPORT_SYMBOL_GPL(crypto_clone_shash); -- 2.50.1