[PATCH v3 14/21] objtool: Prevent kCFI hashes from being decoded as instructions

Josh Poimboeuf jpoimboe at kernel.org
Sat Aug 8 14:59:42 PDT 2026


On Tue, Jun 30, 2026 at 02:40:42PM -0400, Joe Lawrence wrote:
> The root cause is that create_fake_symbols() skips the entire special
> section if any symbol exists at offset 0.  But Clang places a .Ltmp*
> label at the start of .kcfi_traps, so no per-entry fake symbols are
> created and clone_special_sections() extracts nothing.
> 
>   static int create_fake_symbols(struct elf *elf)
>   {
>   ...
>   	/*
>   	 * 2) Make symbols for sh_entsize, and simple arrays of pointers:
>   	 */
>   entsize:
>   	for_each_sec(elf, sec) {
>   		unsigned int entry_size;
>   		unsigned long offset;
> 
>   		if (!is_special_section(sec) || find_symbol_by_offset(sec, 0))
>   			continue;
> 
>   $ llvm-readelf --wide --symbols klp-tmp/3-checksum-patched/vmlinux.o | \
>           awk '$7 == 74993'
>    93266: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT   74993 .Ltmp78
>    93544: 0000000000000000     0 SECTION LOCAL  DEFAULT   74993 .kcfi_traps
> 
> 
> Possible fix: ignore .L* assembler-local labels at section offset 0
> using the existing is_local_label() helper.
> 
> -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8-- -->8--
> 
> diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
> index b9624bd9439b..4ba400926647 100644
> --- a/tools/objtool/klp-diff.c
> +++ b/tools/objtool/klp-diff.c
> @@ -1860,8 +1860,17 @@ static int create_fake_symbols(struct elf *elf)
>  	for_each_sec(elf, sec) {
>  		unsigned int entry_size;
>  		unsigned long offset;
> +		struct symbol *sym_at_0;
> 
> -		if (!is_special_section(sec) || find_symbol_by_offset(sec, 0))
> +		if (!is_special_section(sec))
> +			continue;
> +
> +		/*
> +		 * Clang may place assembler-local .L* labels at offset 0;
> +		 * they must not prevent per-entry fake symbol creation.
> +		 */
> +		sym_at_0 = find_symbol_by_offset(sec, 0);
> +		if (sym_at_0 && !is_local_label(sym_at_0))
>  			continue;

Thanks, I'll fix this with my other series of fixes in the next version.

find_symbol_by_offset() might not work because there can be multiple
symbols at offset 0.  Instead we can just traverse the symbols in the
section, looking for sym->fake.

-- 
Josh



More information about the linux-arm-kernel mailing list