Re: [PATCH v3 8/9] objtool/klp: Fix relocations for EXPORT_SYMBOL_FOR_MODULES() symbols
From: Dylan Hatch <hidden>
Date: 2026-08-14 21:06:01
Also in:
lkml
Hi Josh, On Fri, Aug 7, 2026 at 2:42 PM Josh Poimboeuf [off-list ref] wrote:
quoted hunk ↗ jump to hunk
EXPORT_SYMBOL_FOR_MODULES() puts a symbol in a "module:<names>" namespace, which the module loader grants access to by matching the importing module's name against that list. klp_reloc_needed() only creates a klp reloc for module-owned exports; a vmlinux export gets a normal reloc. For a vmlinux symbol exported with EXPORT_SYMBOL_FOR_MODULES(), using a normal reloc results in a modpost failure in klp-build: ERROR: modpost: module livepatch-foo uses symbol mpol_shared_policy_lookup from namespace module:kvm, but does not import it. And the modpost error is correct: even with that error removed, the patch module would fail to load: livepatch_foo: module uses symbol (mpol_shared_policy_lookup) from namespace module:kvm, but does not import it. livepatch_foo: Unknown symbol mpol_shared_policy_lookup (err -22) Treat it like an unexported symbol by using a klp reloc. Note this only affects "module:" namespaces. Ordinary namespaced exports continue to work with normal relocs thanks to copy_import_ns(), which propagates the patched object's import_ns tags to the patch module. Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files") Reported-by: Joe Lawrence <joe.lawrence@redhat.com> Link: https://lore.kernel.org/6a6608f4-0a05-4d75-8b7f-edddfac9c5d4@redhat.com (local) Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org> --- tools/objtool/klp-diff.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-)diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 6d34186d8b24c..0f135b74a5b0c 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c@@ -30,7 +30,9 @@ struct elfs { struct export { struct hlist_node hash; - char *mod, *sym; + char *mod; + char *sym; + bool mod_ns; }; bool debug, debug_correlate, debug_clone;@@ -135,7 +137,7 @@ static int read_exports(void) } while (fgets(line, 1024, file)) { - char *sym, *mod, *type; + char *sym, *mod, *type, *namespace; struct export *export; sym = strchr(line, '\t');@@ -162,6 +164,14 @@ static int read_exports(void) *type++ = '\0'; + namespace = strchr(type, '\t'); + if (!namespace) { + ERROR("malformed Module.symvers (namespace) at line %d", line_num); + return -1; + } + + *namespace++ = '\0'; + if (*sym == '\0' || *mod == '\0') { ERROR("malformed Module.symvers at line %d", line_num); return -1;@@ -188,6 +198,9 @@ static int read_exports(void) return -1; } + /* EXPORT_SYMBOL_FOR_MODULES() */ + export->mod_ns = strstarts(namespace, "module:"); + hash_add(exports, &export->hash, str_hash(sym)); }@@ -1174,11 +1187,16 @@ static bool klp_reloc_needed(struct reloc *patched_reloc) * clusterfunk that is late module patching, the patch module is * allowed to be loaded before any modules it depends on. * - * If exported by vmlinux, a normal reloc will do. + * If exported by vmlinux to all modules, a normal reloc will do. */ export = find_export(patched_sym); - if (export) - return strcmp(export->mod, "vmlinux"); + if (export) { + if (strcmp(export->mod, "vmlinux")) + return true; + + /* EXPORT_SYMBOL_FOR_MODULES() gets a klp reloc */ + return export->mod_ns; + } if (!patched_sym->twin) { /* --2.54.0
Following up on the other thread [1], I noticed that when a patch is touching a module function with a reference to one of these module-exported symbols, the patch/module is rejected because KLP relocs referencing vmlinux symbols are not allowed from module-specific livepatch relocation sections. I was able to reproduce this with a simple module/livepatch combo that depends on one of these symbols [2] (see samples/livepatch/testmod.c and test.patch): root@debian-vm:~$ insmod livepatch-test.ko root@debian-vm:~$ insmod testmod.ko insmod: ERROR: could not insert module testmod.ko: Invalid parameters With dmesg: [ 655.596876] livepatch_test: loading out-of-tree module taints kernel. [ 655.600961] livepatch_test: tainting kernel with TAINT_LIVEPATCH [ 655.605436] livepatch: enabling patch 'livepatch_test' [ 655.609119] livepatch: 'livepatch_test': starting patching transition [ 656.653454] livepatch: 'livepatch_test': patching complete [ 738.777872] livepatch: invalid access to vmlinux symbol 'get_task_policy' from module-specific livepatch relocation section [ 738.784899] livepatch: failed to initialize patch 'livepatch_test' for module 'testmod' (-22) [ 738.790371] livepatch: patch 'livepatch_test' failed for module 'testmod', refusing to load module 'testmod' Do you recommend a strategy for working around this, or is this something that would have to be fixed in the kernel? Refs: [1]: https://lore.kernel.org/all/CADBMgpyY6R_YmEqhZSw=88-Bfkv9=s-N-x1siE1uPAgH_fTURw@mail.gmail.com/ (local) [2]: https://github.com/dylanbhatch/linux/tree/mod-ns-lp Thanks, Dylan