mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 22:09:30 +02:00
objtool/klp: Fix checksums for constant pool references
Adding a line of code to __link_shadow_page() with a literal string
causes a false positive changed function with GCC:
arch/x86/kvm/kvm.ko.o: changed function: kvm_tdp_mmu_map_private_pfn
While the patch only touched __link_shadow_page(), the string addition
triggered a rename of .LC64 -> .LC65 in kvm_tdp_mmu_map_private_pfn()
even though the underlying referenced constant data didn't change.
So for .LC* symbols, the suffix is arbitrary but the data isn't. Add
the underlying data to the checksum calculation rather than the symbol
name.
Clang also uses .LC* symbols, but also uses anonymous data. Both
compilers put this data in .rodata.cst<num> sections.
Fixes: 0d83da43b1 ("objtool/klp: Add --checksum option to generate per-function checksums")
Link: https://patch.msgid.link/f3a9e74ceebc6475ce94bcfe985401140857814a.1787939301.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
@@ -54,6 +54,19 @@ static int checksum_debug_init(struct objtool_file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect a reference to anonymous constant pool data which the compiler places
|
||||
* in .rodata.cst<num> and which either has an .LC<num> symbol associated with
|
||||
* it or (with Clang) no symbol at all. These are typically initializers for
|
||||
* local function stack data, so they're considered part of the function rather
|
||||
* than data per se.
|
||||
*/
|
||||
static bool is_anonymous_const_data(struct symbol *sym)
|
||||
{
|
||||
return strstarts(sym->sec->name, ".rodata.cst") &&
|
||||
(is_sec_sym(sym) || strstarts(sym->name, ".LC"));
|
||||
}
|
||||
|
||||
static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
|
||||
struct instruction *insn)
|
||||
{
|
||||
@@ -129,6 +142,14 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
|
||||
goto alts;
|
||||
}
|
||||
|
||||
if (is_anonymous_const_data(sym)) {
|
||||
void *cst;
|
||||
|
||||
cst = sym->sec->data->d_buf + sym->offset + offset;
|
||||
__checksum_update_insn(func, insn, cst, sym->sec->sh.sh_entsize);
|
||||
goto alts;
|
||||
}
|
||||
|
||||
if (is_sec_sym(sym)) {
|
||||
sym = find_symbol_containing(reloc->sym->sec, offset);
|
||||
if (!sym)
|
||||
|
||||
Reference in New Issue
Block a user