[PATCH v2 1/2] modules: Add __module_build_id() to find module by build_id
From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
Date: 2025-02-01 07:23:15
Also in:
linux-trace-kernel, lkml
Subsystem:
library code, module support, the rest · Maintainers:
Andrew Morton, Luis Chamberlain, Petr Pavlu, Daniel Gomez, Sami Tolvanen, Linus Torvalds
From: Masami Hiramatsu (Google) <mhiramat@kernel.org> Add __module_build_id() to find module by build_id. This also makes module::build_id available with CONFIG_MODULE_BUILD_ID kconfig. Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> --- include/linux/module.h | 8 +++++++- kernel/module/Kconfig | 3 +++ kernel/module/kallsyms.c | 4 ++-- kernel/module/main.c | 29 +++++++++++++++++++++++++++++ lib/Kconfig.debug | 1 + 5 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/include/linux/module.h b/include/linux/module.h
index b3a643435357..e181056d6af6 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h@@ -416,7 +416,7 @@ struct module { /* Unique handle for this module */ char name[MODULE_NAME_LEN]; -#ifdef CONFIG_STACKTRACE_BUILD_ID +#ifdef CONFIG_MODULE_BUILD_ID /* Module build ID */ unsigned char build_id[BUILD_ID_SIZE_MAX]; #endif
@@ -622,6 +622,7 @@ static inline bool module_is_coming(struct module *mod) struct module *__module_text_address(unsigned long addr); struct module *__module_address(unsigned long addr); +struct module *__module_build_id(unsigned char *build_id, int size); bool is_module_address(unsigned long addr); bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr); bool is_module_percpu_address(unsigned long addr);
@@ -791,6 +792,11 @@ static inline struct module *__module_text_address(unsigned long addr) return NULL; } +static inline struct module *__module_build_id(unsigned char *build_id, int size) +{ + return NULL; +} + static inline bool is_module_address(unsigned long addr) { return false;
diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
index 7b329057997a..5e81dea1afea 100644
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig@@ -26,6 +26,9 @@ if MODULES config MODULE_DEBUGFS bool +config MODULE_BUILD_ID + bool + config MODULE_DEBUG bool "Module debugging" depends on DEBUG_FS
diff --git a/kernel/module/kallsyms.c b/kernel/module/kallsyms.c
index bf65e0c3c86f..98f2661c1da8 100644
--- a/kernel/module/kallsyms.c
+++ b/kernel/module/kallsyms.c@@ -224,7 +224,7 @@ void add_kallsyms(struct module *mod, const struct load_info *info) mod->core_kallsyms.num_symtab = ndst; } -#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) +#if IS_ENABLED(CONFIG_MODULE_BUILD_ID) void init_build_id(struct module *mod, const struct load_info *info) { const Elf_Shdr *sechdr;
@@ -338,7 +338,7 @@ int module_address_lookup(unsigned long addr, if (modname) *modname = mod->name; if (modbuildid) { -#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) +#if IS_ENABLED(CONFIG_MODULE_BUILD_ID) *modbuildid = mod->build_id; #else *modbuildid = NULL;
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 5399c182b3cb..fca9b6a692e3 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c@@ -3746,6 +3746,35 @@ struct module *__module_text_address(unsigned long addr) return mod; } +/** + * __module_build_id() - get the module whose build_id start with an array. + * @build_id: the first part of the build_id. + * @size: the size of @build_id. + * + * Must be called with preempt disabled or module mutex held so that + * module doesn't get freed during this. + */ +struct module *__module_build_id(unsigned char *build_id, int size) +{ +#ifdef CONFIG_MODULE_BUILD_ID + struct module *mod; + + if (size < 0) + return NULL; + + if (size > BUILD_ID_SIZE_MAX) + size = BUILD_ID_SIZE_MAX; + + list_for_each_entry_rcu(mod, &modules, list) { + if (mod->state == MODULE_STATE_UNFORMED) + continue; + if (!memcmp(mod->build_id, build_id, size)) + return mod; + } +#endif + return NULL; +} + /* Don't grab lock, we're oopsing. */ void print_modules(void) {
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index cf2a41dc7682..2d3a2f656a86 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug@@ -38,6 +38,7 @@ config PRINTK_CALLER config STACKTRACE_BUILD_ID bool "Show build ID information in stacktraces" depends on PRINTK + select MODULE_BUILD_ID if MODULES help Selecting this option adds build ID information for symbols in stacktraces printed with the printk format '%p[SR]b'.