[tip: objtool/core] objtool/klp: Add test for new references to exported symbols
From: tip-bot2 for Song Liu
Date: Fri Sep 18 2026 - 06:30:25 EST
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: b45f394ee3afd2ff0a54894f95a01f96ecc8e30a
Gitweb: https://git.kernel.org/tip/b45f394ee3afd2ff0a54894f95a01f96ecc8e30a
Author: Song Liu <song@xxxxxxxxxx>
AuthorDate: Wed, 16 Sep 2026 11:43:26 -07:00
Committer: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
CommitterDate: Wed, 16 Sep 2026 17:13:29 -07:00
objtool/klp: Add test for new references to exported symbols
A patch may introduce a reference the original object did not have. That
is fine when the export belongs to vmlinux, and not fine when it belongs to
a module: the livepatch would gain a module dependency nobody declared, and
late module patching lets the patch load first.
This tests the behavior of commit 72d76d0c18eb ("objtool/klp: Allow new
references to module exports").
Assisted-by: Claude:claude-opus-4
Based-on-test-by: Joe Lawrence <joe.lawrence@xxxxxxxxxx>
Assisted-by: Claude:claude-opus-5
Signed-off-by: Song Liu <song@xxxxxxxxxx>
Link: https://patch.msgid.link/20260916184351.2720310-34-song@xxxxxxxxxx
Signed-off-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
---
tools/objtool/tests/generic/fixtures/new_export_ref.c | 35 ++++++++-
tools/objtool/tests/generic/test-new-export-ref.sh | 46 ++++++++++-
2 files changed, 81 insertions(+)
create mode 100644 tools/objtool/tests/generic/fixtures/new_export_ref.c
create mode 100755 tools/objtool/tests/generic/test-new-export-ref.sh
diff --git a/tools/objtool/tests/generic/fixtures/new_export_ref.c b/tools/objtool/tests/generic/fixtures/new_export_ref.c
new file mode 100644
index 0000000..73210aa
--- /dev/null
+++ b/tools/objtool/tests/generic/fixtures/new_export_ref.c
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * A reference which only exists in the patched build. The symbol has no twin
+ * in the original object, so what klp diff may do with it depends entirely on
+ * whether Module.symvers says it is exported, and by what.
+ */
+
+static const char __modinfo[]
+ __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
+
+extern int newly_referenced(int x);
+
+/*
+ * A reference both builds have. When Module.symvers says a module exports
+ * this one, the original already depends on that module, which is what makes
+ * a new reference to it safe -- the loader will not let the patched module
+ * load without it. EXISTING_DEP leaves it out, for the case where there is
+ * no such dependency to inherit.
+ */
+extern int existing_dep(int x);
+
+int target(int x)
+{
+#ifdef EXISTING_DEP
+ int base = existing_dep(x);
+#else
+ int base = x;
+#endif
+
+#ifdef PATCHED
+ return newly_referenced(base);
+#else
+ return base + 1;
+#endif
+}
diff --git a/tools/objtool/tests/generic/test-new-export-ref.sh b/tools/objtool/tests/generic/test-new-export-ref.sh
new file mode 100755
index 0000000..f0be2cf
--- /dev/null
+++ b/tools/objtool/tests/generic/test-new-export-ref.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# A reference the patch adds has no counterpart in the original object. klp
+# diff used to reject any such reference needing a klp relocation, which ruled
+# out patches that call something they did not call before -- a common enough
+# thing for a fix to do.
+#
+# Module.symvers is what makes it safe: it says the symbol exists and who owns
+# it. But that is only sufficient for a vmlinux export. A new reference to a
+# module's export is a dependency the patch module does not declare, and the
+# relocation would resolve only if that module happened to be loaded, so it
+# stays an error.
+
+. "$(dirname "$0")/../lib.sh"
+
+setup
+build_pair new_export_ref.c
+
+# Exported by vmlinux, in a module: namespace so it needs a klp relocation
+# rather than an ordinary one. Allowed.
+export_syms
+add_exports_ns vmlinux module:kvm newly_referenced
+run_diff
+assert_klp_sym newly_referenced vmlinux
+
+# Exported by a module the patched object does not depend on. Rejected, and
+# for that reason rather than some other.
+export_syms
+add_exports other_mod newly_referenced
+run_diff 255
+assert_diff_log 'undeclared module dependency'
+
+# ... unless the original already referenced something that module exports.
+# The loader will not let the patched object load without other_mod, so the
+# klp relocation has something to resolve against, and klp diff allows it.
+# This is the other half of the rule, and it fails in the opposite direction:
+# refusing here would reject a patch which is safe to apply.
+rm -f "$workdir/out.o"
+build_pair new_export_ref.c -DEXISTING_DEP
+export_syms
+add_exports other_mod newly_referenced existing_dep
+run_diff
+assert_klp_sym newly_referenced other_mod
+
+pass "new reference allowed for vmlinux and for a module already depended on"