linux: compatible modules without kallsyms on KALLSYMS enabled kernel

linux/module.h: move kallsyms to the end of struct
This commit is contained in:
Liangbin Lian 2025-01-02 19:36:18 +08:00
parent f778584050
commit a0f8ed1334

View File

@ -0,0 +1,131 @@
From e3b12676bb6b3c4fed08f2153749cfc7dd1c4c8b Mon Sep 17 00:00:00 2001
From: jjm2473 <jjm2473@gmail.com>
Date: Thu, 2 Jan 2025 18:39:43 +0800
Subject: [PATCH] header: linux/module.h: move kallsyms to the end of struct
kernel: compatible modules without kallsyms on KALLSYMS enabled kernel
for better compatible
---
include/linux/module.h | 24 ++++++++++++------------
kernel/module/main.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 12 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index 06caf5a4a..66362f8c8 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -474,18 +474,6 @@ struct module {
struct bug_entry *bug_table;
#endif
-#ifdef CONFIG_KALLSYMS
- /* Protected by RCU and/or module_mutex: use rcu_dereference() */
- struct mod_kallsyms __rcu *kallsyms;
- struct mod_kallsyms core_kallsyms;
-
- /* Section attributes */
- struct module_sect_attrs *sect_attrs;
-
- /* Notes attributes */
- struct module_notes_attrs *notes_attrs;
-#endif
-
/* The command line arguments (may be mangled). People like
keeping pointers to this stuff */
char *args;
@@ -586,6 +574,18 @@ struct module {
#ifdef CONFIG_DYNAMIC_DEBUG_CORE
struct _ddebug_info dyndbg_info;
#endif
+
+#ifdef CONFIG_KALLSYMS
+ /* Protected by RCU and/or module_mutex: use rcu_dereference() */
+ struct mod_kallsyms __rcu *kallsyms;
+ struct mod_kallsyms core_kallsyms;
+
+ /* Section attributes */
+ struct module_sect_attrs *sect_attrs;
+
+ /* Notes attributes */
+ struct module_notes_attrs *notes_attrs;
+#endif
} ____cacheline_aligned __randomize_layout;
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 55cc7eaa2..5a88ef41e 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1550,6 +1550,16 @@ static void __layout_sections(struct module *mod, struct load_info *info, bool i
if (WARN_ON_ONCE(type == MOD_INVALID))
continue;
+#ifdef CONFIG_KALLSYMS
+ if (i == info->index.mod && sizeof(struct module) > s->sh_size) {
+ pr_warn("%s: module has no kallsyms\n",
+ info->name);
+ Elf_Shdr dummy;
+ dummy.sh_addralign = s->sh_addralign;
+ dummy.sh_size = sizeof(struct module);
+ s->sh_entsize = module_get_offset_and_type(mod, type, &dummy, i);
+ } else
+#endif
s->sh_entsize = module_get_offset_and_type(mod, type, s, i);
pr_debug("\t%s\n", sname);
}
@@ -1870,11 +1880,19 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
goto no_exec;
}
+#ifdef CONFIG_KALLSYMS
+ if (shdr->sh_size > sizeof(struct module)) {
+ pr_err("module %s: .gnu.linkonce.this_module section size must match the kernel's built struct module size at run time\n",
+ info->name ?: "(missing .modinfo section or name field)");
+ goto no_exec;
+ }
+#else
if (shdr->sh_size != sizeof(struct module)) {
pr_err("module %s: .gnu.linkonce.this_module section size must match the kernel's built struct module size at run time\n",
info->name ?: "(missing .modinfo section or name field)");
goto no_exec;
}
+#endif
info->index.mod = mod_idx;
@@ -2277,11 +2295,19 @@ static int move_module(struct module *mod, struct load_info *info)
* end up copying over all modifications made to the
* userspace copy of the entire struct module.
*/
+#ifdef CONFIG_KALLSYMS
+ if (i == info->index.mod &&
+ (WARN_ON_ONCE(shdr->sh_size > sizeof(struct module)))) {
+ ret = -ENOEXEC;
+ goto out_enomem;
+ }
+#else
if (i == info->index.mod &&
(WARN_ON_ONCE(shdr->sh_size != sizeof(struct module)))) {
ret = -ENOEXEC;
goto out_enomem;
}
+#endif
memcpy(dest, (void *)shdr->sh_addr, shdr->sh_size);
}
/*
@@ -2291,6 +2317,11 @@ static int move_module(struct module *mod, struct load_info *info)
* minted official memory area.
*/
shdr->sh_addr = (unsigned long)dest;
+
+#ifdef CONFIG_KALLSYMS
+ if (i == info->index.mod && sizeof(struct module) > shdr->sh_size)
+ shdr->sh_size = sizeof(struct module);
+#endif
pr_debug("\t0x%lx 0x%.8lx %s\n", (long)shdr->sh_addr,
(long)shdr->sh_size, info->secstrings + shdr->sh_name);
}
--
2.46.0