diff options
| author | Josh Poimboeuf <jpoimboe@kernel.org> | 2026-08-07 14:37:53 -0700 |
|---|---|---|
| committer | Josh Poimboeuf <jpoimboe@kernel.org> | 2026-08-11 16:10:51 -0700 |
| commit | 4cd3cfb8b54feca89a682720434092a87bfa4967 (patch) | |
| tree | 707abbdf0f6e9a01793d118b6bb908d3899c74e1 /tools/objtool | |
| parent | 72d76d0c18ebd40f6a32df875ff40528564849c1 (diff) | |
objtool/klp: Fix relocations for EXPORT_SYMBOL_FOR_MODULES() symbols
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
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
Acked-by: Song Liu <song@kernel.org>
Link: https://patch.msgid.link/fe5a00818e06ec613344d41d5944de054fcd8832.1786138493.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Diffstat (limited to 'tools/objtool')
| -rw-r--r-- | tools/objtool/klp-diff.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 0211e5c87160..1f05646f3e9c 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)); } @@ -1175,11 +1188,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) { /* |
