From: Jay Wang <wanjay@amazon.com>
To: Herbert Xu <herbert@gondor.apana.org.au>,
"David S . Miller" <davem@davemloft.net>,
<linux-crypto@vger.kernel.org>
Cc: Jay Wang <jay.wang.upstream@gmail.com>,
Vegard Nossum <vegard.nossum@oracle.com>,
Nicolai Stange <nstange@suse.de>,
Ilia Okomin <ilya.okomin@oracle.com>,
Catalin Marinas <catalin.marinas@arm.com>,
"Will Deacon" <will@kernel.org>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Borislav Petkov <bp@alien8.de>,
Luis Chamberlain <mcgrof@kernel.org>,
Petr Pavlu <petr.pavlu@suse.com>,
Nathan Chancellor <nathan@kernel.org>,
Nicolas Schier <nsc@kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <x86@kernel.org>,
<linux-kbuild@vger.kernel.org>, <linux-modules@vger.kernel.org>
Subject: [PATCH 12/17] Execute crypto initcalls during module initialization
Date: Thu, 12 Feb 2026 02:42:16 +0000 [thread overview]
Message-ID: <20260212024228.6267-13-wanjay@amazon.com> (raw)
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>
After moving builtin cryptos into the standalone crypto module, to ensure
all such cryptos are properly initialized as they were builtin, the
initcalls of the cryptos should be executed at proper booting time.
To do so, this patch adds run_initcalls() function to execute the
initialization calls of the collected cryptos right after the module is
loaded. The function iterates through initcalls in the __fips_initcalls
section (which stores all function addresses of the collected crypto
initcalls) and executes them.
A key consideration is to ensure the crypto initcalls are executed in
proper order, for instance, some crypto initcalls are ought to execute
at `late_initcall` boot time level while some should be executed at
`module_init` boot time level. To do so, this patch enables coordination
between kernel and the crypto module initialization to preserve proper
execution order by hijacking the kernel initialization function
`do_initcall_level` with added synchronization helpers.
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
crypto/fips140/fips140-loader.c | 92 +++++++++++++++++++++++++++++++++
crypto/fips140/fips140-module.c | 50 ++++++++++++++++++
crypto/fips140/fips140-module.h | 12 +++++
include/linux/init.h | 10 ++++
init/main.c | 4 ++
5 files changed, 168 insertions(+)
diff --git a/crypto/fips140/fips140-loader.c b/crypto/fips140/fips140-loader.c
index 826075928723..d9a477421063 100644
--- a/crypto/fips140/fips140-loader.c
+++ b/crypto/fips140/fips140-loader.c
@@ -107,3 +107,95 @@ static int __init fips_loader_init(void)
vfree(vmalloc_mem); // Free after successful module loading
return ret;
}
+
+/* FIPS140 synchronization between kernel and module
+ *
+ * Synchronization levels map kernel initcall levels to FIPS module levels:
+ * - Level 0: subsys_initcall (kernel init level 4) - Basic subsystem initialization
+ * - Level 1: device_initcall (kernel init level 6) - Device driver initialization
+ * - Level 2: late_initcall (kernel init level 7) - Late system initialization
+ *
+ * The kernel marks each level complete and waits for the FIPS module to
+ * complete the corresponding level before proceeding to ensure proper
+ * initialization ordering between kernel crypto and FIPS module.
+ */
+atomic_t fips140_kernel_level_complete = ATOMIC_INIT(0);
+atomic_t fips140_module_level_complete = ATOMIC_INIT(0);
+
+/* Wait queues for efficient synchronization */
+DECLARE_WAIT_QUEUE_HEAD(fips140_kernel_wq);
+DECLARE_WAIT_QUEUE_HEAD(fips140_module_wq);
+
+void fips140_mark_kernel_level_complete(int level)
+{
+ atomic_or(1 << level, &fips140_kernel_level_complete);
+ wake_up(&fips140_kernel_wq);
+}
+
+bool fips140_is_kernel_level_complete(int level)
+{
+ return atomic_read(&fips140_kernel_level_complete) & (1 << level);
+}
+
+bool fips140_is_module_level_complete(int level)
+{
+ return atomic_read(&fips140_module_level_complete) & (1 << level);
+}
+
+void fips140_mark_module_level_complete(int level)
+{
+ atomic_or(1 << level, &fips140_module_level_complete);
+ wake_up(&fips140_module_wq);
+}
+
+static int __init fips140_sync_thread(void *data)
+{
+ pr_info("FIPS 140: starting sync thread\n");
+
+ /* Call FIPS loader explicitly */
+ int ret = fips_loader_init();
+ if (ret)
+ panic("FIPS 140: loader initialization failed: %d\n", ret);
+
+ pr_info("FIPS 140: sync thread finished\n");
+ return 0;
+}
+
+void __init start_fips140_loader(void)
+{
+ struct task_struct *task;
+
+ task = kthread_run(fips140_sync_thread, NULL, "fips140_sync");
+ if (IS_ERR(task)) {
+ panic("FIPS 140: failed to create sync thread\n");
+ }
+}
+
+void __init wait_until_fips140_level_sync(int level)
+{
+ /* Map kernel initcall levels to FIPS module levels */
+ int fips_level = -1;
+ if (level == 3) /* Start FIPS loader thread at arch_initcall_sync level */
+ start_fips140_loader();
+ if (level == 4) /* subsys_initcall */
+ fips_level = 0;
+ else if (level == 6) /* device_initcall */
+ fips_level = 1;
+ else if (level == 7) /* late_initcall */
+ fips_level = 2;
+
+ if (fips_level >= 0) {
+ /* Mark kernel level complete and wait for module level completion */
+ fips140_mark_kernel_level_complete(fips_level);
+ wait_event(fips140_module_wq, fips140_is_module_level_complete(fips_level));
+ }
+}
+
+EXPORT_SYMBOL(fips140_kernel_level_complete);
+EXPORT_SYMBOL(fips140_module_level_complete);
+EXPORT_SYMBOL(fips140_kernel_wq);
+EXPORT_SYMBOL(fips140_module_wq);
+EXPORT_SYMBOL(fips140_mark_kernel_level_complete);
+EXPORT_SYMBOL(fips140_is_kernel_level_complete);
+EXPORT_SYMBOL(fips140_is_module_level_complete);
+EXPORT_SYMBOL(fips140_mark_module_level_complete);
\ No newline at end of file
diff --git a/crypto/fips140/fips140-module.c b/crypto/fips140/fips140-module.c
index a942de8780ef..e0e669ba1b5e 100644
--- a/crypto/fips140/fips140-module.c
+++ b/crypto/fips140/fips140-module.c
@@ -16,9 +16,59 @@
#define CRYPTO_INTERNAL "CRYPTO_INTERNAL"
+static int __init run_initcalls(void)
+{
+ typedef int (*initcall_t)(void);
+
+ extern initcall_t __fips140_initcall0_start[], __fips140_initcall0_end[];
+ extern initcall_t __fips140_initcall1_start[], __fips140_initcall1_end[];
+ extern initcall_t __fips140_initcall2_start[], __fips140_initcall2_end[];
+
+ initcall_t *starts[] = {
+ __fips140_initcall0_start,
+ __fips140_initcall1_start,
+ __fips140_initcall2_start,
+ };
+
+ initcall_t *ends[] = {
+ __fips140_initcall0_end,
+ __fips140_initcall1_end,
+ __fips140_initcall2_end,
+ };
+
+ pr_info("FIPS 140: run_initcalls starting\n");
+
+ for (int level = 0; level < ARRAY_SIZE(starts); level++) {
+
+ /* Run FIPS initcalls for this level */
+ for (initcall_t *initcall = starts[level]; initcall < ends[level]; ++initcall) {
+ int ret;
+ initcall_t fn = *initcall;
+
+ ret = fn();
+ if (!ret || ret == -ENODEV)
+ continue;
+
+ pr_err("FIPS 140: initcall %pS failed: %d\n", fn, ret);
+ }
+
+ if (level < 2)
+ fips140_mark_module_level_complete(level);
+ /* Wait for kernel to complete this level */
+ wait_event(fips140_kernel_wq, fips140_is_kernel_level_complete(level));
+ }
+
+ pr_info("FIPS 140: run_initcalls finished\n");
+ return 0;
+}
+
/* Initialize the FIPS 140 module */
static int __init fips140_init(void)
{
+ pr_info("loading " FIPS140_MODULE_NAME "\n");
+
+ run_initcalls();
+ fips140_mark_module_level_complete(2);
return 0;
}
diff --git a/crypto/fips140/fips140-module.h b/crypto/fips140/fips140-module.h
index ed2b6e17969f..e95dac8eeda9 100644
--- a/crypto/fips140/fips140-module.h
+++ b/crypto/fips140/fips140-module.h
@@ -10,5 +10,17 @@
#include <linux/crypto.h>
#include <crypto/algapi.h>
#include <linux/init.h>
+#include <linux/atomic.h>
+#include <linux/wait.h>
+
+/* FIPS140 synchronization between kernel and module */
+extern atomic_t fips140_kernel_level_complete;
+extern atomic_t fips140_module_level_complete;
+extern wait_queue_head_t fips140_kernel_wq;
+
+void fips140_mark_kernel_level_complete(int level);
+bool fips140_is_kernel_level_complete(int level);
+bool fips140_is_module_level_complete(int level);
+void fips140_mark_module_level_complete(int level);
#endif /* _CRYPTO_FIPS140_MODULE_H */
diff --git a/include/linux/init.h b/include/linux/init.h
index 40331923b9f4..eefbdfac1d41 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -392,4 +392,14 @@ void __init parse_early_options(char *cmdline);
#define __exit_p(x) NULL
#endif
+#if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(__ASSEMBLY__)
+/* FIPS140 synchronization between kernel and module */
+void fips140_mark_kernel_level_complete(int level);
+bool fips140_is_kernel_level_complete(int level);
+bool fips140_is_module_level_complete(int level);
+void fips140_mark_module_level_complete(int level);
+void start_fips140_loader(void);
+void wait_until_fips140_level_sync(int level);
+#endif /* CONFIG_CRYPTO_FIPS140_EXTMOD && !__ASSEMBLY__ */
+
#endif /* _LINUX_INIT_H */
diff --git a/init/main.c b/init/main.c
index b84818ad9685..0324226fe7b9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1438,6 +1438,10 @@ static void __init do_initcall_level(int level, char *command_line)
do_trace_initcall_level(initcall_level_names[level]);
for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
do_one_initcall(initcall_from_entry(fn));
+
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ wait_until_fips140_level_sync(level);
+#endif
}
static void __init do_initcalls(void)
--
2.47.3
next prev parent reply other threads:[~2026-02-12 2:45 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-12 2:42 [PATCH v1 00/17] crypto: Standalone crypto module (Series 1/4): Core implementation Jay Wang
2026-02-12 2:42 ` [PATCH 01/17] crypto: add Kconfig options for standalone crypto module Jay Wang
2026-02-12 2:42 ` [PATCH 02/17] crypto: add module entry for standalone crypto kernel module Jay Wang
2026-02-12 2:42 ` [PATCH 03/17] build: special compilation rule for building the standalone crypto module Jay Wang
2026-02-12 2:42 ` [PATCH 04/17] build: Add ELF marker for crypto-objs-m modules Jay Wang
2026-02-12 2:42 ` [PATCH 05/17] module: allow kernel module loading directly from memory Jay Wang
2026-02-12 2:42 ` [PATCH 06/17] crypto: add pluggable interface for builtin crypto modules Jay Wang
2026-02-12 2:42 ` [PATCH 07/17] crypto: dedicated ELF sections for collected crypto initcalls Jay Wang
2026-02-12 2:42 ` [PATCH 08/17] crypto: fips140: add crypto module loader Jay Wang
2026-02-12 2:42 ` [PATCH 09/17] build: embed the standalone crypto module into vmlinux Jay Wang
2026-02-12 2:42 ` [PATCH 10/17] build: add CONFIG_DEBUG_INFO_BTF_MODULES support for the standalone crypto kernel module Jay Wang
2026-02-12 2:42 ` [PATCH 11/17] Allow selective crypto module loading at boot based on FIPS mode Jay Wang
2026-02-12 2:42 ` Jay Wang [this message]
2026-02-12 2:42 ` [PATCH 13/17] crypto/algapi.c: skip crypto_check_module_sig() for the standalone crypto module Jay Wang
2026-02-12 2:42 ` [PATCH 14/17] crypto: fips140: add module integrity self-check Jay Wang
2026-02-12 2:42 ` [PATCH 15/17] x86: crypto: to convert exported crypto symbols into pluggable interface for x86 cryptos Jay Wang
2026-02-12 2:42 ` [PATCH 16/17] arm64: crypto: to convert exported crypto symbols into pluggable interface for arm64 cryptos Jay Wang
2026-02-12 2:42 ` [PATCH 17/17] Add standalone crypto kernel module technical documentation Jay Wang
2026-02-25 1:55 ` Eric Biggers
2026-02-25 14:08 ` Christoph Hellwig
2026-02-25 17:35 ` Jay Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260212024228.6267-13-wanjay@amazon.com \
--to=wanjay@amazon.com \
--cc=bp@alien8.de \
--cc=catalin.marinas@arm.com \
--cc=davem@davemloft.net \
--cc=herbert@gondor.apana.org.au \
--cc=ilya.okomin@oracle.com \
--cc=jay.wang.upstream@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-modules@vger.kernel.org \
--cc=mcgrof@kernel.org \
--cc=mingo@redhat.com \
--cc=nathan@kernel.org \
--cc=nsc@kernel.org \
--cc=nstange@suse.de \
--cc=petr.pavlu@suse.com \
--cc=tglx@kernel.org \
--cc=vegard.nossum@oracle.com \
--cc=will@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox