Module-related stubs for CONFIG_MODULES=n can normally live in linux/module.h. This works well when the stub does nothing or simply returns a constant. However, some non-module implementations may be more expensive, either because they have a real implementation or because they require additional dependencies to be pulled into linux/module.h. This header appears in roughly 15k #include directives across the kernel, so it should avoid bringing in unnecessary definitions.
Specifically, linux/module.h defines module_put_and_kthread_exit() as an alias for kthread_exit() when CONFIG_MODULES=n. That in turn requires linux/kthread.h, even though linux/module.h otherwise has no need for it. Note that linux/module.h currently doesn't include linux/kthread.h and requires its users to pick it up through other paths, which is itself not quite right. Introduce kernel/module/stubs.c to hold such stubs, built only for CONFIG_MODULES=n. This mirrors kernel/time/posix-stubs.c, which is used for CONFIG_POSIX_TIMERS=n. Define module_put_and_kthread_exit() in both CONFIG_MODULES configurations to call __module_put_and_kthread_exit() and add a CONFIG_MODULES=n implementation of that function to kernel/module/stubs.c. Since __module_put_and_kthread_exit() is now implemented even when CONFIG_MODULES=n, remove the corresponding '#ifdef CONFIG_MODULES' from the noreturn_deny BPF list. Signed-off-by: Petr Pavlu <[email protected]> --- kernel/module/stubs.c should also be used for add_taint_module() [1] in the future. [1] https://lore.kernel.org/linux-modules/[email protected]/ --- include/linux/module.h | 9 +++------ kernel/Makefile | 2 +- kernel/bpf/verifier.c | 2 -- kernel/module/Makefile | 4 ++++ kernel/module/main.c | 1 + kernel/module/stubs.c | 11 +++++++++++ 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/linux/module.h b/include/linux/module.h index 96cc98568eea..4c7bd7f9f889 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -658,10 +658,6 @@ static inline bool within_module(unsigned long addr, const struct module *mod) /* Search for module by name: must be in a RCU critical section. */ struct module *find_module(const char *name); -extern void __noreturn __module_put_and_kthread_exit(struct module *mod, - long code); -#define module_put_and_kthread_exit(code) __module_put_and_kthread_exit(THIS_MODULE, code) - #ifdef CONFIG_MODULE_UNLOAD int module_refcount(struct module *mod); void __symbol_put(const char *symbol); @@ -850,8 +846,6 @@ static inline int unregister_module_notifier(struct notifier_block *nb) return 0; } -#define module_put_and_kthread_exit(code) kthread_exit(code) - static inline void print_modules(void) { } @@ -879,6 +873,9 @@ static inline void module_for_each_mod(int(*func)(struct module *mod, void *data } #endif /* CONFIG_MODULES */ +void __noreturn __module_put_and_kthread_exit(struct module *mod, long code); +#define module_put_and_kthread_exit(code) __module_put_and_kthread_exit(THIS_MODULE, code) + #ifdef CONFIG_SYSFS extern struct kset *module_kset; extern const struct kobj_type module_ktype; diff --git a/kernel/Makefile b/kernel/Makefile index 1e1a31673577..08a94594975d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -58,7 +58,7 @@ obj-y += liveupdate/ obj-y += dma/ obj-y += entry/ obj-y += unwind/ -obj-$(CONFIG_MODULES) += module/ +obj-y += module/ obj-$(CONFIG_KCMP) += kcmp.o obj-$(CONFIG_FREEZER) += freezer.o diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 72a3f5998dd2..be70f10e4968 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20417,9 +20417,7 @@ BTF_ID(func, __ia32_sys_exit_group) BTF_ID(func, __kunit_abort) BTF_ID(func, kunit_try_catch_throw) #endif -#ifdef CONFIG_MODULES BTF_ID(func, __module_put_and_kthread_exit) -#endif #ifdef CONFIG_X86_64 BTF_ID(func, __x64_sys_exit) BTF_ID(func, __x64_sys_exit_group) diff --git a/kernel/module/Makefile b/kernel/module/Makefile index 50ffcc413b54..72fd2972eacf 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -7,6 +7,7 @@ # and produce insane amounts of uninteresting coverage. KCOV_INSTRUMENT_main.o := n +ifeq ($(CONFIG_MODULES),y) obj-y += main.o obj-y += strict_rwx.o obj-y += kmod.o @@ -23,3 +24,6 @@ obj-$(CONFIG_KGDB_KDB) += kdb.o obj-$(CONFIG_MODVERSIONS) += version.o obj-$(CONFIG_MODULE_UNLOAD_TAINT_TRACKING) += tracking.o obj-$(CONFIG_MODULE_STATS) += stats.o +else +obj-y += stubs.o +endif diff --git a/kernel/module/main.c b/kernel/module/main.c index d0e1e0bd2ad0..a8bf803afa81 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -60,6 +60,7 @@ #include <linux/codetag.h> #include <linux/debugfs.h> #include <linux/execmem.h> +#include <linux/kthread.h> #include <uapi/linux/module.h> #include "internal.h" diff --git a/kernel/module/stubs.c b/kernel/module/stubs.c new file mode 100644 index 000000000000..81e66c02260c --- /dev/null +++ b/kernel/module/stubs.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <linux/kthread.h> +#include <linux/module.h> +#include "internal.h" + +void __noreturn __module_put_and_kthread_exit(struct module *mod, long code) +{ + kthread_exit(code); +} +EXPORT_SYMBOL(__module_put_and_kthread_exit); --- base-commit: 93f51579e7df248780214094418f205253383cc5 change-id: 20260918-module-stubs-dccefe41dace

