Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Support conditional retpolines

A Clang-built kernel is showing the following warning:

arch/x86/kernel/platform-quirks.o: warning: objtool: x86_early_init_platform_quirks()+0x84: unreachable instruction

That corresponds to this code:

7e: 0f 85 00 00 00 00 jne 84 <x86_early_init_platform_quirks+0x84>
80: R_X86_64_PC32 __x86_indirect_thunk_r11-0x4
84: c3 retq

This is a conditional retpoline sibling call, which is now possible
thanks to retpolines. Objtool hasn't seen that before. It's
incorrectly interpreting the conditional jump as an unconditional
dynamic jump.

Reported-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/30d4c758b267ef487fb97e6ecb2f148ad007b554.1563413318.git.jpoimboe@redhat.com

authored by

Josh Poimboeuf and committed by
Thomas Gleixner
b68b9907 9fe7b764

+11 -2
+1
tools/objtool/arch.h
··· 15 15 INSN_JUMP_CONDITIONAL, 16 16 INSN_JUMP_UNCONDITIONAL, 17 17 INSN_JUMP_DYNAMIC, 18 + INSN_JUMP_DYNAMIC_CONDITIONAL, 18 19 INSN_CALL, 19 20 INSN_CALL_DYNAMIC, 20 21 INSN_RETURN,
+10 -2
tools/objtool/check.c
··· 575 575 * Retpoline jumps are really dynamic jumps in 576 576 * disguise, so convert them accordingly. 577 577 */ 578 - insn->type = INSN_JUMP_DYNAMIC; 578 + if (insn->type == INSN_JUMP_UNCONDITIONAL) 579 + insn->type = INSN_JUMP_DYNAMIC; 580 + else 581 + insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL; 582 + 579 583 insn->retpoline_safe = true; 580 584 continue; 581 585 } else { ··· 2118 2114 break; 2119 2115 2120 2116 case INSN_JUMP_DYNAMIC: 2117 + case INSN_JUMP_DYNAMIC_CONDITIONAL: 2121 2118 if (func && is_sibling_call(insn)) { 2122 2119 ret = validate_sibling_call(insn, &state); 2123 2120 if (ret) 2124 2121 return ret; 2125 2122 } 2126 2123 2127 - return 0; 2124 + if (insn->type == INSN_JUMP_DYNAMIC) 2125 + return 0; 2126 + 2127 + break; 2128 2128 2129 2129 case INSN_CONTEXT_SWITCH: 2130 2130 if (func && (!next_insn || !next_insn->hint)) {