mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 18:03:10 -04:00
objtool/klp: Normalize Module.symvers paths to module names
Module.symvers contains build-tree object paths as module identifiers
(e.g., "arch/x86/kvm/kvm") rather than runtime module names ("kvm").
Objtool's clone_reloc_klp() uses this field directly for exported
symbols, while unexported symbols correctly go through __find_modname().
This means that exported symbol relocations may land in a .klp.rela
section named with the build path rather than the module name. That is
a crash waiting to happen: the kernel's livepatch loader silently skips
this relocation because it doesn't match the expected klp_object name.
The unresolved relocation sits in the newly activated code, crashing
when executed.
Normalize export->mod at Module.symvers read time using the same logic
as __find_modname() (refactored into a shared normalize_modname()
helper).
Fixes: dd590d4d57 ("objtool/klp: Introduce klp diff subcommand for diffing object files")
Reported-by: Ben Procknow <bprockno@redhat.com>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Cc: live-patching@vger.kernel.org
Link: https://patch.msgid.link/dbe1b72931bd3c31b751fd0729613d9f2226fff6.1785727106.git.jpoimboe@kernel.org
This commit is contained in:
committed by
Ingo Molnar
parent
165affd6f0
commit
8668bf91e0
@@ -83,6 +83,35 @@ static char *escape_str(const char *orig)
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a build-tree object path to a runtime module name: strip
|
||||
* directory components, replace '-' with '_', and remove file
|
||||
* extensions. Examples:
|
||||
*
|
||||
* "arch/x86/kvm/kvm" -> "kvm"
|
||||
* "arch/x86/kvm/kvm-intel" -> "kvm_intel".
|
||||
*
|
||||
* Used by read_exports() to normalize Module.symvers entries and by
|
||||
* __find_modname() as a fallback when .modinfo lacks a "name=" tag.
|
||||
*/
|
||||
static char *normalize_modname(char *name)
|
||||
{
|
||||
char *slash = strrchr(name, '/');
|
||||
|
||||
if (slash)
|
||||
name = slash + 1;
|
||||
|
||||
for (char *c = name; *c; c++) {
|
||||
if (*c == '-')
|
||||
*c = '_';
|
||||
else if (*c == '.') {
|
||||
*c = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static int read_exports(void)
|
||||
{
|
||||
const char *symvers = "Module.symvers";
|
||||
@@ -150,6 +179,9 @@ static int read_exports(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(export->mod, "vmlinux"))
|
||||
export->mod = normalize_modname(export->mod);
|
||||
|
||||
export->sym = strdup(sym);
|
||||
if (!export->sym) {
|
||||
ERROR_GLIBC("strdup");
|
||||
@@ -1140,7 +1172,7 @@ static struct export *find_export(struct symbol *sym)
|
||||
static const char *__find_modname(struct elfs *e)
|
||||
{
|
||||
struct section *sec;
|
||||
char *name, *slash;
|
||||
char *name;
|
||||
|
||||
sec = find_section_by_name(e->orig, ".modinfo");
|
||||
if (!sec) {
|
||||
@@ -1158,20 +1190,7 @@ static const char *__find_modname(struct elfs *e)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slash = strrchr(name, '/');
|
||||
if (slash)
|
||||
name = slash + 1;
|
||||
|
||||
for (char *c = name; *c; c++) {
|
||||
if (*c == '-')
|
||||
*c = '_';
|
||||
else if (*c == '.') {
|
||||
*c = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
return normalize_modname(name);
|
||||
}
|
||||
|
||||
/* Get the object's module name as defined by the kernel (and klp_object) */
|
||||
|
||||
Reference in New Issue
Block a user