crypto: hash - Fix clone error handling
authorHerbert Xu <herbert@gondor.apana.org.au>
Wed, 23 Apr 2025 09:22:31 +0000 (17:22 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Mon, 28 Apr 2025 11:40:54 +0000 (19:40 +0800)
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 <herbert@gondor.apana.org.au>
crypto/ahash.c
crypto/api.c
crypto/shash.c

index 9b813f7b9177db910ebc3aefdf3530e78e94da22..cc9885d5cfd2653590309dfca996c51802965b35 100644 (file)
@@ -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);
index 172e82f79c69a7fb79fd5dbab24fd8904b248e75..5cd5ec105bb142b00560dc2bb8b0c8eec5d45c2b 100644 (file)
@@ -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;
index b6c79a4a044a1504e296dc14516702125ed0e8d0..c4a724e55d7a69a5515a6b6554c3e70974797a40 100644 (file)
@@ -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);