Cryptographic components must be properly initialized
before use. This initialization is typically achieved
through dedicated init functions registered via wrappers
such as module_init() or late_initcall(). Traditionally,
these init functions are executed automatically as part of
the kernel boot sequence. However, now that the crypto code
is moved into a standalone module (fips140.ko), there needs
to be a way to collect and later execute them from within
the module.

To collect these init functions, the init wrappers
(module_init(), subsys_initcall(), late_initcall()) are
modified so that when compiled for the FIPS module (under
-DFIPS_MODULE), they automatically place the wrapped crypto
init function pointer into a dedicated ELF section instead
of the normal initcall mechanism. A custom linker script
crypto/fips140/fips140.lds is introduced to organize these
sections. Since the init functions must be called in proper
ordering in a later patch (e.g., subsys_initcall before
module_init, and module_init before late_initcall), the
linker script allocates separate leveled sections
(.fips_initcall0, .fips_initcall1, .fips_initcall2) with
corresponding boundary symbols (e.g.,
__fips140_initcall0_start/end) to preserve the correct
execution order.

Signed-off-by: Jay Wang <[email protected]>
---
 Makefile                   |  2 +-
 crypto/fips140/fips140.lds | 38 ++++++++++++++++++++++++++++++++++++++
 include/linux/module.h     | 23 +++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 crypto/fips140/fips140.lds

diff --git a/Makefile b/Makefile
index feacb5bd6235a..f3c43f87d6786 100644
--- a/Makefile
+++ b/Makefile
@@ -1378,7 +1378,7 @@ crypto/fips140/.fips140.symvers: fips140-ready
        @:
 modpost: crypto/fips140/.fips140.symvers
 quiet_cmd_ld_fips140 = LD [M]  $@
-      cmd_ld_fips140 = $(LD) -r $(KBUILD_LDFLAGS) $(KBUILD_LDFLAGS_MODULE) 
$(LDFLAGS_MODULE) --build-id=none --whole-archive $< --no-whole-archive -o $@
+      cmd_ld_fips140 = $(LD) -r $(KBUILD_LDFLAGS) $(KBUILD_LDFLAGS_MODULE) 
$(LDFLAGS_MODULE) --build-id=none -T $(srctree)/crypto/fips140/fips140.lds 
--whole-archive $< --no-whole-archive -o $@
 
 cmd_fips140_mod = ar -t $< > $@
 
diff --git a/crypto/fips140/fips140.lds b/crypto/fips140/fips140.lds
new file mode 100644
index 0000000000000..6b5c63b1c6028
--- /dev/null
+++ b/crypto/fips140/fips140.lds
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * FIPS 140 module initcall section layout.
+ *
+ * The overridden subsys_initcall/module_init/late_initcall macros
+ * (include/linux/module.h) place function pointers into these
+ * sections when compiled with FIPS_MODULE defined.
+ *
+ * Section mapping:
+ *   .fips_initcall0  <-  subsys_initcall()
+ *                        Syncs with kernel subsys_initcall (initcall level 4)
+ *   .fips_initcall1  <-  module_init()
+ *                        Syncs with kernel device_initcall (initcall level 6)
+ *   .fips_initcall2  <-  late_initcall()
+ *                        Syncs with kernel late_initcall (initcall level 7)
+ *
+ * The fips140 loader thread (fips140-loader.c) starts at
+ * arch_initcall_sync (level 3) and run_initcalls() in
+ * fips140-module.c executes each level in order, synchronizing
+ * with the kernel's initcall progression via wait queues.
+ */
+
+SECTIONS {
+       .init.data : {
+               __fips140_initcalls_start = .;
+               __fips140_initcall0_start = .;
+               *(.fips_initcall0)
+               __fips140_initcall0_end = .;
+               __fips140_initcall1_start = .;
+               *(.fips_initcall1)
+               __fips140_initcall1_end = .;
+               __fips140_initcall2_start = .;
+               *(.fips_initcall2)
+               __fips140_initcall2_end = .;
+               __fips140_initcalls_end = .;
+       }
+}
\ No newline at end of file
diff --git a/include/linux/module.h b/include/linux/module.h
index 0ff24c45ef61d..6a10b70b5e92c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -115,18 +115,40 @@ extern void cleanup_module(void);
 #define postcore_initcall(fn)          module_init(fn)
 #define postcore_initcall_sync(fn)     module_init(fn)
 #define arch_initcall(fn)              module_init(fn)
+#if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && defined(FIPS_MODULE) && 
!defined(FIPS140_CORE)
+#define subsys_initcall(fn) \
+       static initcall_t __used __section(".fips_initcall0") \
+               __fips_##fn = fn;
+#else
 #define subsys_initcall(fn)            module_init(fn)
+#endif
 #define subsys_initcall_sync(fn)       module_init(fn)
 #define fs_initcall(fn)                        module_init(fn)
 #define fs_initcall_sync(fn)           module_init(fn)
 #define rootfs_initcall(fn)            module_init(fn)
 #define device_initcall(fn)            module_init(fn)
 #define device_initcall_sync(fn)       module_init(fn)
+#if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && defined(FIPS_MODULE) && 
!defined(FIPS140_CORE)
+#define late_initcall(fn) \
+       static initcall_t __used __section(".fips_initcall2") \
+               __fips_##fn = fn;
+#else
 #define late_initcall(fn)              module_init(fn)
+#endif
 #define late_initcall_sync(fn)         module_init(fn)
 
 #define console_initcall(fn)           module_init(fn)
 
+#if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && defined(FIPS_MODULE) && 
!defined(FIPS140_CORE)
+/* FIPS module: place init/exit in special sections for fips140 loader */
+#define module_init(initfn) \
+       static initcall_t __used __section(".fips_initcall1") \
+               __fips_##initfn = initfn;
+
+#define module_exit(exitfn) \
+       static unsigned long __used __section(".fips_exitcall") \
+               __fips_##exitfn = (unsigned long)&exitfn;
+#else
 /* Each module must use one module_init(). */
 #define module_init(initfn)                                    \
        static inline initcall_t __maybe_unused __inittest(void)                
\
@@ -142,6 +164,7 @@ extern void cleanup_module(void);
        void cleanup_module(void) __copy(exitfn)                \
                __attribute__((alias(#exitfn)));                \
        ___ADDRESSABLE(cleanup_module, __exitdata);
+#endif /* CONFIG_CRYPTO_FIPS140_EXTMOD && FIPS_MODULE && !FIPS140_CORE */
 
 #endif
 
-- 
2.47.3


Reply via email to