From: Peter Zijlstra peterz@infradead.org
commit e52c1dc7455d32c8a55f9949d300e5e87d011fa6 upstream.
FineIBT-paranoid was using the retpoline bytes for the paranoid check, disabling retpolines, because all parts that have IBT also have eIBRS and thus don't need no stinking retpolines.
Except... ITS needs the retpolines for indirect calls must not be in the first half of a cacheline :-/
So what was the paranoid call sequence:
<fineibt_paranoid_start>: 0: 41 ba 78 56 34 12 mov $0x12345678, %r10d 6: 45 3b 53 f7 cmp -0x9(%r11), %r10d a: 4d 8d 5b <f0> lea -0x10(%r11), %r11 e: 75 fd jne d <fineibt_paranoid_start+0xd> 10: 41 ff d3 call *%r11 13: 90 nop
Now becomes:
<fineibt_paranoid_start>: 0: 41 ba 78 56 34 12 mov $0x12345678, %r10d 6: 45 3b 53 f7 cmp -0x9(%r11), %r10d a: 4d 8d 5b f0 lea -0x10(%r11), %r11 e: 2e e8 XX XX XX XX cs call __x86_indirect_paranoid_thunk_r11
Where the paranoid_thunk looks like:
1d: <ea> (bad) __x86_indirect_paranoid_thunk_r11: 1e: 75 fd jne 1d __x86_indirect_its_thunk_r11: 20: 41 ff eb jmp *%r11 23: cc int3
[ dhansen: remove initialization to false ]
[ pawan: move the its_static_thunk() definition to alternative.c. This is done to avoid a build failure due to circular dependency between kernel.h(asm-generic/bug.h) and asm/alternative.h which is neeed for WARN_ONCE(). ]
Signed-off-by: Peter Zijlstra (Intel) peterz@infradead.org Signed-off-by: Dave Hansen dave.hansen@linux.intel.com Reviewed-by: Alexandre Chartre alexandre.chartre@oracle.com [ Just a portion of the original commit, in order to fix a build issue in stable kernels due to backports ] Tested-by: Holger Hoffstätte holger@applied-asynchrony.com Link: https://lore.kernel.org/r/20250514113952.GB16434@noisy.programming.kicks-ass... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Pawan Gupta pawan.kumar.gupta@linux.intel.com --- arch/x86/include/asm/alternative.h | 2 ++ arch/x86/kernel/alternative.c | 19 ++++++++++++++++++- arch/x86/net/bpf_jit_comp.c | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 4ab021fd3887211723e0bf0f68683e713f260f07..f2cce0cd87a65c4a9ad2d934cc8c8bb651971576 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -80,6 +80,8 @@ extern void apply_returns(s32 *start, s32 *end);
struct module;
+extern u8 *its_static_thunk(int reg); + #ifdef CONFIG_MITIGATION_ITS extern void its_init_mod(struct module *mod); extern void its_fini_mod(struct module *mod); diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 923b4d1e98dbc378270e254960fcb7ce1bc3e665..30dc73210c2ea4c14de38810f47db1d5381ce378 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -752,7 +752,24 @@ static bool cpu_wants_indirect_its_thunk_at(unsigned long addr, int reg) /* Lower-half of the cacheline? */ return !(addr & 0x20); } -#endif + +u8 *its_static_thunk(int reg) +{ + u8 *thunk = __x86_indirect_its_thunk_array[reg]; + + return thunk; +} + +#else /* CONFIG_MITIGATION_ITS */ + +u8 *its_static_thunk(int reg) +{ + WARN_ONCE(1, "ITS not compiled in"); + + return NULL; +} + +#endif /* CONFIG_MITIGATION_ITS */
/* * Rewrite the compiler generated retpoline thunk calls. diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index c322702126407e4102cbd0a874264dd69b17b9fd..d3450088569ff3364f456dfa5f2e06ca90b80fe7 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -390,7 +390,7 @@ static void emit_indirect_jump(u8 **pprog, int reg, u8 *ip) if (IS_ENABLED(CONFIG_MITIGATION_ITS) && cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) { OPTIMIZER_HIDE_VAR(reg); - emit_jump(&prog, &__x86_indirect_its_thunk_array[reg], ip); + emit_jump(&prog, its_static_thunk(reg), ip); } else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) { EMIT_LFENCE(); EMIT2(0xFF, 0xE0 + reg);