From deffe1edba626d474fef38007c03646ca5876a0e Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Fri, 13 Mar 2026 14:48:02 +0100 Subject: module: Fix freeing of charp module parameters when CONFIG_SYSFS=n When setting a charp module parameter, the param_set_charp() function allocates memory to store a copy of the input value. Later, when the module is potentially unloaded, the destroy_params() function is called to free this allocated memory. However, destroy_params() is available only when CONFIG_SYSFS=y, otherwise only a dummy variant is present. In the unlikely case that the kernel is configured with CONFIG_MODULES=y and CONFIG_SYSFS=n, this results in a memory leak of charp values when a module is unloaded. Fix this issue by making destroy_params() always available when CONFIG_MODULES=y. Rename the function to module_destroy_params() to clarify that it is intended for use by the module loader. Fixes: e180a6b7759a ("param: fix charp parameters set via sysfs") Signed-off-by: Petr Pavlu Signed-off-by: Sami Tolvanen --- kernel/module/main.c | 4 ++-- kernel/params.c | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'kernel') diff --git a/kernel/module/main.c b/kernel/module/main.c index c3ce106c70af..ef2e2130972f 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1408,7 +1408,7 @@ static void free_module(struct module *mod) module_unload_free(mod); /* Free any allocated parameters. */ - destroy_params(mod->kp, mod->num_kp); + module_destroy_params(mod->kp, mod->num_kp); if (is_livepatch_module(mod)) free_module_elf(mod); @@ -3519,7 +3519,7 @@ static int load_module(struct load_info *info, const char __user *uargs, mod_sysfs_teardown(mod); coming_cleanup: mod->state = MODULE_STATE_GOING; - destroy_params(mod->kp, mod->num_kp); + module_destroy_params(mod->kp, mod->num_kp); blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_GOING, mod); klp_module_going(mod); diff --git a/kernel/params.c b/kernel/params.c index 7188a12dbe86..c6a354d54213 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -745,15 +745,6 @@ void module_param_sysfs_remove(struct module *mod) } #endif -void destroy_params(const struct kernel_param *params, unsigned num) -{ - unsigned int i; - - for (i = 0; i < num; i++) - if (params[i].ops->free) - params[i].ops->free(params[i].arg); -} - struct module_kobject * __init_or_module lookup_or_create_module_kobject(const char *name) { @@ -985,3 +976,21 @@ static int __init param_sysfs_builtin_init(void) late_initcall(param_sysfs_builtin_init); #endif /* CONFIG_SYSFS */ + +#ifdef CONFIG_MODULES + +/* + * module_destroy_params - free all parameters for one module + * @params: module parameters (array) + * @num: number of module parameters + */ +void module_destroy_params(const struct kernel_param *params, unsigned int num) +{ + unsigned int i; + + for (i = 0; i < num; i++) + if (params[i].ops->free) + params[i].ops->free(params[i].arg); +} + +#endif /* CONFIG_MODULES */ -- cgit v1.2.3 From 65f535501e2a3378629b8650eca553920de5e5a2 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Fri, 13 Mar 2026 14:48:03 +0100 Subject: module: Clean up parse_args() arguments * Use the preferred `unsigned int` over plain `unsigned` for the `num` parameter. * Synchronize the parameter names in moduleparam.h with the ones used by the implementation in params.c. Signed-off-by: Petr Pavlu Signed-off-by: Sami Tolvanen --- kernel/params.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/params.c b/kernel/params.c index c6a354d54213..74d620bc2521 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -161,7 +161,7 @@ static int parse_one(char *param, char *parse_args(const char *doing, char *args, const struct kernel_param *params, - unsigned num, + unsigned int num, s16 min_level, s16 max_level, void *arg, parse_unknown_fn unknown) -- cgit v1.2.3 From 3fe1dcbc2d20c5dbc581c0bb458e05365bfffcf7 Mon Sep 17 00:00:00 2001 From: Nicholas Sielicki Date: Sat, 7 Mar 2026 03:00:09 -0600 Subject: module: expose imported namespaces via sysfs Add /sys/module/*/import_ns to expose imported namespaces for currently loaded modules. The file contains one namespace per line and only exists for modules that import at least one namespace. Previously, the only way for userspace to inspect the symbol namespaces a module imports is to locate the .ko on disk and invoke modinfo(8) to decompress/parse the metadata. The kernel validated namespaces at load time, but it was otherwise discarded. Exposing this data via sysfs provides a runtime mechanism to verify which namespaces are being used by modules. For example, this allows userspace to audit driver API access in Android GKI, which uses symbol namespaces to restrict vendor drivers from using specific kernel interfaces (e.g., direct filesystem access). Signed-off-by: Nicholas Sielicki [Sami: Updated the commit message to explain motivation.] Signed-off-by: Sami Tolvanen --- kernel/module/main.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/module/main.c b/kernel/module/main.c index ef2e2130972f..fc033137863d 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -607,6 +607,36 @@ static const struct module_attribute modinfo_##field = { \ MODINFO_ATTR(version); MODINFO_ATTR(srcversion); +static void setup_modinfo_import_ns(struct module *mod, const char *s) +{ + mod->imported_namespaces = NULL; +} + +static ssize_t show_modinfo_import_ns(const struct module_attribute *mattr, + struct module_kobject *mk, char *buffer) +{ + return sysfs_emit(buffer, "%s\n", mk->mod->imported_namespaces); +} + +static int modinfo_import_ns_exists(struct module *mod) +{ + return mod->imported_namespaces != NULL; +} + +static void free_modinfo_import_ns(struct module *mod) +{ + kfree(mod->imported_namespaces); + mod->imported_namespaces = NULL; +} + +static const struct module_attribute modinfo_import_ns = { + .attr = { .name = "import_ns", .mode = 0444 }, + .show = show_modinfo_import_ns, + .setup = setup_modinfo_import_ns, + .test = modinfo_import_ns_exists, + .free = free_modinfo_import_ns, +}; + static struct { char name[MODULE_NAME_LEN]; char taints[MODULE_FLAGS_BUF_SIZE]; @@ -1058,6 +1088,7 @@ const struct module_attribute *const modinfo_attrs[] = { &module_uevent, &modinfo_version, &modinfo_srcversion, + &modinfo_import_ns, &modinfo_initstate, &modinfo_coresize, #ifdef CONFIG_ARCH_WANTS_MODULES_DATA_IN_VMALLOC @@ -1760,11 +1791,43 @@ static void module_license_taint_check(struct module *mod, const char *license) } } +static int copy_modinfo_import_ns(struct module *mod, struct load_info *info) +{ + char *ns; + size_t len, total_len = 0; + char *buf, *p; + + for_each_modinfo_entry(ns, info, "import_ns") + total_len += strlen(ns) + 1; + + if (!total_len) { + mod->imported_namespaces = NULL; + return 0; + } + + buf = kmalloc(total_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + p = buf; + for_each_modinfo_entry(ns, info, "import_ns") { + len = strlen(ns); + memcpy(p, ns, len); + p += len; + *p++ = '\n'; + } + /* Replace trailing newline with null terminator. */ + *(p - 1) = '\0'; + + mod->imported_namespaces = buf; + return 0; +} + static int setup_modinfo(struct module *mod, struct load_info *info) { const struct module_attribute *attr; char *imported_namespace; - int i; + int i, err; for (i = 0; (attr = modinfo_attrs[i]); i++) { if (attr->setup) @@ -1783,6 +1846,10 @@ static int setup_modinfo(struct module *mod, struct load_info *info) } } + err = copy_modinfo_import_ns(mod, info); + if (err) + return err; + return 0; } -- cgit v1.2.3 From acd87264af525dba6e9355310e8acdf066a5f6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Thu, 5 Mar 2026 10:31:39 +0100 Subject: module: Give 'enum pkey_id_type' a more specific name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enum originates in generic cryptographic code and has a very generic name. Nowadays it is only used for module signatures. As this enum is going to be exposed in a UAPI header, give it a more specific name for clarity and consistency. Signed-off-by: Thomas Weißschuh Reviewed-by: Petr Pavlu Reviewed-by: Nicolas Schier Signed-off-by: Sami Tolvanen --- kernel/module_signature.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/module_signature.c b/kernel/module_signature.c index 00132d12487c..a0eee2fe4368 100644 --- a/kernel/module_signature.c +++ b/kernel/module_signature.c @@ -24,7 +24,7 @@ int mod_check_sig(const struct module_signature *ms, size_t file_len, if (be32_to_cpu(ms->sig_len) >= file_len - sizeof(*ms)) return -EBADMSG; - if (ms->id_type != PKEY_ID_PKCS7) { + if (ms->id_type != MODULE_SIGNATURE_TYPE_PKCS7) { pr_err("%s: not signed with expected PKCS#7 message\n", name); return -ENOPKG; -- cgit v1.2.3 From 2ae4ea2d9aaf25cb74fbc23450b1b8f0a5b7aa89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Thu, 5 Mar 2026 10:31:40 +0100 Subject: module: Give MODULE_SIG_STRING a more descriptive name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of the constant it is not entirely clear from its name. As this constant is going to be exposed in a UAPI header, give it a more specific name for clarity. As all its users call it 'marker', use that wording in the constant itself. Signed-off-by: Thomas Weißschuh Reviewed-by: Petr Pavlu Reviewed-by: Nicolas Schier Signed-off-by: Sami Tolvanen --- kernel/module/signing.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/module/signing.c b/kernel/module/signing.c index a2ff4242e623..590ba29c85ab 100644 --- a/kernel/module/signing.c +++ b/kernel/module/signing.c @@ -70,7 +70,7 @@ int mod_verify_sig(const void *mod, struct load_info *info) int module_sig_check(struct load_info *info, int flags) { int err = -ENODATA; - const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; + const unsigned long markerlen = sizeof(MODULE_SIGNATURE_MARKER) - 1; const char *reason; const void *mod = info->hdr; bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS | @@ -81,7 +81,7 @@ int module_sig_check(struct load_info *info, int flags) */ if (!mangled_module && info->len > markerlen && - memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { + memcmp(mod + info->len - markerlen, MODULE_SIGNATURE_MARKER, markerlen) == 0) { /* We truncate the module to discard the signature */ info->len -= markerlen; err = mod_verify_sig(mod, info); -- cgit v1.2.3 From 55fcb926b6d8b5cfb40873e4840a69961db1bb69 Mon Sep 17 00:00:00 2001 From: Siddharth Nayyar Date: Thu, 26 Mar 2026 21:25:05 +0000 Subject: module: use kflagstab instead of *_gpl sections Read kflagstab section for vmlinux and modules to determine whether kernel symbols are GPL only. This patch eliminates the need for fragmenting the ksymtab for infering the value of GPL-only symbol flag, henceforth stop populating *_gpl versions of the ksymtab and kcrctab in modpost. Signed-off-by: Siddharth Nayyar Reviewed-by: Petr Pavlu Signed-off-by: Sami Tolvanen --- kernel/module/internal.h | 1 + kernel/module/main.c | 55 +++++++++++++++++++++++++----------------------- 2 files changed, 30 insertions(+), 26 deletions(-) (limited to 'kernel') diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 618202578b42..69b84510e097 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -57,6 +57,7 @@ extern const struct kernel_symbol __start___ksymtab_gpl[]; extern const struct kernel_symbol __stop___ksymtab_gpl[]; extern const u32 __start___kcrctab[]; extern const u32 __start___kcrctab_gpl[]; +extern const u8 __start___kflagstab[]; #define KMOD_PATH_LEN 256 extern char modprobe_path[]; diff --git a/kernel/module/main.c b/kernel/module/main.c index fc033137863d..c243d6b79cdd 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -87,7 +88,7 @@ struct mod_tree_root mod_tree __cacheline_aligned = { struct symsearch { const struct kernel_symbol *start, *stop; const u32 *crcs; - enum mod_license license; + const u8 *flagstab; }; /* @@ -364,19 +365,21 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms, struct find_symbol_arg *fsa) { struct kernel_symbol *sym; - - if (!fsa->gplok && syms->license == GPL_ONLY) - return false; + u8 sym_flags; sym = bsearch(fsa->name, syms->start, syms->stop - syms->start, sizeof(struct kernel_symbol), cmp_name); if (!sym) return false; + sym_flags = *(syms->flagstab + (sym - syms->start)); + if (!fsa->gplok && (sym_flags & KSYM_FLAG_GPL_ONLY)) + return false; + fsa->owner = owner; fsa->crc = symversion(syms->crcs, sym - syms->start); fsa->sym = sym; - fsa->license = syms->license; + fsa->license = (sym_flags & KSYM_FLAG_GPL_ONLY) ? GPL_ONLY : NOT_GPL_ONLY; return true; } @@ -387,36 +390,31 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms, */ bool find_symbol(struct find_symbol_arg *fsa) { - static const struct symsearch arr[] = { - { __start___ksymtab, __stop___ksymtab, __start___kcrctab, - NOT_GPL_ONLY }, - { __start___ksymtab_gpl, __stop___ksymtab_gpl, - __start___kcrctab_gpl, - GPL_ONLY }, + const struct symsearch syms = { + .start = __start___ksymtab, + .stop = __stop___ksymtab, + .crcs = __start___kcrctab, + .flagstab = __start___kflagstab, }; struct module *mod; - unsigned int i; - for (i = 0; i < ARRAY_SIZE(arr); i++) - if (find_exported_symbol_in_section(&arr[i], NULL, fsa)) - return true; + if (find_exported_symbol_in_section(&syms, NULL, fsa)) + return true; list_for_each_entry_rcu(mod, &modules, list, lockdep_is_held(&module_mutex)) { - struct symsearch arr[] = { - { mod->syms, mod->syms + mod->num_syms, mod->crcs, - NOT_GPL_ONLY }, - { mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms, - mod->gpl_crcs, - GPL_ONLY }, + const struct symsearch syms = { + .start = mod->syms, + .stop = mod->syms + mod->num_syms, + .crcs = mod->crcs, + .flagstab = mod->flagstab, }; if (mod->state == MODULE_STATE_UNFORMED) continue; - for (i = 0; i < ARRAY_SIZE(arr); i++) - if (find_exported_symbol_in_section(&arr[i], mod, fsa)) - return true; + if (find_exported_symbol_in_section(&syms, mod, fsa)) + return true; } pr_debug("Failed to find symbol %s\n", fsa->name); @@ -2681,6 +2679,7 @@ static int find_module_sections(struct module *mod, struct load_info *info) sizeof(*mod->gpl_syms), &mod->num_gpl_syms); mod->gpl_crcs = section_addr(info, "__kcrctab_gpl"); + mod->flagstab = section_addr(info, "__kflagstab"); #ifdef CONFIG_CONSTRUCTORS mod->ctors = section_objs(info, ".ctors", @@ -2884,8 +2883,12 @@ out_err: return ret; } -static int check_export_symbol_versions(struct module *mod) +static int check_export_symbol_sections(struct module *mod) { + if (mod->num_syms && !mod->flagstab) { + pr_err("%s: no flags for exported symbols\n", mod->name); + return -ENOEXEC; + } #ifdef CONFIG_MODVERSIONS if ((mod->num_syms && !mod->crcs) || (mod->num_gpl_syms && !mod->gpl_crcs)) { @@ -3501,7 +3504,7 @@ static int load_module(struct load_info *info, const char __user *uargs, if (err) goto free_unload; - err = check_export_symbol_versions(mod); + err = check_export_symbol_sections(mod); if (err) goto free_unload; -- cgit v1.2.3 From b4760ff2a5e4351c59d185967735f59c0b0bd7f6 Mon Sep 17 00:00:00 2001 From: Siddharth Nayyar Date: Thu, 26 Mar 2026 21:25:06 +0000 Subject: module: deprecate usage of *_gpl sections in module loader The *_gpl section are not being used populated by modpost anymore. Hence the module loader doesn't need to find and process these sections in modules. This patch also simplifies symbol finding logic in module loader since *_gpl sections don't have to be searched anymore. Signed-off-by: Siddharth Nayyar Reviewed-by: Petr Pavlu Signed-off-by: Sami Tolvanen --- kernel/module/internal.h | 3 --- kernel/module/main.c | 46 ++++++++++++++++++---------------------------- 2 files changed, 18 insertions(+), 31 deletions(-) (limited to 'kernel') diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 69b84510e097..061161cc79d9 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -53,10 +53,7 @@ extern const size_t modinfo_attrs_count; /* Provided by the linker */ extern const struct kernel_symbol __start___ksymtab[]; extern const struct kernel_symbol __stop___ksymtab[]; -extern const struct kernel_symbol __start___ksymtab_gpl[]; -extern const struct kernel_symbol __stop___ksymtab_gpl[]; extern const u32 __start___kcrctab[]; -extern const u32 __start___kcrctab_gpl[]; extern const u8 __start___kflagstab[]; #define KMOD_PATH_LEN 256 diff --git a/kernel/module/main.c b/kernel/module/main.c index c243d6b79cdd..c4f768953516 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1495,29 +1495,17 @@ EXPORT_SYMBOL_GPL(__symbol_get); */ static int verify_exported_symbols(struct module *mod) { - unsigned int i; const struct kernel_symbol *s; - struct { - const struct kernel_symbol *sym; - unsigned int num; - } arr[] = { - { mod->syms, mod->num_syms }, - { mod->gpl_syms, mod->num_gpl_syms }, - }; - - for (i = 0; i < ARRAY_SIZE(arr); i++) { - for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { - struct find_symbol_arg fsa = { - .name = kernel_symbol_name(s), - .gplok = true, - }; - if (find_symbol(&fsa)) { - pr_err("%s: exports duplicate symbol %s" - " (owned by %s)\n", - mod->name, kernel_symbol_name(s), - module_name(fsa.owner)); - return -ENOEXEC; - } + for (s = mod->syms; s < mod->syms + mod->num_syms; s++) { + struct find_symbol_arg fsa = { + .name = kernel_symbol_name(s), + .gplok = true, + }; + if (find_symbol(&fsa)) { + pr_err("%s: exports duplicate symbol %s (owned by %s)\n", + mod->name, kernel_symbol_name(s), + module_name(fsa.owner)); + return -ENOEXEC; } } return 0; @@ -2675,12 +2663,15 @@ static int find_module_sections(struct module *mod, struct load_info *info) mod->syms = section_objs(info, "__ksymtab", sizeof(*mod->syms), &mod->num_syms); mod->crcs = section_addr(info, "__kcrctab"); - mod->gpl_syms = section_objs(info, "__ksymtab_gpl", - sizeof(*mod->gpl_syms), - &mod->num_gpl_syms); - mod->gpl_crcs = section_addr(info, "__kcrctab_gpl"); mod->flagstab = section_addr(info, "__kflagstab"); + if (section_addr(info, "__ksymtab_gpl")) + pr_warn("%s: ignoring obsolete section __ksymtab_gpl\n", + mod->name); + if (section_addr(info, "__kcrctab_gpl")) + pr_warn("%s: ignoring obsolete section __kcrctab_gpl\n", + mod->name); + #ifdef CONFIG_CONSTRUCTORS mod->ctors = section_objs(info, ".ctors", sizeof(*mod->ctors), &mod->num_ctors); @@ -2890,8 +2881,7 @@ static int check_export_symbol_sections(struct module *mod) return -ENOEXEC; } #ifdef CONFIG_MODVERSIONS - if ((mod->num_syms && !mod->crcs) || - (mod->num_gpl_syms && !mod->gpl_crcs)) { + if (mod->num_syms && !mod->crcs) { return try_to_force_load(mod, "no versions for exported symbols"); } -- cgit v1.2.3 From 743f8cae549affe8eafb021b8c0e78a9f3bc23fa Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 30 Mar 2026 08:13:51 -0500 Subject: module: Override -EEXIST module return The -EEXIST errno is reserved by the module loading functionality. When userspace calls [f]init_module(), it expects a -EEXIST to mean that the module is already loaded in the kernel. If module_init() returns it, that is not true anymore. Override the error when returning to userspace: it doesn't make sense to change potentially long error propagation call chains just because it's will end up as the return of module_init(). Closes: https://lore.kernel.org/all/aKLzsAX14ybEjHfJ@orbyte.nwl.cc/ Cc: Greg Kroah-Hartman Cc: Aaron Tomlin Cc: Petr Pavlu Cc: Daniel Gomez Cc: Phil Sutter Cc: Christophe Leroy Signed-off-by: Lucas De Marchi [Sami: Fixed a typo.] Signed-off-by: Sami Tolvanen --- kernel/module/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'kernel') diff --git a/kernel/module/main.c b/kernel/module/main.c index c4f768953516..ef6742536700 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -3105,6 +3105,14 @@ static noinline int do_init_module(struct module *mod) if (mod->init != NULL) ret = do_one_initcall(mod->init); if (ret < 0) { + /* + * -EEXIST is reserved by [f]init_module() to signal to userspace that + * a module with this name is already loaded. Use something else if the + * module itself is returning that. + */ + if (ret == -EEXIST) + ret = -EBUSY; + goto fail_free_freeinit; } if (ret > 0) { -- cgit v1.2.3 From 663385f9155f27892a97a5824006f806a32eb8dc Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 30 Mar 2026 08:13:52 -0500 Subject: module: Simplify warning on positive returns from module_init() It should now be rare to trigger this warning - it doesn't need to be so verbose. Make it follow the usual style in the module loading code. For the same reason, drop the dump_stack(). Suggested-by: Petr Pavlu Signed-off-by: Lucas De Marchi Reviewed-by: Aaron Tomlin Reviewed-by: Petr Pavlu Reviewed-by: Daniel Gomez Signed-off-by: Sami Tolvanen --- kernel/module/main.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'kernel') diff --git a/kernel/module/main.c b/kernel/module/main.c index ef6742536700..46dd8d25a605 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -3115,13 +3115,9 @@ static noinline int do_init_module(struct module *mod) goto fail_free_freeinit; } - if (ret > 0) { - pr_warn("%s: '%s'->init suspiciously returned %d, it should " - "follow 0/-E convention\n" - "%s: loading module anyway...\n", - __func__, mod->name, ret, __func__); - dump_stack(); - } + if (ret > 0) + pr_warn("%s: init suspiciously returned %d, it should follow 0/-E convention\n", + mod->name, ret); /* Now it's a first class citizen! */ mod->state = MODULE_STATE_LIVE; -- cgit v1.2.3