On Fri, Aug 14, 2026 at 7:36 PM Josh Poimboeuf <[email protected]> wrote: > > When a module function references a vmlinux symbol which is exported > with EXPORT_SYMBOL_FOR_MODULES(), a patch to that function needs to use > a klp reloc. > > Currently, livepatch fails to load such a module: > > livepatch: invalid access to vmlinux symbol 'get_task_policy' from > module-specific livepatch relocation section > livepatch: failed to initialize patch 'livepatch_test' for module 'testmod' > (-22) > livepatch: patch 'livepatch_test' failed for module 'testmod', refusing to > load module 'testmod' > > klp diff puts all klp relocs in __klp_relocs.<patched object>, so > post-link names the section .klp.rela.<patched object>.<secname>, which the > kernel rejects for vmlinux symbols. > > Commit 07f14d6af9d77 ("objtool/klp: Fix cross-module klp relocation > section naming") changed the meaning of objname in the klp rela section > name to be where the referenced symbol is referenced rather than where > it lives. That premise only holds for symbols in a module: the relocs > get applied when the patched module gets patched, and the module > dependency guarantees the referenced module is loaded by then. > > A vmlinux symbol needs the opposite. It's always resolvable, and it has > to be applied when the patch module loads, before the module loader > initializes the patch module's special sections, which may reference it. > That's why livepatch rejects vmlinux symbols in module-specific > sections. > > Use "vmlinux" as the section objname when the referenced symbol lives in > vmlinux. This moves such klp relocs from .klp.rela.kvm..text to > .klp.rela.vmlinux..text. > > Fixes: 07f14d6af9d77 ("objtool/klp: Fix cross-module klp relocation section > naming") > Reported-by: Dylan Hatch <[email protected]> > Closes: > https://lore.kernel.org/CADBMgpz7iWC0=t=_ge-tfvv0mtpq4kg0qq2zgph8dvpe6eq...@mail.gmail.com > Signed-off-by: Josh Poimboeuf <[email protected]> > --- > tools/objtool/include/objtool/klp.h | 5 +++-- > tools/objtool/klp-diff.c | 35 ++++++++++++++++++----------- > 2 files changed, 25 insertions(+), 15 deletions(-) > > diff --git a/tools/objtool/include/objtool/klp.h > b/tools/objtool/include/objtool/klp.h > index 646d8e1f12eff..c57775d78c71e 100644 > --- a/tools/objtool/include/objtool/klp.h > +++ b/tools/objtool/include/objtool/klp.h > @@ -20,8 +20,9 @@ > * SHF_RELA_LIVEPATCH, nor does it support having two RELA sections for a > * single PROGBITS section. > * > - * "objname" is the name of the object being patched ("vmlinux" or a module > - * name). post-link uses it to name the resulting > + * "objname" is the object whose loading gates the relocation: "vmlinux" for > + * references to vmlinux symbols, otherwise the name of the module being > + * patched. post-link uses it to name the resulting > * .klp.rela.objname.section_name sections. > */ > #define KLP_RELOCS_SEC "__klp_relocs" > diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c > index a66049e0726a6..16681a76f13d0 100644 > --- a/tools/objtool/klp-diff.c > +++ b/tools/objtool/klp-diff.c > @@ -1344,13 +1344,14 @@ static int clone_reloc_klp(struct elfs *e, struct > reloc *patched_reloc, > struct section *sec, unsigned long offset, > struct export *export) > { > + const char *sym_modname, *sym_orig_name, *sec_objname; > struct symbol *patched_sym = patched_reloc->sym; > s64 addend = reloc_addend(patched_reloc); > - const char *sym_modname, *sym_orig_name; > - static struct section *klp_relocs; > char tombstone_name[SYM_NAME_LEN]; > struct symbol *sym, *klp_sym; > unsigned long klp_reloc_off; > + struct section *klp_relocs; > + char sec_name[SEC_NAME_LEN]; > char sym_name[SYM_NAME_LEN]; > struct klp_reloc klp_reloc; > unsigned long sympos; > @@ -1441,20 +1442,28 @@ static int clone_reloc_klp(struct elfs *e, struct > reloc *patched_reloc, > * This intermediate step is necessary to prevent corruption by the > * linker, which doesn't know how to properly handle two rela sections > * applying to the same base section. > + * > + * The objname decides when the reloc gets applied. A reference to a > + * vmlinux symbol goes in the vmlinux section so it gets applied when > + * the patch module loads. Everything else goes in the patched > + * object's section, applied when the patched module is loaded. > */ > > + if (!strcmp(sym_modname, "vmlinux")) { > + sec_objname = "vmlinux"; > + } else { > + sec_objname = find_modname(e); > + if (!sec_objname) > + return -1; > + } > + > + /* section format: __klp_relocs.objname */ > + if (snprintf_check(sec_name, SEC_NAME_LEN, > + KLP_RELOCS_SEC ".%s", sec_objname)) > + return -1; > + > + klp_relocs = find_section_by_name(e->out, sec_name); > if (!klp_relocs) { > - const char *objname = find_modname(e); > - char sec_name[SEC_NAME_LEN]; > - > - if (!objname) > - return -1; > - > - /* section format: __klp_relocs.objname */ > - if (snprintf_check(sec_name, SEC_NAME_LEN, > - KLP_RELOCS_SEC ".%s", objname)) > - return -1; > - > klp_relocs = elf_create_section(e->out, sec_name, 0, > 0, SHT_PROGBITS, 8, > SHF_ALLOC); > if (!klp_relocs) > -- > 2.55.0 > Tested-by: Dylan Hatch <[email protected]>
Tested with the reproducer patch I mentioned earlier: https://github.com/dylanbhatch/linux/tree/mod-ns-lp Also, are there integration test cases kept anywhere for klp-build? And would this reproducer be helpful as a test case? Thanks, Dylan

