* [PATCH 0/1] Fix exported symbol klp-relocation bug
@ 2026-07-13 21:31 Joe Lawrence
2026-07-13 21:31 ` [PATCH 1/1] objtool/klp-diff: normalize Module.symvers paths to module names Joe Lawrence
0 siblings, 1 reply; 3+ messages in thread
From: Joe Lawrence @ 2026-07-13 21:31 UTC (permalink / raw)
To: live-patching
Cc: Ben Procknow, Jiri Kosina, Josh Poimboeuf, Miroslav Benes,
Petr Mladek, Song Liu
Here is another klp-build bug reported downstream by Ben and reproduced
upstream by me:
Config
======
Default-ish config, note the KVM modules and allowing missing module NS
imports (more on that later):
$ make defconfig
$ ./scripts/config --file .config \
--set-val CONFIG_FTRACE y \
--set-val CONFIG_KALLSYMS_ALL y \
--set-val CONFIG_FUNCTION_TRACER y \
--set-val CONFIG_DYNAMIC_FTRACE y \
--set-val CONFIG_DYNAMIC_DEBUG y \
--set-val CONFIG_LIVEPATCH y \
--set-val CONFIG_KVM m \
--set-val CONFIG_KVM_INTEL m \
--set-val CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS y
$ make olddefconfig
Base kernel and livepatch build
===============================
$ make -j$(nproc)
Build a small patch to kvm :: mmu.c that introduces a call to
kvm_flush_remote_tlbs():
$ cat minimal-kvm-repro.patch
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 24fbc9ea502a..3f11b8c051ce 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -2553,6 +2553,9 @@ static void __link_shadow_page(struct kvm *kvm,
drop_large_spte(kvm, sptep, flush);
spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp));
+
+ if (flush)
+ kvm_flush_remote_tlbs(kvm);
mmu_spte_set(sptep, spte);
Ignore the namespace complaint for now:
$ ./scripts/livepatch/klp-build -T minimal-kvm-repro.patch
Validating patch(es)
Building original kernel
Copying original object files
Fixing patch(es)
Building patched kernel
Copying patched object files
Generating original checksums
Generating patched checksums
Diffing objects
arch/x86/kvm/kvm.o: changed function: __link_shadow_page
Building patch module: livepatch-minimal-kvm-repro.ko
WARNING: modpost: module livepatch-minimal-kvm-repro uses symbol kvm_flush_remote_tlbs from namespace module:kvm-intel, but does not import it.
SUCCESS
klp-relocation inspection
=========================
Take a look at the generated klp-relocation symbols:
$ readelf --wide --symbols livepatch-minimal-kvm-repro.ko | grep -o '.klp.sym.*'
.klp.sym.kvm.kvm_flush_remote_tlbs_sptep,0
.klp.sym.kvm.make_nonleaf_spte,0
.klp.sym.kvm.drop_spte,0
.klp.sym.arch/x86/kvm/kvm.kvm_flush_remote_tlbs,0 << "arch/x86/kvm/kvm" what?!
.klp.sym.kvm.pte_list_add.isra.0,0
.klp.sym.kvm.kvm_mmu_mark_parents_unsync,0
Oddly, the klp-relocation looks like the pathname / Module.symvers:
$ grep kvm_flush_remote_tlbs Module.symvers
0x00000000 kvm_flush_remote_tlbs arch/x86/kvm/kvm EXPORT_SYMBOL_GPL module:kvm-intel
^^^^^^^^^^^^^^^^
klp-diff
========
In klp-diff.c :: clone_reloc_klp() there are two paths for grabbing a
symbol's module name, depending on whether it's been exported or not:
/*
* Create the KLP symbol.
*/
if (export) {
sym_modname = export->mod;
sym_orig_name = export->sym;
sympos = 0;
} else {
sym_modname = find_modname(e);
if (!sym_modname)
return -1;
where the !export path calls find_modname() and __find_modname contains
some string manipulation at the end to form a simple, normalized kernel
module name:
for (char *c = name; *c; c++) {
if (*c == '/')
name = c + 1;
else if (*c == '-')
*c = '_';
else if (*c == '.') {
*c = '\0';
break;
}
}
but the export path assigns export->mod directly, which was originally
extracted from the Modules.symvers file in read_exports() with no such
string simplification.
AFAICT no where does klp-diff expect to handle export->mod as a path and
not a normalized module name.
Fix
===
With that, the attached patch extracts the string code from
__find_modname() into a helper function that both it and read_exports()
can call.
$ ./scripts/livepatch/klp-build -T minimal-kvm-repro.patch
Validating patch(es)
Building original kernel
Copying original object files
Fixing patch(es)
Building patched kernel
Copying patched object files
Generating original checksums
Generating patched checksums
Diffing objects
arch/x86/kvm/kvm.o: changed function: __link_shadow_page
Building patch module: livepatch-minimal-kvm-repro.ko
WARNING: modpost: module livepatch-minimal-kvm-repro uses symbol kvm_flush_remote_tlbs from namespace module:kvm-intel, but does not import it.
SUCCESS
$ readelf --wide --symbols livepatch-minimal-kvm-repro.ko | grep -o '.klp.sym.*'
.klp.sym.kvm.kvm_flush_remote_tlbs_sptep,0
.klp.sym.kvm.make_nonleaf_spte,0
.klp.sym.kvm.kvm_flush_remote_tlbs,0 << fixed
.klp.sym.kvm.drop_spte,0
.klp.sym.kvm.pte_list_add.isra.0,0
.klp.sym.kvm.kvm_mmu_mark_parents_unsync,0
Next: symbol namespaces
=======================
Now a harder question, I think, about symbol namespaces. In the past,
kpatch-build had supported patching symbols in namespace where
MODULE_IMPORT_NS() is allowed. Looking at kvm :: mmu.c
::kvm_flush_remote_tlbs(), that is annotated with
EXPORT_SYMBOL_FOR_KVM_INTERNAL() instead.
Should we make an effort to support klp-relocations / patching to this
use-case?
If modpost were to let klp-relocation symbols through, I *think*
(untested) that might be enough... but it seems like that may violate
the spirit of what the namespacing effort is trying to achieve.
Note that klp-post-link converts these symbols to SHN_LIVEPATCH before
the module is loaded, so the kernel module loader already skips them in
simplify_symbols() (see SHN_LIVEPATCH case). AFAICT, the namespace
check in modpost is the only enforcement point, and it's checking a
symbol that will never be resolved through the normal module loading
path anyway.
Regards,
Joe Lawrence (1):
objtool/klp-diff: normalize Module.symvers paths to module names
tools/objtool/klp-diff.c | 42 ++++++++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 12 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH 1/1] objtool/klp-diff: normalize Module.symvers paths to module names
2026-07-13 21:31 [PATCH 0/1] Fix exported symbol klp-relocation bug Joe Lawrence
@ 2026-07-13 21:31 ` Joe Lawrence
2026-07-15 15:52 ` Josh Poimboeuf
0 siblings, 1 reply; 3+ messages in thread
From: Joe Lawrence @ 2026-07-13 21:31 UTC (permalink / raw)
To: live-patching
Cc: Ben Procknow, Jiri Kosina, Josh Poimboeuf, Miroslav Benes,
Petr Mladek, Song Liu
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 <bprockno@redhat.com>
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
Note on the fix and existing gotchas for the review bots: The
normalize_modname() helper is a direct refactoring of the pre-existing
loop in __find_modname(). To keep this critical bug fix short and
safe for stable backporting, I've kept the string manipulation logic
identical to what has already been proven stable in objtool.
tools/objtool/klp-diff.c | 42 ++++++++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index c2c4e4968bc2..2f3b5e69ab2d 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -83,6 +83,32 @@ 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)
+{
+ for (char *c = name; *c; c++) {
+ if (*c == '/')
+ name = c + 1;
+ else if (*c == '-')
+ *c = '_';
+ else if (*c == '.') {
+ *c = '\0';
+ break;
+ }
+ }
+ return name;
+}
+
static int read_exports(void)
{
const char *symvers = "Module.symvers";
@@ -150,6 +176,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");
@@ -790,18 +819,7 @@ static const char *__find_modname(struct elfs *e)
return NULL;
}
- for (char *c = name; *c; c++) {
- if (*c == '/')
- name = c + 1;
- else 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) */
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH 1/1] objtool/klp-diff: normalize Module.symvers paths to module names
2026-07-13 21:31 ` [PATCH 1/1] objtool/klp-diff: normalize Module.symvers paths to module names Joe Lawrence
@ 2026-07-15 15:52 ` Josh Poimboeuf
0 siblings, 0 replies; 3+ messages in thread
From: Josh Poimboeuf @ 2026-07-15 15:52 UTC (permalink / raw)
To: Joe Lawrence
Cc: live-patching, Ben Procknow, Jiri Kosina, Miroslav Benes,
Petr Mladek, Song Liu
On Mon, Jul 13, 2026 at 05:31:28PM -0400, Joe Lawrence wrote:
> 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 <bprockno@redhat.com>
> Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Looks good, thanks! I'll queue it up.
--
Josh
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-15 15:52 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-13 21:31 [PATCH 0/1] Fix exported symbol klp-relocation bug Joe Lawrence
2026-07-13 21:31 ` [PATCH 1/1] objtool/klp-diff: normalize Module.symvers paths to module names Joe Lawrence
2026-07-15 15:52 ` Josh Poimboeuf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox