[PATCH] crypto: api - Do not load modules until algapi is ready

Herbert Xu
2024-05-18T07:03:59Z

On Fri, May 17, 2024 at 09:31:15PM -0700, Eric Biggers wrote:
>
> This is "normal" behavior when the crypto API instantiates a template:
>
> 1. drbg.c asks for "hmac(sha512)"
>
> 2. The crypto API looks for a direct implementation of "hmac(sha512)".
> This includes requesting a module with alias "crypto-hmac(sha512)".
>
> 3. If none is found, the "hmac" template is instantiated instead.
>
> There are two possible fixes for the bug. Either fix ecc_gen_privkey() to just
> use get_random_bytes() instead of the weird crypto API RNG, or make
> drbg_init_hash_kernel() pass the CRYPTO_NOLOAD flag to crypto_alloc_shash().
>
> Or if the TPM driver could be changed to not need to generate an ECC private key
> at probe time, that would also avoid this problem.

Thanks for diagnosing the problem. This is easy to fix though,
we could simply reuse the static branch that was created for
boot-time self-testing:

---8<---
When the Crypto API is built into the kernel, it may be invoked
during system initialisation before modules can be loaded. Ensure
that it doesn't load modules if this is the case by checking
crypto_boot_test_finished().

Add a call to wait_for_device_probe so that the drivers that may
call into the Crypto API have finished probing.

Reported-by: Nícolas F. R. A. Prado" <nfraprado@collabora.com>
Reported-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/crypto/algapi.c b/crypto/algapi.c
index 85bc279b4233..c018bcbd1f46 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -7,6 +7,7 @@

#include <crypto/algapi.h>
#include <crypto/internal/simd.h>
+#include <linux/device/driver.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/fips.h>
@@ -1056,9 +1057,12 @@ EXPORT_SYMBOL_GPL(crypto_type_has_alg);

static void __init crypto_start_tests(void)
{
- if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS))
+ if (!IS_BUILTIN(CONFIG_CRYPTO_ALGAPI))
return;

+ if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS))
+ goto test_done;
+
for (;;) {
struct crypto_larval *larval = NULL;
struct crypto_alg *q;
@@ -1092,6 +1096,8 @@ static void __init crypto_start_tests(void)
crypto_wait_for_test(larval);
}

+test_done:
+ wait_for_device_probe();
set_crypto_boot_test_finished();
}

diff --git a/crypto/api.c b/crypto/api.c
index 6aa5a3b4ed5e..5c970af04ba9 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -31,9 +31,8 @@ EXPORT_SYMBOL_GPL(crypto_alg_sem);
BLOCKING_NOTIFIER_HEAD(crypto_chain);
EXPORT_SYMBOL_GPL(crypto_chain);

-#ifndef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
+#if IS_BUILTIN(CONFIG_CRYPTO_ALGAPI)
DEFINE_STATIC_KEY_FALSE(__crypto_boot_test_finished);
-EXPORT_SYMBOL_GPL(__crypto_boot_test_finished);
#endif

static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg);
@@ -280,7 +279,7 @@ static struct crypto_alg *crypto_larval_lookup(const char *name, u32 type,
mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);

alg = crypto_alg_lookup(name, type, mask);
- if (!alg && !(mask & CRYPTO_NOLOAD)) {
+ if (crypto_boot_test_finished() && !alg && !(mask & CRYPTO_NOLOAD)) {
request_module("crypto-%s", name);

if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
diff --git a/crypto/internal.h b/crypto/internal.h
index 63e59240d5fb..d27166a92eca 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -66,7 +66,7 @@ extern struct blocking_notifier_head crypto_chain;

int alg_test(const char *driver, const char *alg, u32 type, u32 mask);

-#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
+#if !IS_BUILTIN(CONFIG_CRYPTO_ALGAPI)
static inline bool crypto_boot_test_finished(void)
{
return true;
@@ -84,7 +84,7 @@ static inline void set_crypto_boot_test_finished(void)
{
static_branch_enable(&__crypto_boot_test_finished);
}
-#endif /* !CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
+#endif /* !IS_BUILTIN(CONFIG_CRYPTO_ALGAPI) */

#ifdef CONFIG_PROC_FS
void __init crypto_init_proc(void);
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt