[PATCH 03/14] objtool/klp: Fix false module dependencies caused by dead relocs
Josh Poimboeuf <[email protected]> Sun, 2 Aug 2026 20:24:25 -0700
| Newsgroups | org.kernel.vger.linux-modules,org.kernel.vger.linux-kernel,org.kernel.vger.live-patching |
|---|---|
| Message-ID | <9548393f4d89ec3b498f4f69aa6ef6b9bb7150fe.1785727106.git.jpoimboe@kernel.org> |
When creating a klp reloc, klp-diff keeps the original relocation but
converts the referenced symbol to an UNDEF/WEAK placeholder tombstone
symbol, which gets fully disabled later by klp post-link. The tombstone
symbol is only needed to avoid confusing objtool when it does the final
run on the patch module.
However, for references to exported symbols, modpost sees the reference
to the tombstone symbol as a real reference to an exported symbol,
resulting in a false module dependency getting created.
Further, for a reference to a tombstone symbol which is exported into a
module namespace, e.g. via EXPORT_SYMBOL_FOR_KVM_INTERNAL(), modpost
can't satisfy the dependency, resulting in a warning like the following:
module ... uses symbol kvm_flush_remote_tlbs from namespace
module:kvm-amd,kvm-intel, but does not import it.
Rename the placeholder tombstone symbols to ".klp.tombstone.<name>" so
modpost no longer recognizes them.
Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files")
Reported-by: Ben Procknow <[email protected]>
Reported-by: Joe Lawrence <[email protected]>
Link: https://lore.kernel.org/[email protected]
Signed-off-by: Josh Poimboeuf <[email protected]>
---
tools/objtool/elf.c | 13 +++++++++++++
tools/objtool/include/objtool/klp.h | 2 ++
tools/objtool/klp-diff.c | 16 ++++++++++++----
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 33c95a74a51b..a791f4ea6ec1 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -23,6 +23,7 @@
#include <linux/log2.h>
#include <objtool/builtin.h>
#include <objtool/elf.h>
+#include <objtool/klp.h>
#include <objtool/warn.h>
static ssize_t demangled_name_len(const char *name);
@@ -626,6 +627,18 @@ static int read_symbols(struct elf *elf)
return -1;
}
+ /*
+ * "klp diff" renames the placeholder symbols of KLP relocs to
+ * hide them from modpost. Hide the prefix from the rest of
+ * objtool so its many name-based heuristics (noreturns,
+ * uaccess safe list, ...) still see the original symbol name.
+ *
+ * st_name is left alone, so the renamed symbol is preserved in
+ * the output file.
+ */
+ if (strstarts(sym->name, KLP_TOMBSTONE_PREFIX))
+ sym->name += strlen(KLP_TOMBSTONE_PREFIX);
+
if ((sym->sym.st_shndx > SHN_UNDEF &&
sym->sym.st_shndx < SHN_LORESERVE) ||
(shndx_data && sym->sym.st_shndx == SHN_XINDEX)) {
diff --git a/tools/objtool/include/objtool/klp.h b/tools/objtool/include/objtool/klp.h
index 6f60cf05db86..aab6db42052d 100644
--- a/tools/objtool/include/objtool/klp.h
+++ b/tools/objtool/include/objtool/klp.h
@@ -23,6 +23,8 @@
#define KLP_RELOCS_SEC "__klp_relocs"
#define KLP_STRINGS_SEC ".rodata.klp.str1.1"
+#define KLP_TOMBSTONE_PREFIX ".klp.tombstone."
+
struct klp_reloc {
void *offset;
void *sym;
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 15d37d955af0..75ba0e060a34 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1362,6 +1362,7 @@ static int clone_reloc_klp(struct elfs *e, struct reloc *patched_reloc,
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;
char sym_name[SYM_NAME_LEN];
@@ -1376,15 +1377,22 @@ static int clone_reloc_klp(struct elfs *e, struct reloc *patched_reloc,
/*
* Keep the original reloc intact for now to avoid breaking objtool run
* which relies on proper relocations for many of its features. This
- * will be disabled later by "objtool klp post-link".
+ * reloc now targets a functionally dead tombstone symbol and will be
+ * disabled later by "objtool klp post-link".
*
- * Convert it to UNDEF (and WEAK to avoid modpost warnings).
+ * Convert the symbol to UNDEF/WEAK and rename to
+ * .klp.tombstone.sym_name to prevent modpost from printing warnings or
+ * creating false module dependencies. The prefix is hidden from the
+ * objtool run itself by read_symbols().
*/
sym = patched_sym->clone;
if (!sym) {
- /* STB_WEAK: avoid modpost undefined symbol warnings */
- sym = elf_create_symbol(e->out, patched_sym->name, NULL,
+ if (snprintf_check(tombstone_name, SYM_NAME_LEN,
+ KLP_TOMBSTONE_PREFIX "%s", patched_sym->name))
+ return -1;
+
+ sym = elf_create_symbol(e->out, tombstone_name, NULL,
STB_WEAK, patched_sym->type, 0, 0);
if (!sym)
return -1;
--
2.54.0