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


Reply via email to