On Fri, Aug 14, 2026 at 05:18:19PM -0700, Josh Poimboeuf wrote:
> On Fri, Aug 14, 2026 at 02:05:48PM -0700, Dylan Hatch wrote:
> > 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?
> 
> Ah, this is another tooling issue, let me work up a patch.

Here is an untested diff, I'll post a proper patch once I get a chance
to test it.

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)

Reply via email to