diff options
| author | Song Liu <song@kernel.org> | 2026-09-16 11:43:26 -0700 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2026-09-21 11:12:06 +0200 |
| commit | 6549ce0dd1be2400ecdd8693e47c189c54562a4e (patch) | |
| tree | 673c7e7aa9f40ab02632f071a727701fb8fafc36 /tools/objtool/tests/generic | |
| parent | a87892ac05098d23e855e25c7afc128b1e9973fe (diff) | |
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@redhat.com>
Assisted-by: Claude:claude-opus-5
Signed-off-by: Song Liu <song@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://patch.msgid.link/20260916184351.2720310-34-song@kernel.org
Diffstat (limited to 'tools/objtool/tests/generic')
| -rw-r--r-- | tools/objtool/tests/generic/fixtures/new_export_ref.c | 35 | ||||
| -rwxr-xr-x | tools/objtool/tests/generic/test-new-export-ref.sh | 46 |
2 files changed, 81 insertions, 0 deletions
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 000000000000..73210aacb4ae --- /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 000000000000..f0be2cf87fe3 --- /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" |
