Thread (39 messages) flat view 39 messages, 10 authors, 2022-03-17

Re: [PATCH] crypto: api - Fix built-in testing dependency failures

From: Eric Biggers <ebiggers@kernel.org>
Date: 2021-09-13 18:16:08

On Mon, Sep 13, 2021 at 03:12:51PM +0800, Herbert Xu wrote:
When complex algorithms that depend on other algorithms are built
into the kernel, the order of registration must be done such that
the underlying algorithms are ready before the ones on top are
registered.  As otherwise they would fail during the self-test
which is required during registration.

In the past we have used subsystem initialisation ordering to
guarantee this.  The number of such precedence levels are limited
and they may cause ripple effects in other subsystems.

This patch solves this problem by delaying all self-tests during
boot-up for built-in algorithms.  They will be tested either when
something else in the kernel requests for them, or when we have
finished registering all built-in algorithms, whichever comes
earlier.
Are there any specific examples that you could give?
quoted hunk ↗ jump to hunk
 int crypto_register_alg(struct crypto_alg *alg)
 {
 	struct crypto_larval *larval;
+	bool tested;
 	int err;
 
 	alg->cra_flags &= ~CRYPTO_ALG_DEAD;
@@ -421,12 +402,15 @@ int crypto_register_alg(struct crypto_alg *alg)
 
 	down_write(&crypto_alg_sem);
 	larval = __crypto_register_alg(alg);
+	tested = static_key_enabled(&crypto_boot_test_finished);
+	larval->tested = tested;
'tested' is set before the algorithm has actually been tested, and it sounds
like the same as CRYPTO_ALG_TESTED which already exists.  Maybe it should be
called something else, like 'test_started'?
+static void __init crypto_start_tests(void)
+{
+	for (;;) {
+		struct crypto_larval *larval = NULL;
+		struct crypto_alg *q;
+
+		down_write(&crypto_alg_sem);
+
+		list_for_each_entry(q, &crypto_alg_list, cra_list) {
+			struct crypto_larval *l;
+
+			if (!crypto_is_larval(q))
+				continue;
+
+			l = (void *)q;
+
+			if (!crypto_is_test_larval(l))
+				continue;
+
+			if (l->tested)
+				continue;
+
+			l->tested = true;
+			larval = l;
+			break;
+		}
+
+		up_write(&crypto_alg_sem);
+
+		if (!larval)
+			break;
+
+		crypto_wait_for_test(larval);
+	}
Is there a way to continue iterating from the previous algorithm, so that this
doesn't take quadratic time?
+
+	static_branch_enable(&crypto_boot_test_finished);
+}
+
 static int __init crypto_algapi_init(void)
 {
 	crypto_init_proc();
+	crypto_start_tests();
A comment explaining why the tests aren't run until late_initcall would be
helpful.  People shouldn't have to dig through commit messages to understand the
code.

Also, did you check whether there is anything that relies on the crypto API
being available before or during late_initcall?  That wouldn't work with this
new approach, right?

- Eric
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help