[tip: objtool/core] objtool/klp: Normalize Module.symvers paths to module names

"tip-bot2 for Joe Lawrence" <[email protected]> Mon, 03 Aug 2026 05:49:43 -0000
Newsgroups org.kernel.vger.live-patching,org.kernel.vger.linux-kernel
Message-ID <178573618371.1210945.1444857092839684415.tip-bot2@tip-bot2>
The following commit has been merged into the objtool/core branch of tip:

Commit-ID:     8668bf91e0508abeb8e98b4edd89032be02228a1
Gitweb:        https://git.kernel.org/tip/8668bf91e0508abeb8e98b4edd89032be02=
228a1
Author:        Joe Lawrence <[email protected]>
AuthorDate:    Sun, 02 Aug 2026 20:24:24 -07:00
Committer:     Ingo Molnar <[email protected]>
CommitterDate: Mon, 03 Aug 2026 07:12:38 +02: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: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing =
object files")
Reported-by: Ben Procknow <[email protected]>
Signed-off-by: Joe Lawrence <[email protected]>
Signed-off-by: Josh Poimboeuf <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
Reviewed-by: Miroslav Benes <[email protected]>
Cc: [email protected]
Link: https://patch.msgid.link/dbe1b72931bd3c31b751fd0729613d9f2226fff6.17857=
[email protected]
---
 tools/objtool/klp-diff.c | 49 +++++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index aeb99d5..15d37d9 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -83,6 +83,35 @@ static char *escape_str(const char *orig)
 	return new;
 }
=20
+/*
+ * 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=3D" tag.
+ */
+static char *normalize_modname(char *name)
+{
+	char *slash =3D strrchr(name, '/');
+
+	if (slash)
+		name =3D slash + 1;
+
+	for (char *c =3D name; *c; c++) {
+		if (*c =3D=3D '-')
+			*c =3D '_';
+		else if (*c =3D=3D '.') {
+			*c =3D '\0';
+			break;
+		}
+	}
+	return name;
+}
+
 static int read_exports(void)
 {
 	const char *symvers =3D "Module.symvers";
@@ -150,6 +179,9 @@ static int read_exports(void)
 			return -1;
 		}
=20
+		if (strcmp(export->mod, "vmlinux"))
+			export->mod =3D normalize_modname(export->mod);
+
 		export->sym =3D 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;
=20
 	sec =3D find_section_by_name(e->orig, ".modinfo");
 	if (!sec) {
@@ -1158,20 +1190,7 @@ static const char *__find_modname(struct elfs *e)
 		return NULL;
 	}
=20
-	slash =3D strrchr(name, '/');
-	if (slash)
-		name =3D slash + 1;
-
-	for (char *c =3D name; *c; c++) {
-		if (*c =3D=3D '-')
-			*c =3D '_';
-		else if (*c =3D=3D '.') {
-			*c =3D '\0';
-			break;
-		}
-	}
-
-	return name;
+	return normalize_modname(name);
 }
=20
 /* Get the object's module name as defined by the kernel (and klp_object) */