With MITIGATION_RETPOLINE=y, GCC lowers the computed goto in ___bpf_prog_run() to a jump through __x86_indirect_thunk_rdx. objtool puts that jump on the retpoline call list along with the indirect calls, so with CONFIG_CFI=y the kCFI check wants a UD2 before it:
vmlinux.o: warning: objtool: ___bpf_prog_run+0x1e: no-cfi indirect call! The jump goes through the "jumptable" array, which objtool already reads from .data.rel.ro.c_jump_table, so its targets stay inside the function and need no kCFI check. Skip jump table jumps in the check. Clang does not emit this jump: with retpolines, it lowers the computed goto without an indirect jump. Build tested ARCH=x86_64 defconfig with CONFIG_LKDTM=y and CONFIG_CFI=y, with GCC 17.0.0 (experimental, with the kCFI series). Assisted-by: LLM Signed-off-by: Kees Cook <[email protected]> --- tools/objtool/check.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 464f6c9d9ff0..d35c5305075f 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -4199,6 +4199,14 @@ static int validate_retpoline(struct objtool_file *file) list_for_each_entry(insn, &file->retpoline_call_list, call_node) { struct symbol *sym = insn_sym(insn); + /* + * A jump through a jump table stays inside the function, so + * it has no kCFI check. GCC turns the computed goto in + * ___bpf_prog_run() into one under MITIGATION_RETPOLINE. + */ + if (is_jump_table_jump(insn)) + continue; + if (sym && (is_notype_sym(sym) || is_func_sym(sym)) && !sym->nocfi) { struct instruction *prev = -- 2.55.0

