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

Reply via email to