* [PATCH 06/17] crypto: add pluggable interface for builtin crypto modules
From: Jay Wang @ 2026-02-12 2:42 UTC (permalink / raw)
To: Herbert Xu, David S . Miller, linux-crypto
Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>
Traditionally, builtin cryptos interact with the main kernel through
exported functions and variables via EXPORT_SYMBOL. The exported
symbols are statically tied with the main kernel, so not suitable
after those builtin cryptos moved to a standalone kernel module
(e.g., main kernel will not even be compilable since users need the
exact function/variable address).
To address this, introduce a pluggable interface between builtin
crypto functions and variables by placing address placeholders.
During runtime once the crypto kernel module is loaded, the address
placeholder gets updated (by `do_crypto_api` and `do_crypto_var`) to
correct address.
In more details, there are two types of address holders: for function
addresses, "static call" mechanism is used; for variable addresses, a
var_type* pointer is used. To apply this pluggable interface, just
wrap the function/variable header declaration with the placeholder
declaration wrappers (implemented as `DECLARE_STATIC_CALL()`/
`DECLARE_CRYPTO_VAR()`), and place the placeholder definition wrappers
for each crypto function/variable in fips140-api.c (implemented as
`DEFINE_CRYPTO_API_STUB()`/`DEFINE_CRYPTO_VAR_STUB()`). Those wrappers
will be compiled differently for main kernel and the crypto kernel
module using different compilation flags. To make such pluggable
interface only affect cryptos chosen as builtin but not crypto chosen
built as modules already, associate wrappers with CONFIG_CRYPTO_{NAME}
parameter.
In addition to the pluggable interface, this patch also adds a way to
collect crypto init functions, such as `module_init()` into a
dedicated ELF section for later module entry to initialize each
crypto.
The idea of using "static call" as pluggable interface for function
address stems from Vegard Nossum <vegard.nossum@oracle.com>, while
we additionally make the following core differences: avoid duplicate
crypto code in main kernel, allow variable pluggable, make this
feature not affect cryptos already chosen to be module-built, and
make this adapt to any .config choices.
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
crypto/fips140/Makefile | 5 +-
crypto/fips140/fips140-api.c | 7 ++
include/asm-generic/vmlinux.lds.h | 1 +
include/crypto/api.h | 197 ++++++++++++++++++++++++++++++
kernel/module/main.c | 46 ++++++-
5 files changed, 253 insertions(+), 3 deletions(-)
create mode 100644 crypto/fips140/fips140-api.c
create mode 100644 include/crypto/api.h
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
index 3b4a74ccf41e..fb083022efbb 100644
--- a/crypto/fips140/Makefile
+++ b/crypto/fips140/Makefile
@@ -1,5 +1,8 @@
crypto-objs-y += \
- fips140-module.o
+ fips140-module.o \
+ fips140-api.o
+
+obj-y += fips140-api.o
clean-files:= .fips140.order .fips140.symvers
\ No newline at end of file
diff --git a/crypto/fips140/fips140-api.c b/crypto/fips140/fips140-api.c
new file mode 100644
index 000000000000..a11e898ff4bc
--- /dev/null
+++ b/crypto/fips140/fips140-api.c
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Define static call keys for any functions which are part of the crypto
+ * API and used by the standalone FIPS module but which are not built into
+ * vmlinux.
+ */
\ No newline at end of file
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index eeb070f330bd..e25b44d29362 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -724,6 +724,7 @@
KERNEL_CTORS() \
MCOUNT_REC() \
*(.init.rodata .init.rodata.*) \
+ BOUNDED_SECTION(__crypto_api_keys) \
FTRACE_EVENTS() \
TRACE_SYSCALLS() \
KPROBE_BLACKLIST() \
diff --git a/include/crypto/api.h b/include/crypto/api.h
new file mode 100644
index 000000000000..b58240ffd173
--- /dev/null
+++ b/include/crypto/api.h
@@ -0,0 +1,197 @@
+#ifndef _CRYPTO_API_H
+#define _CRYPTO_API_H
+
+#include <linux/static_call.h>
+
+#define CRYPTO_VAR_NAME(name) __crypto_##name##_ptr
+
+#define __CAT(a,b) a##b
+#define _CAT(a,b) __CAT(a,b)
+
+#define __IF_1(...) __VA_ARGS__
+#define __IF_0(...)
+#define __IFNOT_1(...)
+#define __IFNOT_0(...) __VA_ARGS__
+
+/* Emit __VA_ARGS__ only if cfg is built into vmlinux (=y) */
+#define IF_BUILTIN(cfg, ...) _CAT(__IF_, IS_BUILTIN(cfg))(__VA_ARGS__)
+/* Emit __VA_ARGS__ only if cfg is NOT built in (i.e., =m or unset) */
+#define IF_NOT_BUILTIN(cfg, ...) _CAT(__IFNOT_, IS_BUILTIN(cfg))(__VA_ARGS__)
+
+#if !defined(CONFIG_CRYPTO_FIPS140_EXTMOD)
+
+/*
+ * These are the definitions that get used when no standalone FIPS module
+ * is used: we simply forward everything to normal functions and function
+ * calls.
+ */
+
+#define DECLARE_CRYPTO_API(cfg, name, ret_type, args_decl, args_call) \
+ ret_type name args_decl;
+
+#define DECLARE_CRYPTO_VAR(cfg, name, var_type, ...) \
+ extern var_type name __VA_ARGS__;
+
+#define crypto_module_init(fn) module_init(fn)
+#define crypto_module_exit(fn) module_exit(fn)
+
+#define crypto_subsys_initcall(fn) subsys_initcall(fn)
+#define crypto_late_initcall(fn) late_initcall(fn)
+
+#define crypto_module_cpu_feature_match(x, __initfunc) \
+ module_cpu_feature_match(x, __initfunc)
+
+#else
+
+struct crypto_api_key {
+ struct static_call_key *key;
+ void *tramp;
+ void *func;
+};
+
+struct crypto_var_key {
+ void **ptr;
+ void *var;
+};
+
+#ifndef FIPS_MODULE
+
+/*
+ * These are the definitions that get used for vmlinux and in-tree
+ * kernel modules.
+ *
+ * In this case, all references to the kernel crypto API functions will
+ * be replaced by wrappers that perform a call using the kernel's static_call
+ * functionality.
+ */
+
+/* Consolidated version of different DECLARE_CRYPTO_API versions */
+
+/*
+ * - If cfg is built-in (=y): declare nonfips_<name>, a static_call key,
+ * and an inline wrapper <name>() that dispatches via static_call.
+ * - Else (cfg =m or unset): only declare <name>() prototype.
+ */
+#define DECLARE_CRYPTO_API(cfg, name, ret_type, args_decl, args_call) \
+ IF_BUILTIN(cfg, \
+ ret_type nonfips_##name args_decl; \
+ DECLARE_STATIC_CALL(crypto_##name##_key, nonfips_##name); \
+ static inline ret_type name args_decl \
+ { \
+ return static_call(crypto_##name##_key) args_call; \
+ } \
+ ) \
+ IF_NOT_BUILTIN(cfg, \
+ ret_type name args_decl; \
+ )
+
+#define DECLARE_CRYPTO_VAR(cfg, name, var_type, ...) \
+ IF_BUILTIN(cfg, \
+ extern void *CRYPTO_VAR_NAME(name); \
+ ) \
+ IF_NOT_BUILTIN(cfg, \
+ extern var_type name __VA_ARGS__; \
+ )
+
+#define DEFINE_CRYPTO_API_STUB(name) \
+ DEFINE_STATIC_CALL_NULL(crypto_##name##_key, name); \
+ EXPORT_STATIC_CALL(crypto_##name##_key)
+
+#define DEFINE_CRYPTO_VAR_STUB(name) \
+ void* CRYPTO_VAR_NAME(name) = NULL;\
+ EXPORT_SYMBOL(CRYPTO_VAR_NAME(name));
+
+#define crypto_module_init(fn) module_init(fn)
+#define crypto_module_exit(fn) module_exit(fn)
+
+#define crypto_subsys_initcall(fn) subsys_initcall(fn)
+#define crypto_late_initcall(fn) late_initcall(fn)
+
+#define crypto_module_cpu_feature_match(x, __initfunc) \
+ module_cpu_feature_match(x, __initfunc)
+
+#else /* defined(FIPS_MODULE) */
+
+/* Consolidated version of different DECLARE_CRYPTO_API versions,
+ within FIPS module, API remains the same, only declare static
+ call key */
+#define DECLARE_CRYPTO_API(cfg, name, ret_type, args_decl, args_call) \
+ IF_BUILTIN(cfg, \
+ ret_type name args_decl; \
+ DECLARE_STATIC_CALL(crypto_##name##_key, name) \
+ ) \
+ IF_NOT_BUILTIN(cfg, \
+ ret_type name args_decl; \
+ )
+
+#define DECLARE_CRYPTO_VAR(cfg, name, var_type, ...) \
+ IF_BUILTIN(cfg, \
+ extern var_type name __VA_ARGS__; \
+ extern void *CRYPTO_VAR_NAME(name); \
+ ) \
+ IF_NOT_BUILTIN(cfg, \
+ extern var_type name __VA_ARGS__; \
+ )
+
+#define DEFINE_CRYPTO_VAR_STUB(name) \
+ static struct crypto_var_key __crypto_##name##_var_key \
+ __used \
+ __section("__crypto_var_keys") \
+ __aligned(__alignof__(struct crypto_var_key)) = \
+ { \
+ .ptr = &CRYPTO_VAR_NAME(name), \
+ .var = (void*)&name, \
+ };
+
+/*
+ * These are the definitions that get used for the main kernel.
+ *
+ * In this case, initialize crypto static call key with original name
+ */
+
+#define DEFINE_CRYPTO_API_STUB(name) \
+ static struct crypto_api_key __##name##_key \
+ __used \
+ __section("__crypto_api_keys") \
+ __aligned(__alignof__(struct crypto_api_key)) = \
+ { \
+ .key = &STATIC_CALL_KEY(crypto_##name##_key), \
+ .tramp = STATIC_CALL_TRAMP_ADDR(crypto_##name##_key), \
+ .func = &name, \
+ };
+
+#define crypto_module_init(fn) \
+ static initcall_t __used __section(".fips_initcall1") \
+ __fips_##fn = fn;
+#define crypto_module_exit(fn) \
+ static unsigned long __used __section(".fips_exitcall") \
+ __fips_##fn = (unsigned long) &fn;
+#define crypto_subsys_initcall(fn) \
+ static initcall_t __used __section(".fips_initcall0") \
+ __fips_##fn = fn;
+#define crypto_subsys_exitcall(fn) \
+ static unsigned long __used __section(".fips_exitcall") \
+ __fips_##fn = (unsigned long) &fn;
+#define crypto_late_initcall(fn) \
+ static initcall_t __used __section(".fips_initcall2") \
+ __fips_##fn = fn;
+#define crypto_late_exitcall(fn) \
+ static unsigned long __used __section(".fips_exitcall") \
+ __fips_##fn = (unsigned long) &fn;
+
+#define crypto_module_cpu_feature_match(x, __initfunc) \
+static struct cpu_feature const __maybe_unused cpu_feature_match_ ## x[] = \
+ { { .feature = cpu_feature(x) }, { } }; \
+MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x); \
+static int __init cpu_feature_match_ ## x ## _init(void) \
+{ \
+ if (!cpu_have_feature(cpu_feature(x))) \
+ return -ENODEV; \
+ return __initfunc(); \
+} \
+crypto_module_init(cpu_feature_match_ ## x ## _init)
+
+#endif /* defined(FIPS_MODULE) */
+#endif /* defined(CONFIG_CRYPTO_FIPS140_EXTMOD) */
+
+#endif /* !_CRYPTO_API_H */
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 2914e7619766..dad84f0548ac 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -7,6 +7,7 @@
#define INCLUDE_VERMAGIC
+#include <crypto/api.h>
#include <linux/export.h>
#include <linux/extable.h>
#include <linux/moduleloader.h>
@@ -2956,6 +2957,39 @@ static int post_relocation(struct module *mod, const struct load_info *info)
return module_finalize(info->hdr, info->sechdrs, mod);
}
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+static void do_crypto_api(struct load_info *info)
+{
+ struct crypto_api_key *crypto_api_keys;
+ unsigned int num_crypto_api_keys;
+
+ unsigned int i;
+
+ crypto_api_keys = section_objs(info, "__crypto_api_keys",
+ sizeof(*crypto_api_keys), &num_crypto_api_keys);
+
+ for (i = 0; i < num_crypto_api_keys; ++i) {
+ struct crypto_api_key *key = &crypto_api_keys[i];
+ __static_call_update(key->key, key->tramp, key->func);
+ }
+}
+
+static void do_crypto_var(struct load_info *info)
+{
+ struct crypto_var_key *crypto_var_keys;
+ unsigned int num_crypto_var_keys;
+ unsigned int i;
+
+ crypto_var_keys = section_objs(info, "__crypto_var_keys",
+ sizeof(*crypto_var_keys), &num_crypto_var_keys);
+
+ for (i = 0; i < num_crypto_var_keys; ++i) {
+ struct crypto_var_key *var_key = &crypto_var_keys[i];
+ *(var_key->ptr) = var_key->var;
+ }
+}
+#endif
+
/* Call module constructors. */
static void do_mod_ctors(struct module *mod)
{
@@ -3010,7 +3044,7 @@ module_param(async_probe, bool, 0644);
* Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb
* helper command 'lx-symbols'.
*/
-static noinline int do_init_module(struct module *mod, int flags)
+static noinline int do_init_module(struct load_info *info, struct module *mod, int flags)
{
int ret = 0;
struct mod_initfree *freeinit;
@@ -3036,6 +3070,14 @@ static noinline int do_init_module(struct module *mod, int flags)
freeinit->init_data = mod->mem[MOD_INIT_DATA].base;
freeinit->init_rodata = mod->mem[MOD_INIT_RODATA].base;
+#ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ if (flags & MODULE_INIT_CRYPTO_FROM_MEM)
+ {
+ do_crypto_api(info);
+ do_crypto_var(info);
+ }
+#endif
+
do_mod_ctors(mod);
/* Start the module */
if (mod->init != NULL)
@@ -3499,7 +3541,7 @@ static int _load_module(struct load_info *info, const char __user *uargs,
/* Done! */
trace_module_load(mod);
- return do_init_module(mod, flags);
+ return do_init_module(info, mod, flags);
sysfs_cleanup:
mod_sysfs_teardown(mod);
--
2.47.3
^ permalink raw reply related
* [PATCH 05/17] module: allow kernel module loading directly from memory
From: Jay Wang @ 2026-02-12 2:42 UTC (permalink / raw)
To: Herbert Xu, David S . Miller, linux-crypto
Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>
From: Vegard Nossum <vegard.nossum@oracle.com>
To enable loading the crypto module earlier before file system is ready,
add a new helper function, load_crypto_module_mem(), which can load a kernel
module from a byte array in memory. When loading in this way, we don't
do signature verification as crypto is not ready yet before loaded.
To tell that a module is loaded in this way, a new module loader flag,
MODULE_INIT_CRYPTO_FROM_MEM, is added.
Co-developed-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com>
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
[With code change and revise commit message]
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
include/linux/module.h | 2 +
include/uapi/linux/module.h | 5 ++
kernel/module/main.c | 100 +++++++++++++++++++++++++-----------
kernel/params.c | 3 +-
4 files changed, 79 insertions(+), 31 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index 20ddfd97630d..22a1d8459ce4 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -589,6 +589,8 @@ struct module {
#ifdef CONFIG_MODULES
+extern int load_crypto_module_mem(const char *mem, size_t size);
+
/* Get/put a kernel symbol (calls must be symmetric) */
void *__symbol_get(const char *symbol);
void *__symbol_get_gpl(const char *symbol);
diff --git a/include/uapi/linux/module.h b/include/uapi/linux/module.h
index 03a33ffffcba..30e9a7813eac 100644
--- a/include/uapi/linux/module.h
+++ b/include/uapi/linux/module.h
@@ -7,4 +7,9 @@
#define MODULE_INIT_IGNORE_VERMAGIC 2
#define MODULE_INIT_COMPRESSED_FILE 4
+#ifdef __KERNEL__
+/* Internal flags */
+#define MODULE_INIT_CRYPTO_FROM_MEM 30
+#endif
+
#endif /* _UAPI_LINUX_MODULE_H */
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 710ee30b3bea..2914e7619766 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2572,11 +2572,14 @@ static void module_augment_kernel_taints(struct module *mod, struct load_info *i
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
{
- const char *modmagic = get_modinfo(info, "vermagic");
+ const char *modmagic = NULL;
int err;
- if (flags & MODULE_INIT_IGNORE_VERMAGIC)
- modmagic = NULL;
+ if (flags & MODULE_INIT_CRYPTO_FROM_MEM)
+ return 0;
+
+ if (!(flags & MODULE_INIT_IGNORE_VERMAGIC))
+ modmagic = get_modinfo(info, "vermagic");
/* This is allowed: modprobe --force will invalidate it. */
if (!modmagic) {
@@ -3007,7 +3010,7 @@ module_param(async_probe, bool, 0644);
* Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb
* helper command 'lx-symbols'.
*/
-static noinline int do_init_module(struct module *mod)
+static noinline int do_init_module(struct module *mod, int flags)
{
int ret = 0;
struct mod_initfree *freeinit;
@@ -3070,8 +3073,10 @@ static noinline int do_init_module(struct module *mod)
ftrace_free_mem(mod, mod->mem[MOD_INIT_TEXT].base,
mod->mem[MOD_INIT_TEXT].base + mod->mem[MOD_INIT_TEXT].size);
mutex_lock(&module_mutex);
- /* Drop initial reference. */
- module_put(mod);
+ /* Drop initial reference for normal modules to allow unloading.
+ * Keep reference for MODULE_INIT_CRYPTO_FROM_MEM modules to prevent unloading. */
+ if (!(flags & MODULE_INIT_CRYPTO_FROM_MEM))
+ module_put(mod);
trim_init_extable(mod);
#ifdef CONFIG_KALLSYMS
/* Switch to core kallsyms now init is done: kallsyms may be walking! */
@@ -3347,31 +3352,17 @@ static int early_mod_check(struct load_info *info, int flags)
/*
* Allocate and load the module: note that size of section 0 is always
* zero, and we rely on this for optional sections.
+ *
+ * NOTE: module signature verification must have been done already.
*/
-static int load_module(struct load_info *info, const char __user *uargs,
- int flags)
+static int _load_module(struct load_info *info, const char __user *uargs,
+ int flags)
{
struct module *mod;
bool module_allocated = false;
long err = 0;
char *after_dashes;
- /*
- * Do the signature check (if any) first. All that
- * the signature check needs is info->len, it does
- * not need any of the section info. That can be
- * set up later. This will minimize the chances
- * of a corrupt module causing problems before
- * we even get to the signature check.
- *
- * The check will also adjust info->len by stripping
- * off the sig length at the end of the module, making
- * checks against info->len more correct.
- */
- err = module_sig_check(info, flags);
- if (err)
- goto free_copy;
-
/*
* Do basic sanity checks against the ELF header and
* sections. Cache useful sections and set the
@@ -3405,7 +3396,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
* We are tainting your kernel if your module gets into
* the modules linked list somehow.
*/
- module_augment_kernel_taints(mod, info);
+ if (!(flags & MODULE_INIT_CRYPTO_FROM_MEM))
+ module_augment_kernel_taints(mod, info);
/* To avoid stressing percpu allocator, do this once we're unique. */
err = percpu_modalloc(mod, info);
@@ -3452,7 +3444,11 @@ static int load_module(struct load_info *info, const char __user *uargs,
flush_module_icache(mod);
/* Now copy in args */
- mod->args = strndup_user(uargs, ~0UL >> 1);
+ if ((flags & MODULE_INIT_CRYPTO_FROM_MEM))
+ mod->args = kstrdup("", GFP_KERNEL);
+ else
+ mod->args = strndup_user(uargs, ~0UL >> 1);
+
if (IS_ERR(mod->args)) {
err = PTR_ERR(mod->args);
goto free_arch_cleanup;
@@ -3500,13 +3496,10 @@ static int load_module(struct load_info *info, const char __user *uargs,
if (codetag_load_module(mod))
goto sysfs_cleanup;
- /* Get rid of temporary copy. */
- free_copy(info, flags);
-
/* Done! */
trace_module_load(mod);
- return do_init_module(mod);
+ return do_init_module(mod, flags);
sysfs_cleanup:
mod_sysfs_teardown(mod);
@@ -3562,7 +3555,54 @@ static int load_module(struct load_info *info, const char __user *uargs,
audit_log_kern_module(info->name ? info->name : "?");
mod_stat_bump_becoming(info, flags);
}
+ return err;
+}
+
+/*
+ * Load crypto module from kernel memory without signature check.
+ */
+int __init load_crypto_module_mem(const char *mem, size_t size)
+{
+ int err;
+ struct load_info info = { };
+
+ if (!mem) {
+ pr_err("load_crypto_module_mem: mem parameter is NULL\n");
+ return -EINVAL;
+ }
+
+ info.sig_ok = true;
+ info.hdr = (Elf_Ehdr *) mem;
+ info.len = size;
+
+ err = _load_module(&info, NULL, MODULE_INIT_CRYPTO_FROM_MEM);
+ return err;
+}
+
+static int load_module(struct load_info *info, const char __user *uargs,
+ int flags)
+{
+ int err;
+
+ /*
+ * Do the signature check (if any) first. All that
+ * the signature check needs is info->len, it does
+ * not need any of the section info. That can be
+ * set up later. This will minimize the chances
+ * of a corrupt module causing problems before
+ * we even get to the signature check.
+ *
+ * The check will also adjust info->len by stripping
+ * off the sig length at the end of the module, making
+ * checks against info->len more correct.
+ */
+ err = module_sig_check(info, flags);
+ if (!err)
+ err = _load_module(info, uargs, flags);
+
+ /* Get rid of temporary copy. */
free_copy(info, flags);
+
return err;
}
diff --git a/kernel/params.c b/kernel/params.c
index 7c2242f64bf0..b0671d752ff1 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -967,7 +967,8 @@ static int __init param_sysfs_init(void)
return 0;
}
-subsys_initcall(param_sysfs_init);
+/* Use arch_initcall instead of subsys_initcall for early module loading */
+arch_initcall(param_sysfs_init);
/*
* param_sysfs_builtin_init - add sysfs version and parameter
--
2.47.3
^ permalink raw reply related
* [PATCH 04/17] build: Add ELF marker for crypto-objs-m modules
From: Jay Wang @ 2026-02-12 2:42 UTC (permalink / raw)
To: Herbert Xu, David S . Miller, linux-crypto
Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>
Previously, crypto-objs-$(CONFIG_*) behavior depends on the config value.
When CONFIG_*=y, crypto is built into fips140.ko. When CONFIG_*=m, crypto
is already built as a separate module (e.g., aes.ko), so previous patches
do not affect such modules.
This patch adds an ELF marker to identify modules built with CONFIG_*=m
so they can be distinguished as part of the CONFIG_CRYPTO_FIPS140_EXTMOD
framework. This gives module loaders a way to tell the module is included
in crypto-objs-m.
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
crypto/fips140/fips140-crypto-module-marker.h | 8 ++++++++
scripts/Makefile.build | 15 +++++++++++++++
2 files changed, 23 insertions(+)
create mode 100644 crypto/fips140/fips140-crypto-module-marker.h
diff --git a/crypto/fips140/fips140-crypto-module-marker.h b/crypto/fips140/fips140-crypto-module-marker.h
new file mode 100644
index 000000000000..eadca087cee2
--- /dev/null
+++ b/crypto/fips140/fips140-crypto-module-marker.h
@@ -0,0 +1,8 @@
+#ifndef _FIPS140_CRYPTO_MODULE_MARKER_H
+#define _FIPS140_CRYPTO_MODULE_MARKER_H
+
+/* Crypto module marker - automatically included for crypto-objs-m modules */
+static const char __fips140_crypto_marker[]
+ __attribute__((section(".fips140_crypto_marker"), used)) = "FIPS140_CRYPTO_OBJS_M";
+
+#endif /* _FIPS140_CRYPTO_MODULE_MARKER_H */
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 018289da4ccd..cb21112472d4 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -68,6 +68,7 @@ obj-m += $(crypto-objs-m)
ifndef CONFIG_CRYPTO_FIPS140_EXTMOD
obj-y += $(crypto-objs-y)
crypto-objs-y :=
+crypto-objs-m := $(filter-out $(crypto-objs-y),$(crypto-objs-m))
endif
# When an object is listed to be built compiled-in and modular,
@@ -130,6 +131,7 @@ multi-obj-m := $(call multi-search, $(obj-m), .o, -objs -y -m)
multi-obj-ym := $(multi-obj-y) $(multi-obj-m)
ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
multi-crypto-objs-y := $(call multi-search, $(crypto-objs-y), .o, -objs -y)
+multi-crypto-objs-m := $(call multi-search, $(crypto-objs-m), .o, -objs -y -m)
endif
# Replace multi-part objects by their individual parts,
@@ -138,6 +140,7 @@ real-obj-y := $(call real-search, $(obj-y), .o, -objs -y)
real-obj-m := $(call real-search, $(obj-m), .o, -objs -y -m)
ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
real-crypto-objs-y := $(strip $(call real-search, $(crypto-objs-y), .o, -objs -y))
+real-crypto-objs-m := $(strip $(call real-search, $(crypto-objs-m), .o, -objs -y -m))
endif
always-y += $(always-m)
@@ -165,11 +168,13 @@ real-obj-y := $(addprefix $(obj)/, $(real-obj-y))
real-obj-m := $(addprefix $(obj)/, $(real-obj-m))
ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
real-crypto-objs-y := $(addprefix $(obj)/, $(real-crypto-objs-y))
+real-crypto-objs-m := $(addprefix $(obj)/, $(real-crypto-objs-m))
endif
multi-obj-m := $(addprefix $(obj)/, $(multi-obj-m))
subdir-ym := $(addprefix $(obj)/, $(subdir-ym))
ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
multi-crypto-objs-y := $(addprefix $(obj)/, $(multi-crypto-objs-y))
+multi-crypto-objs-m := $(addprefix $(obj)/, $(multi-crypto-objs-m))
endif
endif
@@ -575,6 +580,16 @@ $(multi-crypto-objs-y): %.o: %.mod FORCE
$(call multi_depend, $(multi-crypto-objs-y), .o, -objs -y -m)
endif
endif
+
+# Individual object compilation with version-specific flags
+$(real-crypto-objs-m): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1 -include $(srctree)/crypto/fips140/fips140-crypto-module-marker.h
+
+# Also set flags for individual objects that make up composite crypto objects
+$(foreach obj,$(multi-crypto-objs-m),$($(obj:.o=-y))): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1
+$(foreach obj,$(multi-crypto-objs-m),$($(obj:.o=-objs))): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1
+
+# Multi-part crypto objects
+$(multi-crypto-objs-m): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1 -include $(srctree)/crypto/fips140/fips140-crypto-module-marker.h
endif
# This is a list of build artifacts from the current Makefile and its
# sub-directories. The timestamp should be updated when any of the member files.
--
2.47.3
^ permalink raw reply related
* [PATCH 03/17] build: special compilation rule for building the standalone crypto module
From: Jay Wang @ 2026-02-12 2:42 UTC (permalink / raw)
To: Herbert Xu, David S . Miller, linux-crypto
Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>
Add special build rules to redirect builtin crypto algorithms into a
standalone module `fips140.ko` instead of the main kernel, by introducing
a new crypto-objs-y compilation rule that collects crypto objects to
fips140.ko when CONFIG_CRYPTO_FIPS140_EXTMOD is enabled. Details as below:
Originally, builtin crypto (i.e., which specified by
CONFIG_CRYPTO_{NAME}=y) are compiled into main kernel by default. On the
contrary, this standalone crypto module feature requires compiling builtin
crypto into modules while ensuring such cryptos are not included into main
kernel anymore.
A naive way is to have a separate makefile containing all compilation
rules for all cryptos for such standalone module, but such makefile could
be too large to be scalable to arbitrary CONFIG_CRYPTO_{NAME}
configuration, plus, this method cannot ensure the builtin crypto is
completely removed from main kernel either.
To tackle this challenge, this patch automates object linking redirection by
introducing special build logic for kernel crypto subsystem. Specifically:
First, to automatically collect crypto objects file while preserving the
original compilation setting (such as flags, headers, path etc), it
introduces a specific compilation rule `crypto-objs-y += *.o` that replaces
the original rule `obj-y += *.o` in the crypto subsystem Makefile. As a
result, when the standalone crypto module feature is turned on, for any
crypto chosen to be builtin (e.g., crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2)
+= *.o where CONFIG_CRYPTO_SKCIPHER2=y), it will be automatically collected
and linked into a final object binary: `fips140.o`, with special
compilation flag (-DFIPS_MODULE=1) to tell each individual obj files
compiled in a specific way (will be used in later patches for generating
pluggable interface on main kernel side and module side respectively from
same source code). The implementation details are: it refers to the
methodology of how obj-y collecting method of vmlinux.o, it places the
`crypto-objs-y` rule in scripts/Makefile.build that will be run in each
directory Makefile, and create crypto-module.a that comprises all captured
`crypto-objs-y += *.o` under same folders. In its parent folders, such
crypto-module.a will be included into parents' crypto-module.a recursively
and eventually used to generate final fips140.o.
Second, to generate the final kernel module fips140.ko with the above
fips140.o, A naïve approach would be to directly inject the fips140.ko
module build into the existing modules generation pipeline (i.e., `make
modules`) by providing our pre-generated fips140.o. However, we choose
not to do this because it would create a circular make rule dependency
(which is invalid in Makefiles and causes build failures), resulting in
mutual dependencies between the modules and vmlinux targets (i.e.,
`modules:vmlinux` and `vmlinux:modules` at the same time).
This happens for the following reasons:
1. Since we will later embed fips140.ko into the final kernel image (as
described in the later patch), we must make vmlinux depend on
fips140.ko. In other words: vmlinux: fips140.ko.
2. When the kernel is built with CONFIG_DEBUG_INFO_BTF_MODULES=y, it
requires: `modules: vmlinux`. This is because
`CONFIG_DEBUG_INFO_BTF_MODULES=y` will take vmlinux as input to
generate a `BTF` info for the module, and insert such info into the
`.ko` module by default.
3. If we choose to inject fips140.ko into make modules, this would
create a make rule dependency: `fips140.ko: modules`. Combined with
items 1 and 2, this eventually creates an invalid circular dependency
between vmlinux and modules.
Due to these reasons, the design choice is to use a separate make
pipeline (defined as `fips140-ready` in the Makefile). This new
pipeline reuses the same module generation scripts used by make
modules but adds additional logic in
scripts/Makefile.{modfinal|modinst|modpost} and scripts/mod/modpost.c
to handle module symbol generation and verification correctly. In such
pipeline, to eliminate the make rule dependency of
`fips140.ko:vmlinux` which imposed by `CONFIG_DEBUG_INFO_BTF_MODULES=y`,
we temporarily not generating BTF info for fips140.ko in this patch,
where the BTF info for fips140.ko will be generated in later patch in
a special manner.
Finally, with these special build rules, crypto/fips140/fips140.ko is generated.
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
Makefile | 34 +++++++++++-
crypto/fips140/Makefile | 4 +-
scripts/Makefile.build | 108 +++++++++++++++++++++++++++++++++++++-
scripts/Makefile.modfinal | 21 ++++++++
scripts/Makefile.modinst | 13 ++++-
scripts/Makefile.modpost | 25 +++++++++
scripts/mod/modpost.c | 24 +++++++--
7 files changed, 221 insertions(+), 8 deletions(-)
diff --git a/Makefile b/Makefile
index 832992a7b4fc..b5ae385ed5f3 100644
--- a/Makefile
+++ b/Makefile
@@ -1291,6 +1291,38 @@ PHONY += vmlinux
# vmlinux: private export LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
vmlinux: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
vmlinux: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+vmlinux: fips140-ready
+# Ensure fips140.ko is built before embedding
+fips140-ready: crypto/fips140/fips140.o crypto/fips140/.fips140.order crypto/fips140/fips140.mod vmlinux.o | modules_prepare
+ $(Q)$(MAKE) KBUILD_MODULES= -f $(srctree)/scripts/Makefile.modpost
+ $(Q)$(MAKE) KBUILD_MODULES=y crypto-module-gen=1 -f $(srctree)/scripts/Makefile.modpost
+ifneq ($(KBUILD_MODPOST_NOFINAL),1)
+ $(Q)$(MAKE) KBUILD_MODULES=y crypto-module-gen=1 -f $(srctree)/scripts/Makefile.modfinal
+endif
+ @:
+
+# Generate fips140.o from crypto-module.a files
+crypto/fips140/fips140.o: crypto-module.a FORCE
+ $(call if_changed,ld_fips140)
+crypto/fips140/.fips140.order: crypto/fips140/fips140.o
+ echo "crypto/fips140/fips140.o" > $@
+crypto/fips140/fips140.mod: crypto-module.a FORCE
+ $(call if_changed,fips140_mod)
+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_fips140_mod = ar -t $< > $@
+
+# Add to targets so .cmd file is included
+targets += crypto/fips140/fips140.o crypto/fips140/fips140.mod
+
+# Bridge rule: crypto-module.a depends on directory build (like built-in.a)
+crypto-module.a: . ;
+endif
vmlinux: vmlinux.o $(KBUILD_LDS) modpost
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vmlinux
@@ -2083,7 +2115,7 @@ prepare: outputmakefile
# Error messages still appears in the original language
PHONY += $(build-dir)
$(build-dir): prepare
- $(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1 $(single-goals)
+ $(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1 need-crypto=1 $(single-goals)
clean-dirs := $(addprefix _clean_, $(clean-dirs))
PHONY += $(clean-dirs) clean
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
index 364ef52c190f..3b4a74ccf41e 100644
--- a/crypto/fips140/Makefile
+++ b/crypto/fips140/Makefile
@@ -1,3 +1,5 @@
+crypto-objs-y += \
+ fips140-module.o
-
\ No newline at end of file
+clean-files:= .fips140.order .fips140.symvers
\ No newline at end of file
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 32e209bc7985..018289da4ccd 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -29,6 +29,21 @@ ldflags-y :=
subdir-asflags-y :=
subdir-ccflags-y :=
+crypto-objs-flags-y := -DFIPS_MODULE=1
+crypto-objs-y :=
+crypto-module-folders := $(srcroot)/crypto $(srcroot)/arch/$(ARCH)/crypto $(srcroot)/lib/crypto
+# Global crypto directory checking logic
+define is-crypto-related-dir
+$(eval full-path := $(abspath $(obj)/$(1)))
+$(eval norm-folders := $(foreach dir,$(crypto-module-folders),$(abspath $(dir))))
+$(eval check-exact := $(filter $(norm-folders),$(full-path)))
+$(eval check-subdir := $(foreach dir,$(norm-folders),$(filter $(dir)/%,$(full-path))))
+$(eval check-ancestor := $(foreach dir,$(norm-folders),$(if $(filter $(full-path)/%,$(dir)),$(full-path))))
+$(eval result := $(strip $(check-exact) $(check-subdir) $(check-ancestor)))
+$(result)
+endef
+is-crypto-related := $(call is-crypto-related-dir, ./)
+
# Read auto.conf if it exists, otherwise ignore
-include $(objtree)/include/config/auto.conf
@@ -45,6 +60,16 @@ KBUILD_RUSTFLAGS += $(subdir-rustflags-y)
# Figure out what we need to build from the various variables
# ===========================================================================
+
+# Add crypto-objs-m to obj-m unconditionally
+obj-m += $(crypto-objs-m)
+
+# When CRYPTO_FIPS140_EXTMOD is not defined, add crypto-objs-y to obj-y and clear crypto-objs-y
+ifndef CONFIG_CRYPTO_FIPS140_EXTMOD
+obj-y += $(crypto-objs-y)
+crypto-objs-y :=
+endif
+
# When an object is listed to be built compiled-in and modular,
# only build the compiled-in version
obj-m := $(filter-out $(obj-y),$(obj-m))
@@ -71,12 +96,27 @@ else
obj-m := $(filter-out %/, $(obj-m))
endif
+# Capture obj-y directories before conversion
+obj-y-dirs := $(filter %/, $(obj-y))
+
ifdef need-builtin
obj-y := $(patsubst %/, %/built-in.a, $(obj-y))
else
obj-y := $(filter-out %/, $(obj-y))
endif
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+# Add obj-y directories to crypto-objs-y only if they are crypto-related
+crypto-objs-y += $(strip $(foreach dir,$(obj-y-dirs),$(if $(strip $(call is-crypto-related-dir,$(patsubst %/,%,$(dir)))),$(dir))))
+
+ifdef need-crypto
+crypto-objs-y := $(patsubst %/, %/crypto-module.a, $(crypto-objs-y))
+else
+crypto-objs-y := $(filter-out %/, $(crypto-objs-y))
+endif
+endif
+
+
# Expand $(foo-objs) $(foo-y) etc. by replacing their individuals
suffix-search = $(strip $(foreach s, $3, $($(1:%$(strip $2)=%$s))))
# List composite targets that are constructed by combining other targets
@@ -88,11 +128,17 @@ real-search = $(foreach m, $1, $(if $(call suffix-search, $m, $2, $3 -), $(call
multi-obj-y := $(call multi-search, $(obj-y), .o, -objs -y)
multi-obj-m := $(call multi-search, $(obj-m), .o, -objs -y -m)
multi-obj-ym := $(multi-obj-y) $(multi-obj-m)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+multi-crypto-objs-y := $(call multi-search, $(crypto-objs-y), .o, -objs -y)
+endif
# Replace multi-part objects by their individual parts,
# including built-in.a from subdirectories
real-obj-y := $(call real-search, $(obj-y), .o, -objs -y)
real-obj-m := $(call real-search, $(obj-m), .o, -objs -y -m)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+real-crypto-objs-y := $(strip $(call real-search, $(crypto-objs-y), .o, -objs -y))
+endif
always-y += $(always-m)
@@ -117,8 +163,14 @@ obj-m := $(addprefix $(obj)/, $(obj-m))
lib-y := $(addprefix $(obj)/, $(lib-y))
real-obj-y := $(addprefix $(obj)/, $(real-obj-y))
real-obj-m := $(addprefix $(obj)/, $(real-obj-m))
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+real-crypto-objs-y := $(addprefix $(obj)/, $(real-crypto-objs-y))
+endif
multi-obj-m := $(addprefix $(obj)/, $(multi-obj-m))
subdir-ym := $(addprefix $(obj)/, $(subdir-ym))
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+multi-crypto-objs-y := $(addprefix $(obj)/, $(multi-crypto-objs-y))
+endif
endif
ifndef obj
@@ -137,7 +189,9 @@ endif
# subdir-builtin and subdir-modorder may contain duplications. Use $(sort ...)
subdir-builtin := $(sort $(filter %/built-in.a, $(real-obj-y)))
subdir-modorder := $(sort $(filter %/modules.order, $(obj-m)))
-
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+subdir-crypto := $(sort $(filter %/crypto-module.a, $(real-crypto-objs-y)))
+endif
targets-for-builtin := $(extra-y)
ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
@@ -148,6 +202,16 @@ ifdef need-builtin
targets-for-builtin += $(obj)/built-in.a
endif
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+targets-for-crypto :=
+ifneq ($(is-crypto-related),)
+ifdef need-crypto
+targets-for-crypto += $(obj)/crypto-module.a
+endif
+targets += $(obj)/crypto-module.a
+endif
+endif
+
targets-for-modules := $(foreach x, o mod, \
$(patsubst %.o, %.$x, $(filter %.o, $(obj-m))))
@@ -222,6 +286,12 @@ $(obj)/%.ll: $(obj)/%.c FORCE
is-single-obj-m = $(and $(part-of-module),$(filter $@, $(obj-m)),y)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+is-single-crypto-obj-y = $(and $(part-of-module),$(filter $@, $(real-crypto-objs-y)),y)
+else
+is-single-crypto-obj-y =
+endif
+
ifdef CONFIG_MODVERSIONS
# When module versioning is enabled the following steps are executed:
# o compile a <file>.o from <file>.c
@@ -277,7 +347,7 @@ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(target-stem).o)$(OBJECT_FILES_NON_STANDARD)n),$(is-kernel-object))
ifdef CONFIG_OBJTOOL
-$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
+$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(or $(is-single-obj-m),$(is-single-crypto-obj-y)),y))
endif
ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
@@ -433,6 +503,9 @@ $(obj)/%.o: $(obj)/%.S FORCE
targets += $(filter-out $(subdir-builtin), $(real-obj-y))
targets += $(filter-out $(subdir-modorder), $(real-obj-m))
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+targets += $(filter-out $(subdir-crypto), $(real-crypto-objs-y))
+endif
targets += $(lib-y) $(always-y)
# Linker scripts preprocessor (.lds.S -> .lds)
@@ -459,6 +532,9 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
# To build objects in subdirs, we need to descend into the directories
$(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
$(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+$(subdir-crypto): $(obj)/%/crypto-module.a: $(obj)/% ;
+endif
#
# Rule to compile a set of .o files into one .a file (without symbol table)
@@ -474,6 +550,32 @@ quiet_cmd_ar_builtin = AR $@
$(obj)/built-in.a: $(real-obj-y) FORCE
$(call if_changed,ar_builtin)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifneq ($(is-crypto-related),)
+$(obj)/crypto-module.a: $(real-crypto-objs-y) FORCE
+ $(call if_changed,ar_builtin)
+
+# Set module flags for crypto objects when building crypto-module.a
+ifdef need-crypto
+$(real-crypto-objs-y): private part-of-module := y
+$(real-crypto-objs-y): private modname := fips140
+$(real-crypto-objs-y): private KBUILD_CFLAGS += $(crypto-objs-flags-y)
+
+# Also set flags for individual objects that make up composite crypto objects
+$(foreach obj,$(multi-crypto-objs-y),$($(obj:.o=-y))): private part-of-module := y
+$(foreach obj,$(multi-crypto-objs-y),$($(obj:.o=-y))): private modname := fips140
+$(foreach obj,$(multi-crypto-objs-y),$($(obj:.o=-y))): private KBUILD_CFLAGS += $(crypto-objs-flags-y)
+
+# Multi-part crypto objects
+$(multi-crypto-objs-y): private part-of-module := y
+$(multi-crypto-objs-y): private modname := fips140
+$(multi-crypto-objs-y): private KBUILD_CFLAGS += $(crypto-objs-flags-y)
+$(multi-crypto-objs-y): %.o: %.mod FORCE
+ $(call if_changed_rule,ld_multi_m)
+$(call multi_depend, $(multi-crypto-objs-y), .o, -objs -y -m)
+endif
+endif
+endif
# This is a list of build artifacts from the current Makefile and its
# sub-directories. The timestamp should be updated when any of the member files.
@@ -546,6 +648,7 @@ $(subdir-ym):
$(Q)$(MAKE) $(build)=$@ \
need-builtin=$(if $(filter $@/built-in.a, $(subdir-builtin)),1) \
need-modorder=$(if $(filter $@/modules.order, $(subdir-modorder)),1) \
+ need-crypto=$(if $(and $(CONFIG_CRYPTO_FIPS140_EXTMOD), $(filter $@/crypto-module.a, $(subdir-crypto))),1) \
$(filter $@/%, $(single-subdir-goals))
# Add FORCE to the prerequisites of a target to force it to be always rebuilt.
@@ -569,6 +672,7 @@ endif
$(obj)/: $(if $(KBUILD_BUILTIN), $(targets-for-builtin)) \
$(if $(KBUILD_MODULES), $(targets-for-modules)) \
+ $(targets-for-crypto) \
$(subdir-ym) $(always-y)
@:
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index adcbcde16a07..c68dab4d6584 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -11,7 +11,15 @@ include $(srctree)/scripts/Kbuild.include
include $(srctree)/scripts/Makefile.lib
# find all modules listed in modules.order
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(crypto-module-gen),1)
+modules := $(call read-file, crypto/fips140/.fips140.order)
+else
modules := $(call read-file, modules.order)
+endif
+else
+modules := $(call read-file, modules.order)
+endif
__modfinal: $(modules:%.o=%.ko)
@:
@@ -55,12 +63,25 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
# Re-generate module BTFs if either module's .ko or vmlinux changed
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(crypto-module-gen),1)
+%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds FORCE
+ +$(call if_changed,ld_ko_o)
+else
+%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
+ +$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
+ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+ +$(if $(newer-prereqs),$(call cmd,btf_ko))
+endif
+endif
+else
%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
+$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko))
endif
+$(call cmd,check_tracepoint)
+endif
targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 9ba45e5b32b1..32b6d0986922 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -28,7 +28,12 @@ $(MODLIB)/modules.order: modules.order FORCE
$(call cmd,install_modorder)
quiet_cmd_install_modorder = INSTALL $@
- cmd_install_modorder = sed 's:^\(.*\)\.o$$:kernel/\1.ko:' $< > $@
+ cmd_install_modorder = sed 's:^\(.*\)\.o$$:kernel/\1.ko:' $< > $@; \
+ $(if $(CONFIG_CRYPTO_FIPS140_EXTMOD), \
+ if [ -f crypto/fips140/.fips140.order ]; then \
+ sed 's:^\(.*\)\.o$$:kernel/\1.ko:' crypto/fips140/.fips140.order >> $@; \
+ fi \
+ )
# Install modules.builtin(.modinfo,.ranges) even when CONFIG_MODULES is disabled.
install-y += $(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo)
@@ -42,6 +47,12 @@ endif
modules := $(call read-file, modules.order)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifneq ($(wildcard crypto/fips140/.fips140.order),)
+modules += $(call read-file, crypto/fips140/.fips140.order)
+endif
+endif
+
ifeq ($(KBUILD_EXTMOD),)
dst := $(MODLIB)/kernel
else
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index d7d45067d08b..18b5a5de74d9 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -51,6 +51,7 @@ modpost-args = \
$(if $(KBUILD_NSDEPS),-d modules.nsdeps) \
$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \
$(if $(findstring 1, $(KBUILD_EXTRA_WARN)),-W) \
+ $(if $(crypto-module-gen),-c) \
-o $@
modpost-deps := $(MODPOST)
@@ -63,10 +64,22 @@ endif
# Read out modules.order to pass in modpost.
# Otherwise, allmodconfig would fail with "Argument list too long".
ifdef KBUILD_MODULES
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(crypto-module-gen),1)
+# For crypto-module-gen, use .fips140.order instead of modules.order
+modpost-args += -T crypto/fips140/.fips140.order
+modpost-deps += crypto/fips140/.fips140.order
+else
+modpost-args += -T modules.order
+modpost-deps += modules.order
+endif
+else
modpost-args += -T modules.order
modpost-deps += modules.order
endif
+endif
+
ifeq ($(KBUILD_EXTMOD),)
# Generate the list of in-tree objects in vmlinux
@@ -110,6 +123,18 @@ modpost-deps += vmlinux.o
output-symdump := $(if $(KBUILD_MODULES), Module.symvers, vmlinux.symvers)
endif
+# Include .fips140.symvers for regular module builds if it exists
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(KBUILD_MODULES),y)
+ifneq ($(crypto-module-gen),1)
+ifneq ($(wildcard crypto/fips140/.fips140.symvers),)
+modpost-args += -i crypto/fips140/.fips140.symvers
+modpost-deps += crypto/fips140/.fips140.symvers
+endif
+endif
+endif
+endif
+
else
# set src + obj - they may be used in the modules's Makefile
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 0c25b5ad497b..63f123f077e8 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -43,6 +43,8 @@ static bool extended_modversions;
static bool external_module;
/* Only warn about unresolved symbols */
static bool warn_unresolved;
+/* Crypto module generation mode */
+static bool crypto_module_gen;
static int sec_mismatch_count;
static bool sec_mismatch_warn_only = true;
@@ -1746,6 +1748,9 @@ static void check_exports(struct module *mod)
const char *basename;
exp = find_symbol(s->name);
if (!exp) {
+ /* Skip undefined symbol errors for crypto module generation */
+ if (crypto_module_gen)
+ continue;
if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS)
modpost_log(!warn_unresolved,
"\"%s\" [%s.ko] undefined!\n",
@@ -2202,10 +2207,14 @@ static void write_dump(const char *fname)
struct buffer buf = { };
struct module *mod;
struct symbol *sym;
+ bool is_fips_symvers = crypto_module_gen && (strcmp(fname, "crypto/fips140/.fips140.symvers") == 0);
list_for_each_entry(mod, &modules, list) {
if (mod->dump_file)
continue;
+ /* Skip vmlinux symbols when writing .fips140.symvers */
+ if (is_fips_symvers && mod->is_vmlinux)
+ continue;
list_for_each_entry(sym, &mod->exported_symbols, list) {
if (trim_unused_exports && !sym->used)
continue;
@@ -2277,7 +2286,7 @@ int main(int argc, char **argv)
LIST_HEAD(dump_lists);
struct dump_list *dl, *dl2;
- while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:xb")) != -1) {
+ while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:xbc")) != -1) {
switch (opt) {
case 'e':
external_module = true;
@@ -2332,6 +2341,9 @@ int main(int argc, char **argv)
case 'x':
extended_modversions = true;
break;
+ case 'c':
+ crypto_module_gen = true;
+ break;
default:
exit(1);
}
@@ -2377,8 +2389,14 @@ int main(int argc, char **argv)
if (missing_namespace_deps)
write_namespace_deps_files(missing_namespace_deps);
- if (dump_write)
- write_dump(dump_write);
+ if (dump_write) {
+ if (crypto_module_gen) {
+ /* generate .fips140.symvers for FIPS crypto modules */
+ write_dump("crypto/fips140/.fips140.symvers");
+ }else {
+ write_dump(dump_write);
+ }
+ }
if (sec_mismatch_count && !sec_mismatch_warn_only)
error("Section mismatches detected.\n"
"Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
--
2.47.3
^ permalink raw reply related
* [PATCH 02/17] crypto: add module entry for standalone crypto kernel module
From: Jay Wang @ 2026-02-12 2:42 UTC (permalink / raw)
To: Herbert Xu, David S . Miller, linux-crypto
Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>
Add the module entry for the standalone FIPS kernel crypto module.
This creates the basic structure for fips140.ko that will be linked
with built-in crypto implementations in later patches.
The implementation includes module initialization and exit functions
and add into build system.
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
crypto/Makefile | 5 +++++
crypto/fips140/Makefile | 3 +++
crypto/fips140/fips140-module.c | 36 +++++++++++++++++++++++++++++++++
crypto/fips140/fips140-module.h | 14 +++++++++++++
4 files changed, 58 insertions(+)
create mode 100644 crypto/fips140/Makefile
create mode 100644 crypto/fips140/fips140-module.c
create mode 100644 crypto/fips140/fips140-module.h
diff --git a/crypto/Makefile b/crypto/Makefile
index 04e269117589..5129be5e7208 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -210,3 +210,8 @@ obj-$(CONFIG_CRYPTO_KDF800108_CTR) += kdf_sp800108.o
obj-$(CONFIG_CRYPTO_DF80090A) += df_sp80090a.o
obj-$(CONFIG_CRYPTO_KRB5) += krb5/
+
+# FIPS 140 kernel module
+obj-$(CONFIG_CRYPTO_FIPS140_EXTMOD) += fips140/
+
+
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
new file mode 100644
index 000000000000..364ef52c190f
--- /dev/null
+++ b/crypto/fips140/Makefile
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/crypto/fips140/fips140-module.c b/crypto/fips140/fips140-module.c
new file mode 100644
index 000000000000..a942de8780ef
--- /dev/null
+++ b/crypto/fips140/fips140-module.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * FIPS 140 Kernel Cryptographic Module
+ *
+ * This file is the module entry point for fips140.ko, which is linked with previously built-in cryptos
+ * to generate the fips140.ko module.
+ * At load time, this module plugs the previously built-in implementations contained within itself back to the kernel.
+ * It also runs self-tests on these algorithms and verifies the integrity of its code and data.
+ * If either of these steps fails, the kernel will panic.
+ */
+
+#include "fips140-module.h"
+
+#define FIPS140_MODULE_NAME "FIPS 140 Kernel Cryptographic Module"
+#define FIPS140_MODULE_VERSION "1.0.0"
+
+#define CRYPTO_INTERNAL "CRYPTO_INTERNAL"
+
+/* Initialize the FIPS 140 module */
+static int __init fips140_init(void)
+{
+ return 0;
+}
+
+static void __exit fips140_exit(void)
+{
+ pr_info("Unloading " FIPS140_MODULE_NAME "\n");
+}
+
+module_init(fips140_init);
+module_exit(fips140_exit);
+
+MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(FIPS140_MODULE_NAME);
+MODULE_VERSION(FIPS140_MODULE_VERSION);
diff --git a/crypto/fips140/fips140-module.h b/crypto/fips140/fips140-module.h
new file mode 100644
index 000000000000..ed2b6e17969f
--- /dev/null
+++ b/crypto/fips140/fips140-module.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * FIPS 140 Kernel Cryptographic Module - Header File
+ */
+
+#ifndef _CRYPTO_FIPS140_MODULE_H
+#define _CRYPTO_FIPS140_MODULE_H
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <linux/init.h>
+
+#endif /* _CRYPTO_FIPS140_MODULE_H */
--
2.47.3
^ permalink raw reply related
* [PATCH 01/17] crypto: add Kconfig options for standalone crypto module
From: Jay Wang @ 2026-02-12 2:42 UTC (permalink / raw)
To: Herbert Xu, David S . Miller, linux-crypto
Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
linux-modules
In-Reply-To: <20260212024228.6267-1-wanjay@amazon.com>
Add Kconfig option `CRYPTO_FIPS140_EXTMOD` to enable standalone crypto
module support that can override built-in cryptographic implementations.
Currently supports X86_64 and ARM64 architectures and requires CRYPTO
and MODULES to be enabled.
Signed-off-by: Jay Wang <wanjay@amazon.com>
---
crypto/Kconfig | 1 +
crypto/fips140/Kconfig | 15 +++++++++++++++
2 files changed, 16 insertions(+)
create mode 100644 crypto/fips140/Kconfig
diff --git a/crypto/Kconfig b/crypto/Kconfig
index e2b4106ac961..b4ce3c1cfa1b 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1415,6 +1415,7 @@ endif
endif
source "drivers/crypto/Kconfig"
+source "crypto/fips140/Kconfig"
source "crypto/asymmetric_keys/Kconfig"
source "certs/Kconfig"
source "crypto/krb5/Kconfig"
diff --git a/crypto/fips140/Kconfig b/crypto/fips140/Kconfig
new file mode 100644
index 000000000000..0665e94b9fe0
--- /dev/null
+++ b/crypto/fips140/Kconfig
@@ -0,0 +1,15 @@
+config CRYPTO_FIPS140_EXTMOD
+ bool "FIPS 140 compliant algorithms as a kernel module"
+ depends on CRYPTO && (X86_64 || ARM64) && MODULES
+ select CRYPTO_FIPS
+ help
+ This option enables building a kernel module that contains
+ copies of crypto algorithms that are built in a way that
+ complies with the FIPS 140 standard.
+
+ The module registers the algorithms it contains with the
+ kernel crypto API, and the kernel crypto API's FIPS 140 mode
+ can be enabled to restrict crypto algorithm usage to only
+ those provided by this module.
+
+ If unsure, say N.
--
2.47.3
^ permalink raw reply related
* [PATCH v1 00/17] crypto: Standalone crypto module (Series 1/4): Core implementation
From: Jay Wang @ 2026-02-12 2:42 UTC (permalink / raw)
To: Herbert Xu, David S . Miller, linux-crypto
Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Luis Chamberlain, Petr Pavlu, Nathan Chancellor,
Nicolas Schier, linux-arm-kernel, x86, linux-kbuild,
linux-modules
This feature is organized into four patch series for submission to the mainline (up to the "Merge tag 'landlock-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux"):
- Patch Series 1/4: "[PATCH v1 0...17] crypto: Standalone crypto module (Series 1/4): Core implementation"
- Patch Series 2/4: "[PATCH v1 0...106] crypto: Standalone crypto module (Series 2/4): Arch-independent crypto"
- Patch Series 3/4: "[PATCH v1 0...21] crypto: Standalone crypto module (Series 3/4): x86_64 crypto"
- Patch Series 4/4: "[PATCH v1 0...12] crypto: Standalone crypto module (Series 4/4): arm64 crypto"
The full source code is available at https://github.com/amazonlinux/linux/tree/fips-kernel-module.
Details on this feature and what each patch series covers can be found below.
## 1. Introduction
Amazon Linux is releasing a new kernel feature that converts the previously built-in kernel crypto subsystem into a standalone kernel module. This module becomes the carrier of the kernel crypto subsystem and can be loaded at early boot to provide the same functionality as the original built-in crypto. The primary motivation for this modularization is to streamline Federal Information Processing Standards (FIPS) validation, a critical cryptographic certification for cloud computing users doing business with the U.S. government.
In a bit more detail, previously, FIPS certification was tied to the entire kernel image, meaning non-crypto updates could potentially invalidate certification. With this feature, FIPS certification is tied only to the crypto module. Therefore, once the module is certified, loading this certified module on newer kernels automatically makes those kernels FIPS-certified. As a result, this approach can save re-certification costs and 12-18 months of waiting time by reducing the need for repeated FIPS re-certification cycles.
This feature is organized into four patch series:
- Patch Series 1 - Core feature implementation
- Patch Series 2 - Architecture-independent crypto: Modularize built-in crypto under `crypto/`
- Patch Series 3 - x86_64 crypto: Modularize built-in crypto under `arch/x86/crypto/`
- Patch Series 4 - arm64 crypto: Modularize built-in crypto under `arch/arm64/crypto/`
This document provides technical details on how this feature is designed and implemented for users or developers who are interested in developing upon it, and is organized as follows:
- Section 2 - Getting Started: Quick start on how to enable the feature
- Section 3 - Workflow Overview: Changes this feature brings to build and runtime
- Section 4 - Design Implementation Details: Technical deep-dive into each component
- Section 5 - Customizing and Extending Crypto Module: How to select crypto to be included and extend to new crypto/architectures
- Section 6 - Related Work and Comparison
- Section 7 - Summary
## 2. Getting Started
This section provides a quick start guide for developers on how to enable, compile and use the standalone cryptography module feature.
### 2.1 Basic Configuration
The feature is controlled by a single configuration option:
```
CONFIG_CRYPTO_FIPS140_EXTMOD=y
```
What it does: When enabled, automatically redirects a set of cryptographic algorithms from the main kernel into a standalone module `crypto/fips140/fips140.ko`. The cryptographic algorithms that are redirected need to satisfy all the following conditions, otherwise the cryptography will remain in its original form:
1. Must be configured as built-in (i.e., `CONFIG_CRYPTO_*=y`). This means cryptography already configured as modular (i.e., `CONFIG_CRYPTO_*=m`) are not redirected as they are already modularized.
2. Must be among a list, which can be customized by developers as described in Section 5.
When disabled, the kernel behaves as before.
### 2.2 Build Process
Once `CONFIG_CRYPTO_FIPS140_EXTMOD=y` is set, no additional steps are required. The standalone module will be built automatically as part of the standard kernel build process:
```
make -j$(nproc)
# or
make vmlinux
```
**What happens automatically (No user action required):**
1. Build the module as `crypto/fips140/fips140.ko`
2. The cryptography module will be loaded at boot time
3. All kernel cryptographic services will provide the same functionality as before (i.e., prior to introducing this new feature) once boot completes.
### 2.3 Advanced Configuration Options
**Using External Cryptography Module:**
```
CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE=y
```
By default, `CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE` is not set, meaning the freshly built cryptography module is used. Otherwise, the pre-built standalone cryptography module from `fips140_build/crypto/fips140/fips140.ko` and modular cryptography such as `fips140_build/crypto/aes.ko` (need to manually place pre-built modules in these locations before the build) are included in kernel packaging (e.g., during `make modules_install`) and are used at later boot time.
**Dual Version Support:**
```
CONFIG_CRYPTO_FIPS140_DUAL_VERSION=y
```
Encapsulate two versions of `fips140.ko` into kernel: one is freshly built for non-FIPS mode usage, another is pre-built specified by `fips140_build/crypto/fips140/fips140.ko` for FIPS mode usage. The appropriate version is selected and loaded at boot time based on boot time FIPS mode status.
### 2.4 Verification
To verify the feature is working, after install and boot with the new kernel:
```
# Check if fips140.ko module is loaded
lsmod | grep fips140
```
## 3. Workflow Overview
This section provides an overview without delving into deep technical details of the changes the standalone cryptography module feature introduces. When this feature is enabled, it introduces changes to both the kernel build and booting process.
3.1 Build-Time Changes
Kernel cryptography subsystem consists of both cryptography management infrastructure (e.g., `crypto/api.c`, `crypto/algapi.c`, etc), along with hundreds of different cryptography algorithms (e.g., `crypto/arc4.c`).
**Traditional Build Process:**
Traditionally, cryptography management infrastructure are always built-in to the kernel, while cryptographic algorithms can be configured to be built either as built-in (`CONFIG_CRYPTO_*=y`) or as separate modular (`CONFIG_CRYPTO_*=m`) `.ko` file depending on kernel configuration:
As a result, the builtin cryptography management infrastructure and cryptographic algorithms are statically linked into the kernel binary:
```
cryptographic algorithms source files → compiled as .o objfiles → linked into vmlinux → single kernel binary
```
**With Standalone Cryptography Module:**
This feature automatically transforms the builtin cryptographic components into a standalone cryptography module, `fips140.ko`. To do so, it develops a new kernel build rule `crypto-objs-$(CONFIG_CRYPTO_*)` such that, once this build rule is applied to a cryptographic algorithm, such cryptographic algorithm will be automatically collected into the cryptography module if it is configured as built-in (i.e, `CONFIG_CRYPTO_*=y`), for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
```
Such build change allows the modularization transformation to only affect selected cryptographic algorithms (i.e, where the `crypto-objs-$(CONFIG_CRYPTO_*`) is applied).
Then, after the `fips140.ko` is generated, it will be embedded back into main kernel vmlinux as a replacement part. The purpose of this embedding, instead of traditionally putting the `fips140.ko` into filesystem, is a preparation to allow the module to be loaded early enough even before the filesystem is ready.
The new build process is illustrated below.
```
cryptographic algorithms source files → compiled as .o objfiles → automatically collected and linked into fips140.ko → embedded fips140.ko into vmlinux as a replaceable binary
```
### 3.2 Runtime Changes
**Traditional Boot Process:**
The kernel initializes the cryptographic subsystem early during boot, executing each cryptographic initialization routine accordingly. These initialization routines may depend on other cryptographic components or other kernel subsystems, so their invocation follows a well-defined execution order to ensure they are initialized before their first use.
```
kernel starts → cryptography subsystem initialization → cryptography subsystem available → other components use cryptography
```
**With Standalone Cryptography Module:**
At the start of kernel boot, compared to a regular kernel, the first major change introduced by this feature is that no cryptography services are initially available — since the entire cryptography subsystem has been decoupled from the main kernel.
To ensure that the cryptography subsystem becomes available early enough (before the first kernel component that requires cryptography services), the standalone cryptography kernel module must be loaded at a very early stage, even before the filesystem becomes available.
However, the regular module loading mechanism relies on placing kernel modules in the filesystem and loading them from there, which creates a chicken-and-egg problem — the cryptography module cannot be loaded until the filesystem is ready, yet some kernel components may require cryptography services even before that point.
To address this, the second change introduced by this feature is that the cryptography kernel module is loaded directly from memory, leveraging the earlier compilation changes that embed the module binary into the main kernel image. Afterward, the feature includes a “plug-in” mechanism that connects the decoupled cryptography subsystem back to the main kernel, ensuring that kernel cryptography users can correctly locate and invoke the cryptography routine entry points.
Finally, to ensure proper initialization, the feature guarantees that all cryptography algorithms and the cryptography management infra execute their initialization routines in the exact same order as they would if they were built-in.
The process described above is illustrated below.
```
kernel starts → no cryptography available → load fips140.ko from memory → plug cryptography back to kernel → module initialization → cryptographic services available → other components use cryptography
```
## 4. Design Implementation Details
While the earlier sections provide a holistic view of how this feature shapes the kernel, this section provides deeper design details on how these functionalities are realized. There are three key design components:
1. A specialized compile rule that automatically compiles and collects all built-in cryptographic algorithm object files to generate the final module binary under arbitrary kernel configurations, and then embeds the generated binary into the main kernel image for early loading.
2. A mechanism to convert interactions between the cryptography subsystem and the main kernel into a pluggable interface.
3. A module loading and initialization process that ensures the cryptography subsystem is properly initialized as if it were built-in.
### 4.1. Specialized Compilation System
**Automatic Collection and Linking of Built-in Cryptographic Algorithm Objects:**
The first step in generating the `fips140.ko` module is to compile and collect built-in cryptographic components (i.e., those specified by `CONFIG_CRYPTO_*=y`).
Traditionally, the existing module build process requires all module components (e.g., source files) to reside in a single directory. However, this approach is not suitable for our case, where hundreds of cryptographic algorithm source files are scattered across multiple directories.
A naïve approach would be to create a separate Makefile that duplicates the original build rules with adjusted paths.
However, this method is not scalable due to the large number of cryptographic build rules, many of which are highly customized and can vary under different Kconfig settings, making such a separate Makefile even more complex.
Moreover, this approach cannot ensure that built-in cryptographic algorithms are completely removed from the main kernel, which would result in redundant cryptographic code being included in both the kernel and the module.
To tackle this challenge, we automated the object collection and linking process by introducing special build logic for the kernel cryptography subsystem.
Specifically, to automatically collect cryptography object files while preserving their original compilation settings (such as flags, headers, and paths), we introduced a new compilation rule:
```
crypto-objs-y += *.o
```
This replaces the original `obj-y += *.o` rule in cryptography Makefiles later, for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \ asymmetric_type.o \ restrict.o \ signature.o
```
in the cryptography subsystem Makefiles, allowing most of the existing Makefile logic to be reused.
As a result, when the standalone cryptography module feature is enabled, any cryptographic algorithm configured as built-in (for example, `crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o` where `CONFIG_ASYMMETRIC_KEY_TYPE=y`) will be automatically collected and linked into a single final object binary, `fips140.o`.
During this process, a special compilation flag (`-DFIPS_MODULE=1`) is applied to instruct each object file to be compiled in a module-specific manner. This flag will later be used to generate the pluggable interface on both the main kernel side and the module side from the same source code.
The implementation details are as follows: it follows a similar methodology used by the `obj-y` collection process for building `vmlinux.o`. The `crypto-objs-y` rule is placed in `scripts/Makefile.build`, which is executed by each directory Makefile to collect the corresponding crypto object files. Each directory then creates a `crypto-module.a` archive that contains all `crypto-objs-y += <object>.o` files under that directory. In the parent directories, these `crypto-module.a` archives are recursively included into the parent’s own `crypto-module.a`, and this process continues upward until the final `fips140.o` is generated.
**A Separate Module Generation Pipeline for Building the Final Kernel Module from Linked Cryptographic Algorithm Object:**
With the linked cryptographic algorithm object (i.e., `fips140.o`), the next step is to generate the final kernel module, `fips140.ko`.
A direct approach would be to inject the `fips140.ko` module build into the existing modules generation pipeline (i.e., `make modules`) by providing our pre-generated `fips140.o`. However, we choose not to do this because it would create a circular make rule dependency (which is invalid in Makefiles and causes build failures), resulting in mutual dependencies between the modules and vmlinux targets (i.e., `modules:vmlinux` and `vmlinux:modules` at the same time).
This happens for the following reasons:
1. Since we will later embed `fips140.ko` into the final kernel image (as described in the next section), we must make vmlinux depend on `fips140.ko`. In other words: `vmlinux: fips140.ko`.
2. When the kernel is built with `CONFIG_DEBUG_INFO_BTF_MODULES=y`, it requires: modules: vmlinux. This is because `CONFIG_DEBUG_INFO_BTF_MODULES=y` takes vmlinux as input to generate BTF info for the module, and inserts such info into the `.ko` module by default.
3. If we choose to inject `fips140.ko` into make modules, this would create a make rule dependency: `fips140.ko: modules`. Combined with items 1 and 2, this eventually creates an invalid circular dependency between vmlinux and modules.
Due to these reasons, the design choice is to use a separate make pipeline (defined as `fips140-ready` in the Makefile). This new pipeline reuses the same module generation scripts used by make modules but adds additional logic in `scripts/Makefile.{modfinal|modinst|modpost}` and `scripts/mod/modpost.c` to handle module symbol generation and verification correctly.
**A Seamless Process That Embeds the Generated Binary Into the Main Kernel Image for Early Loading:**
As mentioned earlier, in order to load the standalone cryptography module early in the boot process—before the filesystem is ready—the module binary must be embedded into the final kernel image (i.e., vmlinux) so that it can be loaded directly from memory.
We intend for this embedding process to be completely seamless and automatically triggered whenever vmlinux is built (i.e., during `make vmlinux`).
To achieve this, the feature adds a Make dependency rule so that vmlinux depends on `fips140.ko`.
It also modifies the vmlinux link rules (i.e., `arch/<arch>/kernel/vmlinux.lds.S`, `scripts/Makefile.vmlinux`, and `scripts/link-vmlinux.sh`) so that the generated module binary is finally combined with `vmlinux.o`.
In addition, we allow multiple cryptography module binary versions (for example, a certified cryptography binary and a latest, up-to-date but uncertified one) to be embedded into the main kernel image to serve different user needs. This design allows regular (non-FIPS) users to benefit from the latest cryptographic updates, while FIPS-mode users continue to use the certified cryptography module.
To support this, we introduce an optional configuration, `CONFIG_CRYPTO_FIPS140_DUAL_VERSION`. When enabled, this option allows two cryptography module versions to be embedded within a single kernel build and ensures that the appropriate module is selected and loaded at boot time based on the system’s FIPS mode status.
### 4.2. Pluggable Interface Between the Built-in Cryptography Subsystem and the Main Kernel
Although the module binary (`fips140.ko`) has been embedded into the final kernel image (`vmlinux`) as described in the previous section, it is not linked to the kernel in any way. This is because `fips140.ko` is embedded in a data-only manner, so the main kernel cannot directly call any functions or access any data defined in the module binary.
Even worse, simply removing the built-in cryptographic algorithms without additional handling would cause the kernel to fail to compile, because traditionally, built-in cryptographic algorithms and the main kernel can interact only through functions and variables whose addresses they assume to know. As a result, even if they have been removed, kernel cryptography users still expect the symbol addresses of cryptographic routines and data to be available at compile time.
To address this, we introduce a pluggable interface between built-in cryptographic functions and variables by placing **address placeholders**. During runtime, once the cryptography kernel module is loaded, these placeholders are updated to the correct addresses. In the rest of this section, we first introduce this pluggable interface mechanism, and then explain how to apply it to the built-in cryptographic algorithms.
**The Pluggable Interface Mechanism:**
There are two types of address holders used to achieve this pluggable interface:
- Function addresses: We use the “static call” mechanism. Static calls are a Linux mechanism that converts an “indirect call” into something with performance equivalent to a “direct call,” while avoiding the introduction of additional security concerns, such as control-flow–hijacking attack gadgets. We implement this function-address placeholder as the `DECLARE_STATIC_CALL()` and `DEFINE_CRYPTO_API_STUB()` wrappers.
- Variable addresses (the remaining smaller portion): For these, we use a pointer of the corresponding data type. We implement this address placeholder as the `DECLARE_CRYPTO_VAR()` and `DEFINE_CRYPTO_API_STUB()` wrappers:
These wrappers are applied to each symbol-exported (i.e., `EXPORT_SYMBOL()`) cryptographic function and variable (details on how to apply them are described later). Once applied, the wrappers are compiled differently for the main kernel and for the built-in cryptographic algorithm source code—acting as the “outlet” and the “plug,” respectively—using different compilation flags (`-DFIPS_MODULE`) introduced by our customized build rules described earlier.
As a result, the kernel can successfully compile even when the built-in cryptographic algorithms are removed, thanks to these address placeholders. At boot time, the placeholders initially hold NULL, but since no cryptography users exist at that stage, the kernel can still start booting correctly. After the cryptography module is loaded, the placeholders are dynamically updated to the correct addresses later (by `do_crypto_api()` and `do_crypto_var()`, described in later section).
In addition to these address placeholders, there is another important interaction point between the cryptography subsystem and the main kernel—the cryptographic initialization routines. Therefore, we also add a mechanism to collect all cryptographic initialization functions (e.g., those defined using `module_init()`) into a dedicated ELF section. This serves as preparation for the later module and cryptography-subsystem initialization steps described in subsequent sections.
**Applying the Pluggable Interface Mechanism to Cryptographic Algorithms:**
To apply these pluggable interface wrappers to a cryptographic algorithm and make them take effect, we follow the steps below (using `crypto/asymmetric_keys/asymmetric_type.c` as an example):
1. **Apply `crypto-objs-y` compile rule to the cryptographic algorithm:**
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \ asymmetric_type.o \ restrict.o \ signature.o
```
2. **Locate the communication point between the cryptographic algorithm and the main kernel:**
The cryptography subsystem is designed such that most interactions between the main kernel and cryptographic algorithms occur through exported symbols using `EXPORT_SYMBOL()` wrappers.
This kernel design exists because most cryptographic algorithm implementations must support both built-in and modular modes.
Consequently, the cryptographic functions and variables exported by `EXPORT_SYMBOL()` are a well-defined and identifiable interface between the cryptography subsystem and the main kernel:
```
// in crypto/asymmetric_keys/asymmetric_type.c
//Exported cryptographic function:
bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
const struct asymmetric_key_id *kid2) {...}
EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
//Exported cryptographic variable:
struct key_type key_type_asymmetric = {...};
EXPORT_SYMBOL_GPL(key_type_asymmetric);
```
3. **Replace their declarations in the header file with the address-placeholder declaration wrappers:**
```
// in include/keys/asymmetric-type.h
// for exported cryptographic function:
- bool asymmetric_key_id_same const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2);
+ DECLARE_CRYPTO_API(CONFIG_ASYMMETRIC_KEY_TYPE, asymmetric_key_id_same, bool,
(const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2),
(kid1, kid2));
// for exported cryptographic variables:
- struct key_type key_type_asymmetric;
+ DECLARE_CRYPTO_VAR(CONFIG_ASYMMETRIC_KEY_TYPE, key_type_asymmetric, struct key_type, );
+ #if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(FIPS_MODULE) && IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #define key_type_asymmetric (*((struct key_type*)CRYPTO_VAR_NAME(key_type_asymmetric)))
+ #endif
```
By replacing the original declarations with the address-placeholder declaration wrappers, we can automatically force all cryptography users to go through the placeholders, because those users already include the same header file.
The wrapper also takes the cryptographic algorithm Kconfig symbol as a parameter, so that when a cryptographic algorithm is built as a module (for example, `CONFIG_ASYMMETRIC_KEY_TYPE=m`), the original function declarations remain unchanged and are not affected.
4. **Add the address-placeholder definition wrappers into a dedicated file `fips140-api.c`:**
This file will be compiled separately and acts as both the “outlet” and the “plug” for the main kernel and the cryptography module, respectively:
```
// in crypto/fips140/fips140-api.c
+ #if IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #include <keys/asymmetric-type.h>
// for exported cryptographic function:
+ DEFINE_CRYPTO_API_STUB(asymmetric_key_id_same);
// for exported cryptographic variables:
+ #undef key_type_asymmetric
+ DEFINE_CRYPTO_VAR_STUB(key_type_asymmetric);
+ #endif
```
5. **Lastly, collect the cryptographic initialization routines for later module and cryptography-subsystem initialization by wrapping the original cryptographic initialization functions:**
```
// in crypto/asymmetric_keys/asymmetric_type.c
- module_init(asymmetric_key_init);
- module_exit(asymmetric_key_cleanup);
+ crypto_module_init(asymmetric_key_init);
+ crypto_module_exit(asymmetric_key_cleanup);
```
We apply the above steps to both architecture-independent and architecture-specific cryptographic algorithms.
### 4.3. Initialization Synchronization
To ensure the embedded `fips140.ko` module binary provides the same cryptography functionality as the regular kernel, the kernel needs:
1. A module loader to load the module binary directly from memory,
2. A mechanism to plug the module back into the kernel by updating the address placeholders, and
3. Correct cryptography subsystem initialization, as if the cryptographic algorithms were still built-in.
**Directly Load Module Binary from Memory:**
Regular modules are loaded from the filesystem and undergo signature verification on the module binary, which relies on cryptographic operations. However, since we have already fully decoupled the cryptography subsystem, we must skip this step for this `fips140.ko` module.
To achieve this, we add a new loader function `load_crypto_module_mem()` that can load the module binary directly from memory at the designed address without checking the signature. Since the module binary is embedded into main kernel in an ELF section, as specified in the linker script:
```
// in arch/<arch>/kernel/vmlinux.lds.S
.fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
. = ALIGN(8);
_binary_fips140_ko_start = .;
KEEP(*(.fips140_module_data))
_binary_fips140_ko_end = .;
}
```
Therefore, the runtime memory address of the module can be accessed directly by the module loader to invoke the new loader function `load_crypto_module_mem()`.
**Plug Back the Module by Updating Address Placeholder Values:**
To update the address placeholders in the main kernel to the correct addresses matching the loaded module, after compilation the placeholders are placed into dedicated ELF sections `_crypto_api_keys` and `_crypto_var_keys`.
This can be seen from the definition of the placeholder-declaration wrappers:
```
#define DEFINE_CRYPTO_API_STUB(name) \ static struct crypto_api_key __##name##_key \ __used \ __section("__crypto_api_keys") // Place in a dedicated ELF Section
__aligned(__alignof__(struct crypto_api_key)) = \ { \ .key = &STATIC_CALL_KEY(crypto_##name##_key), \ .tramp = STATIC_CALL_TRAMP_ADDR(crypto_##name##_key), \ .func = &name, \ };
#define DEFINE_CRYPTO_VAR_STUB(name) \ static struct crypto_var_key __crypto_##name##_var_key \ __used \ __section("__crypto_var_keys") // Place in a dedicated ELF Section
__aligned(__alignof__(struct crypto_var_key)) = \ { \ .ptr = &CRYPTO_VAR_NAME(name), \ .var = (void*)&name, \ };
```
The purpose of doing this is to allow the main kernel to quickly locate the placeholders and update them to the correct addresses. The update functions are defined as `do_crypto_var()` and `do_crypto_api()`, which are executed at module load.
As a result, all cryptography users in the main kernel can now call the cryptographic functions as if they were built-in.
**Initialize Cryptography Subsystem as if it Were Built-in:**
Cryptographic components must be properly initialized before use, and this initialization is typically achieved through dedicated initialization functions (e.g., `module_init(crypto_init_func)` or `late_initcall(crypto_init_func)`). These functions often have strict execution order requirements and must run during the appropriate boot phase.
Therefore, for our standalone cryptography module feature, we must ensure that these decoupled “built-in” cryptographic algorithms are properly initialized and that their initialization order is preserved as before because failure to follow the correct order can result in kernel panic.
To address this, we introduce a synchronization mechanism between the main kernel and the module to ensure all cryptographic algorithms are executed in the correct kernel boot phase. In more details, we spawn the module initialization process `fips_loader_init()` as an async thread `fips140_sync_thread()`, in which we call `run_initcalls()` to execute the initialization calls of each cryptographic algorithm.
Then, we introduce synchronization helpers such as `wait_until_fips140_level_sync(int level)` to ensure the initialization order of all cryptographic algorithms is synchronized with the main kernel.
## 5. Customization and Extension of Cryptography Module
This section describes how developers can customize which cryptographic algorithms are included in the standalone cryptography module, as well as extend this feature to other cryptographic algorithms or hardware architectures.
### 5.1. Cryptography Selection Mechanism
The feature automatically includes cryptographic algorithms that meet specific criteria:
1. **Built-in Configuration**: Only cryptographic algorithms configured as `CONFIG_CRYPTO_*=y` are candidates for inclusion
2. **Explicit Inclusion**: Cryptographic algorithms must be explicitly converted using the `crypto-objs-$(CONFIG__CRYPTO_*`) build rule
### 5.2. Extend Support to New Cryptographic Algorithms
To extend support to a new cryptographic algorithm in the standalone module, follow these steps:
**Step 1: Update the Makefile**
```
# in crypto/[algorithm]/Makefile
- obj-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
+ crypto-objs-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
```
For Architecture-Specific Cryptographic Algorithms:
- Apply the `crypto-objs-` rule in the appropriate `arch/*/crypto/Makefile`
**Step 2: Add Pluggable Interface Support**
If the cryptographic algorithm exports symbols via `EXPORT_SYMBOL()`, add the pluggable interface wrappers:
```
# Example: in include/crypto/algorithm.h
- extern int crypto_algorithm_transform(struct crypto_tfm *tfm, const u8 *src,
u8 *dst, unsigned int len, u32 flags);
+ DECLARE_CRYPTO_API(CONFIG_CRYPTO_ALGORITHM, crypto_algorithm_transform, int,
(struct crypto_tfm *tfm, const u8 *src, u8 *dst, unsigned int len, u32 flags),
(tfm, src, dst, len, flags));
```
Then, add the corresponding stubs in `crypto/fips140/fips140-api.c`:
```
#if IS_BUILTIN(CONFIG_CRYPTO_ALGORITHM)
#include <crypto/algorithm.h>
DEFINE_CRYPTO_API_STUB(crypto_algorithm_transform);
#endif
```
For Architecture-Specific Cryptographic Algorithms:
- Include architecture-specific stubs in `arch/*/crypto/fips140/fips140-api.c`:
```
# Example: in arch/arm64/crypto/fips140/fips140-api.c
#if IS_BUILTIN(CONFIG_CRYPTO_AES_ARM64_CE)
#include <arch/arm64/crypto/aes-ce-setkey.h>
DEFINE_CRYPTO_API_STUB(ce_aes_setkey);
DEFINE_CRYPTO_API_STUB(ce_aes_expandkey);
#endif
```
**Step 3: Update Initialization**
Replace module initialization calls:
```
# in crypto/algorithm/algorithm.c
- module_init(algorithm_init);
- module_exit(algorithm_exit);
+ crypto_module_init(algorithm_init);
+ crypto_module_exit(algorithm_exit);
```
### 5.3. Architecture-Specific Extensions
**Extending to New Architectures:**
Currently supported architectures are x86_64 and ARM64. To extend this feature to additional architectures:
1. **Update Linker Scripts**: Add ELF sections in `arch/[new-arch]/kernel/vmlinux.lds.S`:
```
.fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
. = ALIGN(8);
_binary_fips140_ko_start = .;
KEEP(*(.fips140_module_data))
_binary_fips140_ko_end = .;
}
```
2. **Create Architecture-Specific Files**: Set up `arch/[new-arch]/crypto/fips140/` directory with Makefile and `fips140-api.c` following the pattern used in x86_64 and ARM64.
## 6. Related Work and Comparison
The idea of modularizing kernel cryptographic functionality has also attracted attention from other Linux distributions as well as Linux-kernel-based platforms that are not traditional distributions. Specifically, there are two related efforts: one from [Android's GKI kernel](https://source.android.com/docs/core/architecture/kernel/gki-fips140-module) and another from [Oracle Linux](https://git.kernel.org/pub/scm/linux/kernel/git/vegard/linux-fips140.git/log/?h=fips140). While Amazon Linux incorporated several valuable ideas from these efforts (and have acknowledged them in the patch commits—thank you again!), this section highlights the key differences between those approaches and this approach. The goal is to describe the trade-offs and design choices objectively, rather than to criticize other implementations.
### 6.1. Comparison with Android's GKI
Android's work is the earliest one on modularizing kernel cryptographic code, and it targets a non-intrusive approach to the core GKI kernel, with the goal of minimizing modifications to the kernel source. To achieve this, the crypto module relies on several interception or "hijacking" techniques that intervene in the core kernel execution path.
While this approach minimizes kernel code changes, we don't adopt such an approach for several reasons. First, these interception mechanisms tightly depend on internal kernel crypto subsystem behavior, making them fragile across major kernel updates thus less suitable to reuse the same module on newer major kernel versions. Second, this design requires substantial additional cryptographic code duplication, which impacts maintainability. Finally, the solution only supports a fixed set of cryptographic algorithms, making it non-general and difficult to extend.
In contrast, our design integrates directly into the Linux kernel source tree, avoids duplicated cryptographic implementations, supports arbitrary kernel configuration settings, and works with any chosen set of cryptographic algorithms.
### 6.2. Comparison with Oracle Linux
Oracle’s work was developed concurrently with this approach. The primary differences between Oracle’s approach and Amazon's lie in build integration, pluggable interface design, and module initialization.
**Build Integration:**
Oracle's module is implemented as an out-of-tree module with a separate Makefile. This introduces three major reasons we don't adopt such an approach:
*First*, the separate Makefile duplicates many kernel build rules, which increases maintenance cost, as upstream kernel build changes must be tracked and replicated. One concrete example can be seen below:
in Oracle's module makefile
```
fips140-y += crypto/skcipher.o
fips140-y += crypto/lskcipher.o
```
However, in upstream, the corresponding build logic is more complex and configuration-dependent:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As shown above, when `CONFIG_BPF_SYSCALL` is enabled, `bpf_crypto_skcipher.o` must also be included. Tracking such dependencies is hard in the duplicated Makefile approach. In contrast, our approach integrates seamlessly into the kernel build system by introducing a customized build rule (`crypto-objs-*`) rather than relying on a duplicated Makefile, such that this is handled correctly by reusing the existing kernel build logic:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As a result, such a Makefile-duplication approach does not scale well across all kernel configurations and does not easily support arbitrary sets of cryptographic algorithms.
*Second*, since the module is to be embedded as part of the kernel image (i.e., `vmlinux`) as described earlier, the module build must be triggered automatically as part of the `vmlinux` build process to achieve a seamless build workflow. However, Oracle's module build is not tightly integrated into the kernel build framework and requires special build commands (e.g., first do `make M=fips140/` specifically, then do some shell command and finally `make`).
In contrast, our approach improves this aspect by integrating the module build tightly into the regular kernel build, so the build process is seamless and automatic with regular build and packaging processes such as `make` or `make vmlinux` or `make install`.
**Pluggable Interface:**
There are several differences in the pluggable interface design.
*First*, we avoid duplicate crypto code so only keep one crypto code in kernel memory, while existing work keeps two crypto code even if these crypto code are from the same source code. This is due to the way Oracle defines pluggable interface macros in `crypto/api`, where its design requires some cryptographic code to remain compiled into the main kernel image in addition to the code inside the standalone cryptography module. Keeping two crypto code is ok if these code are different and designed to be used for different runtime modes (i.e., FIPS/non-FIPS mode), but will be unnecessary if both crypto code are the same.
In contrast, the approach we use can flexibly support both choices: keep one cryptography subsystem, or two different crypto subsystems. To do so, we introduce an option `CRYPTO_FIPS140_DUAL_VERSION` such that when it is disabled, we only keep one cryptographic subsystem in the cryptography module while completely removing it from the main kernel; and when it is enabled, we allow having two different modules carrying different cryptography for different kernel runtime modes (i.e., FIPS and non-FIPS mode).
*Second*, existing approach requires modifications to both the cryptographic implementation (.c) files and the declaration (.h) header files while our approach only requires modifying the header file, making the change less intrusive to the kernel codebase.
*Third*, prior approaches mainly support making cryptographic function calls pluggable, while our approach extends pluggability to cryptographic variables as well.
*Fourth*, prior approach requires all cryptographics that we care (for any purpose such as those within FIPS boundary) to be included within a single kernel module `fips140.ko` (e.g., when `CONFIG_CRYPTO_AES=m`, it cannot be `aes.ko` but must be within fips140.ko). However, this requirement limits the inherent benefit of a kernel module (i.e., on-demand loading for memory efficiency). In contrast, our approach allows the cryptographic we care remain its original modular if it is configured as being so (i.e., if `CONFIG_CRYPTO_AES=m`, the aes will still be as `aes.ko` but not forced to `fips140.ko`) up to the `.config` setting. One benefit of this design is that it does not impose strict requirements on `.config` setting (i.e., a cryptography `.config` can be set to both `=y|m` while existing work must be set as `=y`), preserving configuration flexibility.
To support so, for any cryptography within the interest (i.e., whose makerule has been replaced with `crypto-objs-*`) but configured as build-as-module (i.e., `CONFIG_CRYPTO_*=m`), its compiled `.ko` binary will be marked automatically, such that the loader will have a way to recognize to perform some interest-specific processing (e.g., registered as FIPS-required flag) if needed. And the pluggable interface can also adjust its coverage automatically based on different `CONFIG_CRYPTO_*=y|=m` settings. This is achieved by letting the pluggable interface macro to take `CONFIG_CRYPTO_*` option as a parameter to recognize the `.config` setting.
**Module Initialization:**
Oracle's initialization routine does not guarantee preservation of the original crypto initialization order (i.e., the order they should follow if they were originally built-in in the main kernel), which limits its ability to support arbitrary combinations of cryptographic algorithms. This is because the crypto initialization routine in the module is executed too early, such that all module crypto is initialized before the cryptography init in the main kernel. So if there is a crypto in the module (e.g., a crypto init defined as `late_init()`) that depends on a cryptography (whose init is defined as `module_init()`) in the main kernel, since the one in the main kernel should be executed earlier (but because the module init is too early, it makes the crypto in the main kernel executed too late), such a case will break the kernel boot process.
Our design, on the other hand, introduces explicit initialization synchronization mechanisms between cryptography's init routine in the module and in the main kernel that can preserve the original built-in initialization order. As a result, our module supports any chosen crypto set to be included in the module.
### 6.3. Comparison Summary
Overall, combined with differences in coding style and integration strategy, the proposed approach is more seamlessly integrated with the upstream Linux kernel, making it more generalizable across different kernel configuration settings, and the changed behavior more invisible to kernel users.
## 7. Summary
In this patch series, Amazon Linux proposes a new kernel feature that decouples the built-in crypto subsystem into a dedicated kernel module. To achieve this, several key mechanisms are designed, including specialized compile rules, a novel pluggable interface mechanism, and a module-loading initialization process. This feature is designed in an upstream-friendly manner so that it can support arbitrary kernel configuration settings and arbitrary chosen sets of cryptographic algorithms. It is planned to be officially launched with the Amazon Linux Kernel 6.18 and future kernels.
---
Written by Jay Wang <wanjay@amazon.com>, Amazon Linux
Jay Wang (15):
crypto: add Kconfig options for standalone crypto module
crypto: add module entry for standalone crypto kernel module
build: special compilation rule for building the standalone crypto
module
build: Add ELF marker for crypto-objs-m modules
crypto: add pluggable interface for builtin crypto modules
crypto: dedicated ELF sections for collected crypto initcalls
crypto: fips140: add crypto module loader
build: embed the standalone crypto module into vmlinux
build: add CONFIG_DEBUG_INFO_BTF_MODULES support for the standalone
crypto kernel module
Allow selective crypto module loading at boot based on FIPS mode
Execute crypto initcalls during module initialization
crypto: fips140: add module integrity self-check
x86: crypto: to convert exported crypto symbols into pluggable
interface for x86 cryptos
arm64: crypto: to convert exported crypto symbols into pluggable
interface for arm64 cryptos
Add standalone crypto kernel module technical documentation
Vegard Nossum (2):
module: allow kernel module loading directly from memory
crypto/algapi.c: skip crypto_check_module_sig() for the standalone
crypto module
Makefile | 68 ++-
arch/arm64/crypto/Makefile | 3 +
arch/arm64/crypto/fips140/Makefile | 14 +
arch/arm64/crypto/fips140/fips140-api.c | 0
arch/arm64/kernel/vmlinux.lds.S | 40 ++
arch/x86/crypto/Makefile | 3 +
arch/x86/crypto/fips140/Makefile | 14 +
arch/x86/crypto/fips140/fips140-api.c | 0
arch/x86/kernel/vmlinux.lds.S | 40 ++
crypto/Kconfig | 1 +
crypto/Makefile | 5 +
crypto/algapi.c | 14 +-
crypto/fips140/Kconfig | 68 +++
crypto/fips140/Makefile | 21 +
crypto/fips140/README | 401 ++++++++++++++++++
crypto/fips140/fips140-api.c | 7 +
crypto/fips140/fips140-crypto-module-marker.h | 8 +
crypto/fips140/fips140-loader.c | 201 +++++++++
crypto/fips140/fips140-module.c | 138 ++++++
crypto/fips140/fips140-module.h | 30 ++
crypto/fips140/fips140.lds | 17 +
include/asm-generic/vmlinux.lds.h | 1 +
include/crypto/api.h | 197 +++++++++
include/linux/init.h | 10 +
include/linux/module.h | 2 +
include/uapi/linux/module.h | 5 +
init/main.c | 4 +
kernel/bpf/btf.c | 20 +
kernel/module/main.c | 169 ++++++--
kernel/params.c | 3 +-
scripts/Makefile.build | 123 +++++-
scripts/Makefile.modfinal | 37 ++
scripts/Makefile.modinst | 13 +-
scripts/Makefile.modpost | 25 ++
scripts/Makefile.vmlinux | 59 ++-
scripts/link-vmlinux.sh | 14 +
scripts/mod/modpost.c | 24 +-
37 files changed, 1759 insertions(+), 40 deletions(-)
create mode 100644 arch/arm64/crypto/fips140/Makefile
create mode 100644 arch/arm64/crypto/fips140/fips140-api.c
create mode 100644 arch/x86/crypto/fips140/Makefile
create mode 100644 arch/x86/crypto/fips140/fips140-api.c
create mode 100644 crypto/fips140/Kconfig
create mode 100644 crypto/fips140/Makefile
create mode 100644 crypto/fips140/README
create mode 100644 crypto/fips140/fips140-api.c
create mode 100644 crypto/fips140/fips140-crypto-module-marker.h
create mode 100644 crypto/fips140/fips140-loader.c
create mode 100644 crypto/fips140/fips140-module.c
create mode 100644 crypto/fips140/fips140-module.h
create mode 100644 crypto/fips140/fips140.lds
create mode 100644 include/crypto/api.h
--
2.47.3
^ permalink raw reply
* [PATCH AUTOSEL 6.19-6.18] gendwarfksyms: Fix build on 32-bit hosts
From: Sasha Levin @ 2026-02-12 1:09 UTC (permalink / raw)
To: patches, stable
Cc: Sami Tolvanen, Michal Suchánek, Sasha Levin, linux-modules,
linux-kbuild
In-Reply-To: <20260212010955.3480391-1-sashal@kernel.org>
From: Sami Tolvanen <samitolvanen@google.com>
[ Upstream commit ddc54f912a551f6eb0bbcfc3880f45fe27a252cb ]
We have interchangeably used unsigned long for some of the types
defined in elfutils, assuming they're always 64-bit. This obviously
fails when building gendwarfksyms on 32-bit hosts. Fix the types.
Reported-by: Michal Suchánek <msuchanek@suse.de>
Closes: https://lore.kernel.org/linux-modules/aRcxzPxtJblVSh1y@kitsune.suse.cz/
Tested-by: Michal Suchánek <msuchanek@suse.de>
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now I have a complete picture. Let me write my analysis.
---
## Comprehensive Analysis
### 1. COMMIT MESSAGE ANALYSIS
The subject "gendwarfksyms: Fix build on 32-bit hosts" clearly
identifies this as a **build fix**. The message explains that `unsigned
long` was used interchangeably with elfutils types that are always
64-bit (`uint64_t`), which breaks compilation on 32-bit hosts where
`unsigned long` is only 32 bits.
Key indicators:
- **Reported-by:** Michal Suchanek (SUSE engineer) - a real user who hit
this building kernels
- **Tested-by:** Same reporter - confirms the fix works
- **Closes:** link to lore.kernel.org bug report - documented issue
### 2. CODE CHANGE ANALYSIS
The fix addresses three distinct but related 32-bit portability bugs
across two files:
**Bug 1 - `dwarf.c` (`process_enumerator_type`):**
The type chain is:
- `Dwarf_Word` = `GElf_Xword` = `Elf64_Xword` = `uint64_t` (always
64-bit)
- `unsigned long` = 32-bit on 32-bit hosts
The pre-fix code passes `&value` (where `value` is `Dwarf_Word` /
`uint64_t`) to `kabi_get_enumerator_value()`, which expects `unsigned
long *`. On a 32-bit host, this is a type mismatch: passing a
`uint64_t*` where `unsigned long*` (4 bytes) is expected. The function
would write only 4 bytes to a memory location expected to hold 8 bytes,
leaving the upper half uninitialized. This is both a **compiler
error/warning** and a **correctness bug**.
The fix introduces a properly-typed `unsigned long override` variable,
passes it to the function, then assigns `value = override;` to widen it
back.
**Bug 2 - `symbols.c` (format strings):**
`shdr->sh_entsize` is `GElf_Xword` = `uint64_t`, but was printed with
`%lu` (expects `unsigned long`, 32-bit). Fixed to `"%" PRIu64`.
Similarly, `sym->addr.address` is `Elf64_Addr` = `uint64_t`, but was
printed with `%lx`. Fixed to `"%" PRIx64`. The missing `#include
<inttypes.h>` is added for the `PRIu64`/`PRIx64` macros.
On 32-bit hosts, these format mismatches would cause:
- Compiler warnings (`-Wformat`) or errors (`-Werror`)
- Incorrect printed values (reading wrong stack slots for variadic args)
### 3. CLASSIFICATION
This is unambiguously a **build fix**. Build fixes are explicitly listed
in the stable kernel rules as appropriate for backporting. They don't
introduce new features or change runtime behavior - they simply make the
code compile correctly.
### 4. SCOPE AND RISK ASSESSMENT
- **Files changed:** 2 (`dwarf.c`, `symbols.c`)
- **Lines changed:** ~10 meaningful lines
- **Risk:** Extremely low. The changes are format specifier corrections
and a type-narrowing variable addition. They cannot introduce
regressions.
- **Subsystem:** `scripts/gendwarfksyms/` - a build-time host tool, not
runtime kernel code. Even if there were a mistake, it couldn't crash
the kernel.
### 5. APPLICABILITY TO STABLE TREES
`gendwarfksyms` was introduced in **v6.14-rc1** (commit
`f28568841ae0a`). I verified:
- **v6.12 and earlier (LTS):** Do NOT have `gendwarfksyms` - this fix is
**not applicable**
- **v6.14 through v6.19:** All have the buggy code - this fix IS
applicable
The buggy code (`%lu` formats, `Dwarf_Word`/`unsigned long` mismatch)
has existed since the initial introduction in v6.14-rc1. All three bug
patterns exist in `git show v6.14:scripts/gendwarfksyms/symbols.c` and
`git show v6.14:scripts/gendwarfksyms/dwarf.c`.
Active stable trees that benefit: **v6.18.y** (and potentially v6.14.y
through v6.17.y if still maintained).
### 6. USER IMPACT
This affects anyone building a 6.14+ kernel on a 32-bit host system with
`CONFIG_GENDWARFKSYMS` enabled. While 32-bit build hosts are
increasingly rare, they are still used in some enterprise and embedded
development environments. The reporter is from SUSE, indicating this
affects enterprise distribution builds. Without this fix, the build
simply **fails** on 32-bit hosts.
### 7. DEPENDENCY CHECK
The fix is completely self-contained. It changes format specifiers, adds
a standard C include, and introduces a temporary variable. It has **zero
dependencies** on other commits.
### 8. VERDICT
**Meets stable criteria:**
- Obviously correct and tested (type/format corrections, Tested-by tag)
- Fixes a real bug (build failure on 32-bit hosts + potential incorrect
behavior)
- Small and contained (~10 lines across 2 files)
- No new features, no API changes, no behavioral changes
- Build fixes are explicitly allowed in stable
**Risk vs. benefit:**
- Risk: Near zero - trivial type corrections in a host build tool
- Benefit: Enables building the kernel on 32-bit hosts when
gendwarfksyms is enabled
The only limitation is that this fix is only applicable to stable trees
v6.14.y and newer, since `gendwarfksyms` doesn't exist in the main LTS
trees (6.12.y, 6.6.y, 6.1.y). But for the trees where it applies, it's a
clear and necessary build fix.
**YES**
scripts/gendwarfksyms/dwarf.c | 4 +++-
scripts/gendwarfksyms/symbols.c | 5 +++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/scripts/gendwarfksyms/dwarf.c b/scripts/gendwarfksyms/dwarf.c
index 3538a7d9cb070..e76d732f5f602 100644
--- a/scripts/gendwarfksyms/dwarf.c
+++ b/scripts/gendwarfksyms/dwarf.c
@@ -750,6 +750,7 @@ static void process_enumerator_type(struct state *state, struct die *cache,
Dwarf_Die *die)
{
bool overridden = false;
+ unsigned long override;
Dwarf_Word value;
if (stable) {
@@ -761,7 +762,8 @@ static void process_enumerator_type(struct state *state, struct die *cache,
return;
overridden = kabi_get_enumerator_value(
- state->expand.current_fqn, cache->fqn, &value);
+ state->expand.current_fqn, cache->fqn, &override);
+ value = override;
}
process_list_comma(state, cache);
diff --git a/scripts/gendwarfksyms/symbols.c b/scripts/gendwarfksyms/symbols.c
index ecddcb5ffcdfb..42cd27c9cec4f 100644
--- a/scripts/gendwarfksyms/symbols.c
+++ b/scripts/gendwarfksyms/symbols.c
@@ -3,6 +3,7 @@
* Copyright (C) 2024 Google LLC
*/
+#include <inttypes.h>
#include "gendwarfksyms.h"
#define SYMBOL_HASH_BITS 12
@@ -242,7 +243,7 @@ static void elf_for_each_global(int fd, elf_symbol_callback_t func, void *arg)
error("elf_getdata failed: %s", elf_errmsg(-1));
if (shdr->sh_entsize != sym_size)
- error("expected sh_entsize (%lu) to be %zu",
+ error("expected sh_entsize (%" PRIu64 ") to be %zu",
shdr->sh_entsize, sym_size);
nsyms = shdr->sh_size / shdr->sh_entsize;
@@ -292,7 +293,7 @@ static void set_symbol_addr(struct symbol *sym, void *arg)
hash_add(symbol_addrs, &sym->addr_hash,
symbol_addr_hash(&sym->addr));
- debug("%s -> { %u, %lx }", sym->name, sym->addr.section,
+ debug("%s -> { %u, %" PRIx64 " }", sym->name, sym->addr.section,
sym->addr.address);
} else if (sym->addr.section != addr->section ||
sym->addr.address != addr->address) {
--
2.51.0
^ permalink raw reply related
* Re: [GIT PULL] Modules changes for v7.0-rc1
From: pr-tracker-bot @ 2026-02-10 18:10 UTC (permalink / raw)
To: Sami Tolvanen
Cc: Linus Torvalds, Sami Tolvanen, Aaron Tomlin, Coiby Xu,
Daniel Gomez, Kees Cook, linux-kernel, linux-modules,
Luis Chamberlain, Marco Crivellari, Petr Pavlu, Randy Dunlap
In-Reply-To: <20260209155527.1385229-2-samitolvanen@google.com>
The pull request you sent on Mon, 9 Feb 2026 15:55:26 +0000:
> git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git tags/modules-7.0-rc1
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/a7423e6ea2f8f6f453de79213c26f7a36c86d9a2
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
^ permalink raw reply
* Re: [GIT PULL] Modules changes for v7.0-rc1
From: pr-tracker-bot @ 2026-02-10 18:10 UTC (permalink / raw)
To: Sami Tolvanen
Cc: Linus Torvalds, Sami Tolvanen, Aaron Tomlin, Coiby Xu,
Daniel Gomez, Kees Cook, linux-kernel, linux-modules,
Luis Chamberlain, Marco Crivellari, Petr Pavlu, Randy Dunlap
In-Reply-To: <20260209155527.1385229-2-samitolvanen@google.com>
The pull request you sent on Mon, 9 Feb 2026 15:55:26 +0000:
> git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git tags/modules-7.0-rc1
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/a7423e6ea2f8f6f453de79213c26f7a36c86d9a2
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
^ permalink raw reply
* Re: [GIT PULL] x509, pkcs7: Add support for ML-DSA signatures
From: pr-tracker-bot @ 2026-02-10 18:10 UTC (permalink / raw)
To: David Howells
Cc: Linus Torvalds, dhowells, Lukas Wunner, Ignat Korchagin,
Jarkko Sakkinen, Herbert Xu, Eric Biggers, Luis Chamberlain,
Petr Pavlu, Daniel Gomez, Sami Tolvanen, Jason A . Donenfeld,
Ard Biesheuvel, Stephan Mueller, linux-crypto, keyrings,
linux-modules, linux-kernel
In-Reply-To: <2977832.1770384806@warthog.procyon.org.uk>
The pull request you sent on Fri, 06 Feb 2026 13:33:26 +0000:
> git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git tags/keys-next-20260206
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/b63c90720348578631cda74285958c3ad3169ce9
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
^ permalink raw reply
* [GIT PULL] Modules changes for v7.0-rc1
From: Sami Tolvanen @ 2026-02-09 15:55 UTC (permalink / raw)
To: Linus Torvalds
Cc: Sami Tolvanen, Aaron Tomlin, Coiby Xu, Daniel Gomez, Kees Cook,
linux-kernel, linux-modules, Luis Chamberlain, Marco Crivellari,
Petr Pavlu, Randy Dunlap
The following changes since commit 9448598b22c50c8a5bb77a9103e2d49f134c9578:
Linux 6.19-rc2 (2025-12-21 15:52:04 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git tags/modules-7.0-rc1
for you to fetch changes up to b68758e6f4307179247126b7641fa7ba7109c820:
modules: moduleparam.h: fix kernel-doc comments (2025-12-22 16:35:54 +0000)
----------------------------------------------------------------
Modules changes for v7.0-rc1
Module signing:
- Remove SHA-1 support for signing modules. SHA-1 is no longer
considered secure for signatures due to vulnerabilities that can
lead to hash collisions. None of the major distributions use
SHA-1 anymore, and the kernel has defaulted to SHA-512 since
v6.11. Note that loading SHA-1 signed modules is still supported.
- Update scripts/sign-file to use only the OpenSSL CMS API for
signing. As SHA-1 support is gone, we can drop the legacy PKCS#7
API which was limited to SHA-1. This also cleans up support for
legacy OpenSSL versions.
Cleanups and fixes:
- Use system_dfl_wq instead of the per-cpu system_wq following the
ongoing workqueue API refactoring.
- Avoid open-coded kvrealloc() in module decompression logic by
using the standard helper.
- Improve section annotations by replacing the custom __modinit
with __init_or_module and removing several unused __INIT*_OR_MODULE
macros.
- Fix kernel-doc warnings in include/linux/moduleparam.h.
- Ensure set_module_sig_enforced is only declared when module
signing is enabled.
- Fix gendwarfksyms build failures on 32-bit hosts.
MAINTAINERS:
- Update the module subsystem entry to reflect the maintainer
rotation and update the git repository link.
The changes have been soaking in linux-next since -rc2.
Note that like Daniel mentioned in the previous pull request [1], we
rotate maintainership every 6 months, and I will be handling the module
subsystem pull requests for the first half of this year.
Link: https://lore.kernel.org/r/20251203234840.3720-1-da.gomez@kernel.org [1]
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
----------------------------------------------------------------
Conflicts:
There's a linux-next conflict with dhowells' keys-next branch. Specifically,
the keys-next commit
0ad9a71933e73 ("modsign: Enable ML-DSA module signing")
conflicts with
d7afd65b4acc ("sign-file: Use only the OpenSSL CMS API for signing")
Here's a suggested resolution from Mark Brown, which has been applied to
linux-next:
diff --cc scripts/sign-file.c
index 16f2bf2e1e3c,78276b15ab23..bd269a2bbf26
--- a/scripts/sign-file.c
+++ b/scripts/sign-file.c
@@@ -206,10 -228,15 +206,11 @@@ int main(int argc, char **argv
bool raw_sig = false;
unsigned char buf[4096];
unsigned long module_size, sig_size;
- unsigned int use_signed_attrs;
++ unsigned int use_signed_attrs = CMS_NOATTR;
const EVP_MD *digest_algo;
EVP_PKEY *private_key;
-#ifndef USE_PKCS7
CMS_ContentInfo *cms = NULL;
unsigned int use_keyid = 0;
-#else
- PKCS7 *pkcs7 = NULL;
-#endif
X509 *x509;
BIO *bd, *bm;
int opt, n;
@@@ -271,20 -314,49 +272,40 @@@
digest_algo = EVP_get_digestbyname(hash_algo);
ERR(!digest_algo, "EVP_get_digestbyname");
-#ifndef USE_PKCS7
-
+ unsigned int flags =
+ CMS_NOCERTS |
+ CMS_PARTIAL |
+ CMS_BINARY |
+ CMS_DETACHED |
+ CMS_STREAM |
+ CMS_NOSMIMECAP |
+ #ifdef CMS_NO_SIGNING_TIME
+ CMS_NO_SIGNING_TIME |
+ #endif
+ use_keyid;
+
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_VERSION_NUMBER < 0x40000000L
+ if (EVP_PKEY_is_a(private_key, "ML-DSA-44") ||
+ EVP_PKEY_is_a(private_key, "ML-DSA-65") ||
+ EVP_PKEY_is_a(private_key, "ML-DSA-87")) {
+ /* ML-DSA + CMS_NOATTR is not supported in openssl-3.5
+ * and before.
+ */
+ use_signed_attrs = 0;
+ }
+ #endif
+
+ flags |= use_signed_attrs;
+
/* Load the signature message from the digest buffer. */
- cms = CMS_sign(NULL, NULL, NULL, NULL,
- CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY |
- CMS_DETACHED | CMS_STREAM);
+ cms = CMS_sign(NULL, NULL, NULL, NULL, flags);
ERR(!cms, "CMS_sign");
- ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo,
- CMS_NOCERTS | CMS_BINARY |
- CMS_NOSMIMECAP | CMS_NOATTR |
- use_keyid),
+ ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, flags),
"CMS_add1_signer");
- ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) != 1,
+ ERR(CMS_final(cms, bm, NULL, flags) != 1,
"CMS_final");
-#else
- pkcs7 = PKCS7_sign(x509, private_key, NULL, bm,
- PKCS7_NOCERTS | PKCS7_BINARY |
- PKCS7_DETACHED | use_signed_attrs);
- ERR(!pkcs7, "PKCS7_sign");
-#endif
-
if (save_sig) {
char *sig_file_name;
BIO *b;
----------------------------------------------------------------
Coiby Xu (1):
module: Only declare set_module_sig_enforced when CONFIG_MODULE_SIG=y
Kees Cook (1):
module/decompress: Avoid open-coded kvrealloc()
Marco Crivellari (1):
module: replace use of system_wq with system_dfl_wq
Petr Pavlu (4):
module: Remove unused __INIT*_OR_MODULE macros
params: Replace __modinit with __init_or_module
module: Remove SHA-1 support for module signing
sign-file: Use only the OpenSSL CMS API for signing
Randy Dunlap (1):
modules: moduleparam.h: fix kernel-doc comments
Sami Tolvanen (2):
MAINTAINERS: Update module subsystem maintainers and repository
gendwarfksyms: Fix build on 32-bit hosts
MAINTAINERS | 4 +--
include/linux/module.h | 18 ++++-------
include/linux/moduleparam.h | 8 +++--
kernel/module/Kconfig | 5 ----
kernel/module/decompress.c | 10 +++----
kernel/module/dups.c | 4 +--
kernel/params.c | 15 ++++------
scripts/gendwarfksyms/dwarf.c | 4 ++-
scripts/gendwarfksyms/symbols.c | 5 ++--
scripts/sign-file.c | 66 ++---------------------------------------
10 files changed, 35 insertions(+), 104 deletions(-)
^ permalink raw reply
* Re: [PATCH v16 8/7] pkcs7: Change a pr_warn() to pr_warn_once()
From: Jarkko Sakkinen @ 2026-02-08 13:41 UTC (permalink / raw)
To: David Howells
Cc: Lukas Wunner, Ignat Korchagin, Herbert Xu, Eric Biggers,
Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen,
Jason A . Donenfeld, Ard Biesheuvel, Stephan Mueller,
linux-crypto, keyrings, linux-modules, linux-kernel
In-Reply-To: <2892236.1770306426@warthog.procyon.org.uk>
On Thu, Feb 05, 2026 at 03:47:06PM +0000, David Howells wrote:
> Only display the "PKCS7: Waived invalid module sig (has authattrs)" once.
>
> Suggested-by: Lenny Szubowicz <lszubowi@redhat.com>
> Signed-off-by: David Howells <dhowells@redhat.com>
> Tested-by: Lenny Szubowicz <lszubowi@redhat.com>
> cc: Lukas Wunner <lukas@wunner.de>
> cc: Ignat Korchagin <ignat@cloudflare.com>
> cc: Jarkko Sakkinen <jarkko@kernel.org>
> cc: Stephan Mueller <smueller@chronox.de>
> cc: Eric Biggers <ebiggers@kernel.org>
> cc: Herbert Xu <herbert@gondor.apana.org.au>
> cc: keyrings@vger.kernel.org
> cc: linux-crypto@vger.kernel.org
> ---
> crypto/asymmetric_keys/pkcs7_verify.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
> index 519eecfe6778..474e2c1ae21b 100644
> --- a/crypto/asymmetric_keys/pkcs7_verify.c
> +++ b/crypto/asymmetric_keys/pkcs7_verify.c
> @@ -427,7 +427,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
> if (pkcs7->have_authattrs) {
> #ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
> if (pkcs7->authattrs_rej_waivable) {
> - pr_warn("Waived invalid module sig (has authattrs)\n");
> + pr_warn_once("Waived invalid module sig (has authattrs)\n");
> break;
> }
> #endif
>
Could be also ratelimited but I guess here once is the right call:
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
BR, Jarkko
^ permalink raw reply
* [syzbot] [modules?] KASAN: slab-out-of-bounds Write in try_module_get (2)
From: syzbot @ 2026-02-06 18:05 UTC (permalink / raw)
To: da.gomez, linux-kernel, linux-modules, mcgrof, petr.pavlu,
samitolvanen, syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: 8e621c9a3375 Merge tag 'net-6.18-rc7' of git://git.kernel...
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=110c9a12580000
kernel config: https://syzkaller.appspot.com/x/.config?x=1cd7f786c0f5182f
dashboard link: https://syzkaller.appspot.com/bug?extid=e993e01b15c8eefd9cd4
compiler: gcc (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
Unfortunately, I don't have any reproducer for this issue yet.
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/6be75789d60e/disk-8e621c9a.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/62e7a40cfe48/vmlinux-8e621c9a.xz
kernel image: https://storage.googleapis.com/syzbot-assets/3e523caa536d/bzImage-8e621c9a.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+e993e01b15c8eefd9cd4@syzkaller.appspotmail.com
==================================================================
BUG: KASAN: slab-out-of-bounds in instrument_atomic_read_write include/linux/instrumented.h:96 [inline]
BUG: KASAN: slab-out-of-bounds in atomic_inc_not_zero include/linux/atomic/atomic-instrumented.h:1536 [inline]
BUG: KASAN: slab-out-of-bounds in try_module_get+0x4c/0xd0 kernel/module/main.c:913
Write of size 4 at addr ffff888141a87f08 by task syz.1.7015/6511
CPU: 1 UID: 0 PID: 6511 Comm: syz.1.7015 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
print_address_description mm/kasan/report.c:378 [inline]
print_report+0xcd/0x630 mm/kasan/report.c:482
kasan_report+0xe0/0x110 mm/kasan/report.c:595
check_region_inline mm/kasan/generic.c:194 [inline]
kasan_check_range+0x100/0x1b0 mm/kasan/generic.c:200
instrument_atomic_read_write include/linux/instrumented.h:96 [inline]
atomic_inc_not_zero include/linux/atomic/atomic-instrumented.h:1536 [inline]
try_module_get+0x4c/0xd0 kernel/module/main.c:913
dvb_device_open+0x124/0x3b0 drivers/media/dvb-core/dvbdev.c:103
chrdev_open+0x234/0x6a0 fs/char_dev.c:414
do_dentry_open+0x982/0x1530 fs/open.c:965
vfs_open+0x82/0x3f0 fs/open.c:1097
do_open fs/namei.c:3975 [inline]
path_openat+0x1de4/0x2cb0 fs/namei.c:4134
do_filp_open+0x20b/0x470 fs/namei.c:4161
do_sys_openat2+0x11b/0x1d0 fs/open.c:1437
do_sys_open fs/open.c:1452 [inline]
__do_sys_openat fs/open.c:1468 [inline]
__se_sys_openat fs/open.c:1463 [inline]
__x64_sys_openat+0x174/0x210 fs/open.c:1463
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xcd/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f14c238f749
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f14c3243038 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 00007f14c25e5fa0 RCX: 00007f14c238f749
RDX: 0000000000000100 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007f14c2413f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f14c25e6038 R14: 00007f14c25e5fa0 R15: 00007fff9eaadb88
</TASK>
Allocated by task 1:
kasan_save_stack+0x33/0x60 mm/kasan/common.c:56
kasan_save_track+0x14/0x30 mm/kasan/common.c:77
poison_kmalloc_redzone mm/kasan/common.c:400 [inline]
__kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:417
kmalloc_noprof include/linux/slab.h:957 [inline]
kzalloc_noprof include/linux/slab.h:1094 [inline]
dvb_register_device+0x1e4/0x2370 drivers/media/dvb-core/dvbdev.c:475
dvb_dmxdev_init+0x33e/0x4e0 drivers/media/dvb-core/dmxdev.c:1436
vidtv_bridge_dmxdev_init drivers/media/test-drivers/vidtv/vidtv_bridge.c:343 [inline]
vidtv_bridge_dvb_init drivers/media/test-drivers/vidtv/vidtv_bridge.c:445 [inline]
vidtv_bridge_probe+0x75d/0xa90 drivers/media/test-drivers/vidtv/vidtv_bridge.c:508
platform_probe+0x106/0x1d0 drivers/base/platform.c:1405
call_driver_probe drivers/base/dd.c:581 [inline]
really_probe+0x241/0xa90 drivers/base/dd.c:659
__driver_probe_device+0x1de/0x440 drivers/base/dd.c:801
driver_probe_device+0x4c/0x1b0 drivers/base/dd.c:831
__driver_attach+0x283/0x580 drivers/base/dd.c:1217
bus_for_each_dev+0x13e/0x1d0 drivers/base/bus.c:370
bus_add_driver+0x2e9/0x690 drivers/base/bus.c:678
driver_register+0x15c/0x4b0 drivers/base/driver.c:249
vidtv_bridge_init+0x45/0x80 drivers/media/test-drivers/vidtv/vidtv_bridge.c:598
do_one_initcall+0x123/0x6e0 init/main.c:1283
do_initcall_level init/main.c:1345 [inline]
do_initcalls init/main.c:1361 [inline]
do_basic_setup init/main.c:1380 [inline]
kernel_init_freeable+0x5c8/0x920 init/main.c:1593
kernel_init+0x1c/0x2b0 init/main.c:1483
ret_from_fork+0x675/0x7d0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
The buggy address belongs to the object at ffff888141a87e00
which belongs to the cache kmalloc-256 of size 256
The buggy address is located 48 bytes to the right of
allocated 216-byte region [ffff888141a87e00, ffff888141a87ed8)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x141a86
head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
anon flags: 0x57ff00000000040(head|node=1|zone=2|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 057ff00000000040 ffff88813ffa6b40 ffffea0001fdc480 0000000000000005
raw: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
head: 057ff00000000040 ffff88813ffa6b40 ffffea0001fdc480 0000000000000005
head: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
head: 057ff00000000001 ffffea000506a181 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 1, tgid 1 (swapper/0), ts 19365672156, free_ts 0
set_page_owner include/linux/page_owner.h:32 [inline]
post_alloc_hook+0x1af/0x220 mm/page_alloc.c:1845
prep_new_page mm/page_alloc.c:1853 [inline]
get_page_from_freelist+0x10a3/0x3a30 mm/page_alloc.c:3879
__alloc_frozen_pages_noprof+0x25f/0x2470 mm/page_alloc.c:5178
alloc_pages_mpol+0x1fb/0x550 mm/mempolicy.c:2416
alloc_slab_page mm/slub.c:3059 [inline]
allocate_slab mm/slub.c:3232 [inline]
new_slab+0x24a/0x360 mm/slub.c:3286
___slab_alloc+0xd79/0x1a50 mm/slub.c:4655
__slab_alloc.constprop.0+0x63/0x110 mm/slub.c:4778
__slab_alloc_node mm/slub.c:4854 [inline]
slab_alloc_node mm/slub.c:5276 [inline]
__kmalloc_cache_noprof+0x477/0x780 mm/slub.c:5766
kmalloc_noprof include/linux/slab.h:957 [inline]
kzalloc_noprof include/linux/slab.h:1094 [inline]
bus_add_driver+0x92/0x690 drivers/base/bus.c:662
driver_register+0x15c/0x4b0 drivers/base/driver.c:249
usb_register_driver+0x216/0x4d0 drivers/usb/core/driver.c:1078
do_one_initcall+0x123/0x6e0 init/main.c:1283
do_initcall_level init/main.c:1345 [inline]
do_initcalls init/main.c:1361 [inline]
do_basic_setup init/main.c:1380 [inline]
kernel_init_freeable+0x5c8/0x920 init/main.c:1593
kernel_init+0x1c/0x2b0 init/main.c:1483
ret_from_fork+0x675/0x7d0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
page_owner free stack trace missing
Memory state around the buggy address:
ffff888141a87e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff888141a87e80: 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc
>ffff888141a87f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
^
ffff888141a87f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff888141a88000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==================================================================
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* Re: [PATCH v4 15/17] module: Introduce hash-based integrity checking
From: Nicolas Schier @ 2026-02-06 17:12 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Petr Pavlu, Nathan Chancellor, Arnd Bergmann, Luis Chamberlain,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <28cf8d51-7530-41d5-a47b-cad5ecabd269@t-8ch.de>
On Tue, Feb 03, 2026 at 01:55:05PM +0100, Thomas Weißschuh wrote:
> On 2026-01-30 18:06:20+0100, Petr Pavlu wrote:
> > On 1/13/26 1:28 PM, Thomas Weißschuh wrote:
> > > Normally the .ko module files depend on a fully built vmlinux to be
> > > available for modpost validation and BTF generation. With
> > > CONFIG_MODULE_HASHES, vmlinux now depends on the modules
> > > to build a merkle tree. This introduces a dependency cycle which is
> > > impossible to satisfy. Work around this by building the modules during
> > > link-vmlinux.sh, after vmlinux is complete enough for modpost and BTF
> > > but before the final module hashes are
> >
> > I wonder if this dependency cycle could be resolved by utilizing the
> > split into vmlinux.unstripped and vmlinux that occurred last year.
> >
> > The idea is to create the following ordering: vmlinux.unstripped ->
> > modules -> vmlinux, and to patch in .module_hashes only when building
> > the final vmlinux.
> >
> > This would require the following:
> > * Split scripts/Makefile.vmlinux into two Makefiles, one that builds the
> > current vmlinux.unstripped and the second one that builds the final
> > vmlinux from it.
> > * Modify the top Makefile to recognize vmlinux.unstripped and update the
> > BTF generation rule 'modules: vmlinux' to
> > 'modules: vmlinux.unstripped'.
> > * Add the 'vmlinux: modules' ordering in the top Makefile for
> > CONFIG_MODULE_HASHES=y.
> > * Remove the patching of vmlinux.unstripped in scripts/link-vmlinux.sh
> > and instead move it into scripts/Makefile.vmlinux when running objcopy
> > to produce the final vmlinux.
> >
> > I think this approach has two main advantages:
> > * CONFIG_MODULE_HASHES can be made orthogonal to
> > CONFIG_DEBUG_INFO_BTF_MODULES.
> > * All dependencies are expressed at the Makefile level instead of having
> > scripts/link-vmlinux.sh invoke 'make -f Makefile modules'.
> >
> > Below is a rough prototype that applies on top of this series. It is a
> > bit verbose due to the splitting of part of scripts/Makefile.vmlinux
> > into scripts/Makefile.vmlinux_unstripped.
>
> That looks like a feasible alternative. Before adopting it, I'd like to
> hear the preference of the kbuild folks.
After the first run-through, the proposed alternative sounds good.
Unfortunately, I ran out of time for this week. I can give a more
founded reply in a few days.
Kind regards,
Nicolas
> > diff --git a/Makefile b/Makefile
> > index 841772a5a260..19a3beb82fa7 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -1259,7 +1259,7 @@ vmlinux_o: vmlinux.a $(KBUILD_VMLINUX_LIBS)
> > vmlinux.o modules.builtin.modinfo modules.builtin: vmlinux_o
> > @:
> >
> > -PHONY += vmlinux
> > +PHONY += vmlinux.unstripped vmlinux
> > # LDFLAGS_vmlinux in the top Makefile defines linker flags for the top vmlinux,
> > # not for decompressors. LDFLAGS_vmlinux in arch/*/boot/compressed/Makefile is
> > # unrelated; the decompressors just happen to have the same base name,
> > @@ -1270,9 +1270,11 @@ PHONY += vmlinux
> > # https://savannah.gnu.org/bugs/?61463
> > # For Make > 4.4, the following simple code will work:
> > # vmlinux: private export LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
> > -vmlinux: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
> > -vmlinux: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
> > -vmlinux: vmlinux.o $(KBUILD_LDS) modpost
> > +vmlinux.unstripped: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
> > +vmlinux.unstripped: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
> > +vmlinux.unstripped: vmlinux.o $(KBUILD_LDS) modpost
> > + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vmlinux_unstripped
> > +vmlinux: vmlinux.unstripped
> > $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vmlinux
>
> Maybe we could keep them together in a single Makefile,
> and instead have different targets in it.
>
> (...)
>
> > @@ -98,70 +44,15 @@ remove-symbols := -w --strip-unneeded-symbol='__mod_device_table__*'
> > # To avoid warnings: "empty loadable segment detected at ..." from GNU objcopy,
> > # it is necessary to remove the PT_LOAD flag from the segment.
> > quiet_cmd_strip_relocs = OBJCOPY $@
> > - cmd_strip_relocs = $(OBJCOPY) $(patsubst %,--set-section-flags %=noload,$(remove-section-y)) $< $@; \
> > - $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) $(remove-symbols) $@
> > + cmd_script_relocs = $(OBJCOPY) $(patsubst %,--set-section-flags %=noload,$(remove-section-y)) $< $@; \
> > + $(OBJCOPY) $(addprefix --remove-section=,$(remove-section-y)) \
> > + $(remove-symbols) \
> > + $(patch-module-hashes) $@
>
> cmd_script_relocs -> cmd_strip_relocs
>
> (...)
--
Nicolas
^ permalink raw reply
* Re: [PATCH v4 07/17] kbuild: generate module BTF based on vmlinux.unstripped
From: Nicolas Schier @ 2026-02-06 16:37 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-7-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:51PM +0100, Thomas Weißschuh wrote:
> The upcoming module hashes functionality will build the modules in
> between the generation of the BTF data and the final link of vmlinux.
> At this point vmlinux is not yet built and therefore can't be used for
> module BTF generation. vmlinux.unstripped however is usable and
> sufficient for BTF generation.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> scripts/Makefile.modfinal | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> index adfef1e002a9..930db0524a0a 100644
> --- a/scripts/Makefile.modfinal
> +++ b/scripts/Makefile.modfinal
> @@ -40,11 +40,11 @@ quiet_cmd_ld_ko_o = LD [M] $@
>
> quiet_cmd_btf_ko = BTF [M] $@
> cmd_btf_ko = \
> - if [ ! -f $(objtree)/vmlinux ]; then \
> - printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \
> + if [ ! -f $(objtree)/vmlinux.unstripped ]; then \
> + printf "Skipping BTF generation for %s due to unavailability of vmlinux.unstripped\n" $@ 1>&2; \
> else \
> - LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base $(objtree)/vmlinux $@; \
> - $(RESOLVE_BTFIDS) -b $(objtree)/vmlinux $@; \
> + LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base $(objtree)/vmlinux.unstripped $@; \
> + $(RESOLVE_BTFIDS) -b $(objtree)/vmlinux.unstripped $@; \
Reviewed-by: Nicolas Schier <nsc@kernel.org> # kbuild
I'd like to have some BTF ack for that.
--
Nicolas
^ permalink raw reply
* Re: [PATCH v4 06/17] kbuild: add stamp file for vmlinux BTF data
From: Nicolas Schier @ 2026-02-06 16:28 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-6-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:50PM +0100, Thomas Weißschuh wrote:
> The upcoming module hashes functionality will build the modules in
> between the generation of the BTF data and the final link of vmlinux.
> Having a dependency from the modules on vmlinux would make this
> impossible as it would mean having a cyclic dependency.
> Break this cyclic dependency by introducing a new target.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> scripts/Makefile.modfinal | 4 ++--
> scripts/link-vmlinux.sh | 6 ++++++
> 2 files changed, 8 insertions(+), 2 deletions(-)
>
Reviewed-by: Nicolas Schier <nsc@kernel.org>
^ permalink raw reply
* [GIT PULL] x509, pkcs7: Add support for ML-DSA signatures
From: David Howells @ 2026-02-06 13:33 UTC (permalink / raw)
To: Linus Torvalds
Cc: dhowells, Lukas Wunner, Ignat Korchagin, Jarkko Sakkinen,
Herbert Xu, Eric Biggers, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Jason A . Donenfeld, Ard Biesheuvel,
Stephan Mueller, linux-crypto, keyrings, linux-modules,
linux-kernel
Hi Linus,
Could you pull this patchset in the upcoming merge window please? It adds
support for ML-DSA signatures in X.509 certificates and PKCS#7/CMS
messages, thereby allowing this algorithm to be used for signing modules,
kexec'able binaries, wifi regulatory data, etc..
This requires OpenSSL-3.5 at a minimum and preferably OpenSSL-4 (so that it
can avoid the use of CMS signedAttrs - but that version is not cut yet).
certs/Kconfig does a check to hide the signing options if OpenSSL does not
list the algorithm as being available.
Note that this is dependent on Eric Bigger's libcrypto (for the core ML-DSA
implementation) and would need to be pulled after that.
Note also that this has a conflict with the modules tree which has a patch
to unconditionally use the OpenSSL CMS_* API to generate signatures in
scripts/sign-file.c and to remove fallback use of the PKCS7_* API. I've
added an illustrative merge at the top of my keys-pqc branch for reference
purposes.
The patches were last posted here:
https://lore.kernel.org/r/20260202170216.2467036-1-dhowells@redhat.com/
Thanks,
David
---
The following changes since commit 959a634ebcda02e0add101024a5793323d66cda5:
lib/crypto: mldsa: Add FIPS cryptographic algorithm self-test (2026-01-12 11:07:50 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git tags/keys-next-20260206
for you to fetch changes up to 965e9a2cf23b066d8bdeb690dff9cd7089c5f667:
pkcs7: Change a pr_warn() to pr_warn_once() (2026-02-05 15:44:00 +0000)
----------------------------------------------------------------
keys: Support for ML-DSA module signing
----------------------------------------------------------------
David Howells (8):
crypto: Add ML-DSA crypto_sig support
x509: Separately calculate sha256 for blacklist
pkcs7, x509: Rename ->digest to ->m
pkcs7: Allow the signing algo to do whatever digestion it wants itself
pkcs7, x509: Add ML-DSA support
modsign: Enable ML-DSA module signing
pkcs7: Allow authenticatedAttributes for ML-DSA
pkcs7: Change a pr_warn() to pr_warn_once()
Documentation/admin-guide/module-signing.rst | 16 ++-
certs/Kconfig | 40 ++++++
certs/Makefile | 3 +
crypto/Kconfig | 9 ++
crypto/Makefile | 2 +
crypto/asymmetric_keys/Kconfig | 11 ++
crypto/asymmetric_keys/asymmetric_type.c | 4 +-
crypto/asymmetric_keys/pkcs7_parser.c | 36 ++++-
crypto/asymmetric_keys/pkcs7_parser.h | 3 +
crypto/asymmetric_keys/pkcs7_verify.c | 78 +++++++----
crypto/asymmetric_keys/public_key.c | 13 +-
crypto/asymmetric_keys/signature.c | 3 +-
crypto/asymmetric_keys/x509_cert_parser.c | 27 +++-
crypto/asymmetric_keys/x509_parser.h | 2 +
crypto/asymmetric_keys/x509_public_key.c | 42 ++++--
crypto/mldsa.c | 201 +++++++++++++++++++++++++++
include/crypto/public_key.h | 6 +-
include/linux/oid_registry.h | 5 +
scripts/sign-file.c | 39 ++++--
security/integrity/digsig_asymmetric.c | 4 +-
20 files changed, 473 insertions(+), 71 deletions(-)
create mode 100644 crypto/mldsa.c
^ permalink raw reply
* Re: [PATCH v4 05/17] module: Switch load_info::len to size_t
From: Thomas Weißschuh @ 2026-02-06 9:18 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Nicolas Schier, Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <ffdafd21-fe7a-44a2-86ec-0e0c2ad4238c@kernel.org>
On 2026-02-06 10:09:12+0100, Christophe Leroy (CS GROUP) wrote:
>
>
> Le 13/01/2026 à 13:28, Thomas Weißschuh a écrit :
> > Switching the types will make some later changes cleaner.
> > size_t is also the semantically correct type for this field.
> >
> > As both 'size_t' and 'unsigned int' are always the same size, this
> > should be risk-free.
> Are you sure ?
As mentioned before by David [0], this should have been 'unsigned long'
instead of 'unsigned int'. Which is also what the diff shows.
> Some architectures have size_t as 'unsigned int', some have 'unsigned long',
> some have 'unsigned long long'
(...)
[0] https://lore.kernel.org/lkml/2919071.1770365933@warthog.procyon.org.uk/
^ permalink raw reply
* Re: [PATCH v4 05/17] module: Switch load_info::len to size_t
From: Christophe Leroy (CS GROUP) @ 2026-02-06 9:09 UTC (permalink / raw)
To: Thomas Weißschuh, Nathan Chancellor, Arnd Bergmann,
Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
Paul Moore, James Morris, Serge E. Hallyn, Jonathan Corbet,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Naveen N Rao, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Nicolas Schier, Daniel Gomez, Aaron Tomlin,
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng
Cc: Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-5-0b932db9b56b@weissschuh.net>
Le 13/01/2026 à 13:28, Thomas Weißschuh a écrit :
> Switching the types will make some later changes cleaner.
> size_t is also the semantically correct type for this field.
>
> As both 'size_t' and 'unsigned int' are always the same size, this
> should be risk-free.
Are you sure ?
Some architectures have size_t as 'unsigned int', some have 'unsigned
long', some have 'unsigned long long'
https://elixir.bootlin.com/linux/v6.19-rc5/source/arch/s390/include/uapi/asm/posix_types.h#L16
https://elixir.bootlin.com/linux/v6.19-rc5/source/arch/sparc/include/uapi/asm/posix_types.h#L35
https://elixir.bootlin.com/linux/v6.19-rc5/source/arch/xtensa/include/uapi/asm/posix_types.h#L26
https://elixir.bootlin.com/linux/v6.19-rc5/source/include/uapi/asm-generic/posix_types.h#L68
https://elixir.bootlin.com/linux/v6.19-rc5/source/include/uapi/asm-generic/posix_types.h#L72
https://elixir.bootlin.com/linux/v6.19-rc5/source/arch/sparc/include/uapi/asm/posix_types.h#L23
https://elixir.bootlin.com/linux/v6.19-rc5/source/arch/x86/include/uapi/asm/posix_types_x32.h#L15
https://elixir.bootlin.com/linux/v6.19-rc5/source/include/uapi/asm-generic/posix_types.h#L16
Christophe
^ permalink raw reply
* Re: [PATCH v4 05/17] module: Switch load_info::len to size_t
From: Nicolas Schier @ 2026-02-06 8:55 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <8fd4914d-5cff-4030-822c-98c8e76d0e60@t-8ch.de>
On Fri, Feb 06, 2026 at 09:38:07AM +0100, Thomas Weißschuh wrote:
> On 2026-02-06 09:30:08+0100, Nicolas Schier wrote:
> > On Tue, Jan 13, 2026 at 01:28:49PM +0100, Thomas Weißschuh wrote:
> > > Switching the types will make some later changes cleaner.
> > > size_t is also the semantically correct type for this field.
> > >
> > > As both 'size_t' and 'unsigned int' are always the same size, this
> > > should be risk-free.
> >
> > include/uapi/asm-generic/posix_types.h states:
> > | * Most 32 bit architectures use "unsigned int" size_t,
> > | * and all 64 bit architectures use "unsigned long" size_t.
> >
> > Is that statement wrong? Or did I mix up the context?
>
> That statement is correct. But as both 'unsigned int' and 'unsigned
> long' are 32-bit wide on 32-bit Linux platforms they are compatible.
>
>
> Thomas
sure, thanks!
Acked-by: Nicolas Schier <nsc@kernel.org>
--
Nicolas
^ permalink raw reply
* Re: [PATCH v4 05/17] module: Switch load_info::len to size_t
From: Thomas Weißschuh @ 2026-02-06 8:38 UTC (permalink / raw)
To: Nicolas Schier, Nathan Chancellor, Arnd Bergmann,
Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
Paul Moore, James Morris, Serge E. Hallyn, Jonathan Corbet,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Naveen N Rao, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Daniel Gomez, Aaron Tomlin,
Christophe Leroy (CS GROUP), Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <aYWmkEzjvo9RrzI9@levanger>
On 2026-02-06 09:30:08+0100, Nicolas Schier wrote:
> On Tue, Jan 13, 2026 at 01:28:49PM +0100, Thomas Weißschuh wrote:
> > Switching the types will make some later changes cleaner.
> > size_t is also the semantically correct type for this field.
> >
> > As both 'size_t' and 'unsigned int' are always the same size, this
> > should be risk-free.
>
> include/uapi/asm-generic/posix_types.h states:
> | * Most 32 bit architectures use "unsigned int" size_t,
> | * and all 64 bit architectures use "unsigned long" size_t.
>
> Is that statement wrong? Or did I mix up the context?
That statement is correct. But as both 'unsigned int' and 'unsigned
long' are 32-bit wide on 32-bit Linux platforms they are compatible.
Thomas
^ permalink raw reply
* Re: [PATCH v4 05/17] module: Switch load_info::len to size_t
From: Thomas Weißschuh @ 2026-02-06 8:34 UTC (permalink / raw)
To: David Howells
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Nicolas Schier,
Daniel Gomez, Aaron Tomlin, Christophe Leroy (CS GROUP),
Nicolas Schier, Nicolas Bouchinet, Xiu Jianfeng,
Fabian Grünbichler, Arnout Engelen, Mattia Rizzolo, kpcyrd,
Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <2919071.1770365933@warthog.procyon.org.uk>
On 2026-02-06 08:18:53+0000, David Howells wrote:
> Thomas Weißschuh <linux@weissschuh.net> wrote:
>
> > As both 'size_t' and 'unsigned int' are always the same size, this
> > should be risk-free.
>
> Did you mean 'unsigned long'?
Indeed, I'll fix it for the next revision.
Thomas
^ permalink raw reply
* Re: [PATCH v4 05/17] module: Switch load_info::len to size_t
From: Nicolas Schier @ 2026-02-06 8:30 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-5-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:49PM +0100, Thomas Weißschuh wrote:
> Switching the types will make some later changes cleaner.
> size_t is also the semantically correct type for this field.
>
> As both 'size_t' and 'unsigned int' are always the same size, this
> should be risk-free.
include/uapi/asm-generic/posix_types.h states:
| * Most 32 bit architectures use "unsigned int" size_t,
| * and all 64 bit architectures use "unsigned long" size_t.
Is that statement wrong? Or did I mix up the context?
Kind regards,
Nicolas
^ permalink raw reply
* Re: [PATCH v4 04/17] module: Make mod_verify_sig() static
From: Nicolas Schier @ 2026-02-06 8:25 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Arnd Bergmann, Luis Chamberlain, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Paul Moore, James Morris,
Serge E. Hallyn, Jonathan Corbet, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Naveen N Rao, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Daniel Gomez,
Aaron Tomlin, Christophe Leroy (CS GROUP), Nicolas Bouchinet,
Xiu Jianfeng, Fabian Grünbichler, Arnout Engelen,
Mattia Rizzolo, kpcyrd, Christian Heusel, Câju Mihai-Drosi,
Sebastian Andrzej Siewior, linux-kbuild, linux-kernel, linux-arch,
linux-modules, linux-security-module, linux-doc, linuxppc-dev,
linux-integrity
In-Reply-To: <20260113-module-hashes-v4-4-0b932db9b56b@weissschuh.net>
On Tue, Jan 13, 2026 at 01:28:48PM +0100, Thomas Weißschuh wrote:
> It is not used outside of signing.c.
>
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
> kernel/module/internal.h | 1 -
> kernel/module/signing.c | 2 +-
> 2 files changed, 1 insertion(+), 2 deletions(-)
>
Reviewed-by: Nicolas Schier <nsc@kernel.org>
--
Nicolas
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox