Re: [PATCH v3 bpf-next 07/13] bpf, x86: allow indirect jumps to r8...r15

Eduard Zingerman
2025-09-19T18:25:04Z

On Thu, 2025-09-18 at 09:38 +0000, Anton Protopopov wrote:
> Currently the emit_indirect_jump() function only accepts one of the
> RAX, RCX, ..., RBP registers as the destination. Make it to accept
> R8, R9, ..., R15 as well, and make callers to pass BPF registers, not
> native registers. This is required to enable indirect jumps support
> in eBPF.
>
> Signed-off-by: Anton Protopopov <a.s.protopopov@gmail.com>
> ---
> arch/x86/net/bpf_jit_comp.c | 28 +++++++++++++++++++++-------
> 1 file changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index 8792d7f371d3..fcebb48742ae 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -660,24 +660,38 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
>
> #define EMIT_LFENCE() EMIT3(0x0F, 0xAE, 0xE8)
>
> -static void emit_indirect_jump(u8 **pprog, int reg, u8 *ip)
> +static void __emit_indirect_jump(u8 **pprog, int reg, bool ereg)
> {
> u8 *prog = *pprog; <------------------------------------------------------------------------.
> |
> + if (ereg) |
> + EMIT1(0x41); |
> + |
> + EMIT2(0xFF, 0xE0 + reg); |
> + |
> + *pprog = prog; <------------------------------------------------------------------------|
> +} |
> + |
> +static void emit_indirect_jump(u8 **pprog, int bpf_reg, u8 *ip) |
> +{ |
> + u8 *prog = *pprog; <------------------------------------------------------------------------|
> + int reg = reg2hex[bpf_reg]; |
> + bool ereg = is_ereg(bpf_reg); |
> + |
> if (cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) { |
> OPTIMIZER_HIDE_VAR(reg); |
> emit_jump(&prog, its_static_thunk(reg), ip); |
> } else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) { |
> EMIT_LFENCE(); |
> - EMIT2(0xFF, 0xE0 + reg); |
> + __emit_indirect_jump(pprog, reg, ereg); |
> } else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) { |
> OPTIMIZER_HIDE_VAR(reg); |
> if (cpu_feature_enabled(X86_FEATURE_CALL_DEPTH)) |
> - emit_jump(&prog, &__x86_indirect_jump_thunk_array[reg], ip); |
> + emit_jump(&prog, &__x86_indirect_jump_thunk_array[reg + 8*ereg], ip); |
> else |
> - emit_jump(&prog, &__x86_indirect_thunk_array[reg], ip); |
> + emit_jump(&prog, &__x86_indirect_thunk_array[reg + 8*ereg], ip); |
> } else { |
> - EMIT2(0xFF, 0xE0 + reg); /* jmp *%\reg */ |
> + __emit_indirect_jump(pprog, reg, ereg); <----------------------------------------|
|
You need to re-read *pprog after __emit_indirect_jump() call |
this is what causes KASAN error I reported in the sibling thread. |
W/o re-reading it the FF E1 emitted above is overwritten to CC E1 |
by EMIT1(0xCC) below. |
|
> if (IS_ENABLED(CONFIG_MITIGATION_RETPOLINE) || IS_ENABLED(CONFIG_MITIGATION_SLS)) |
> EMIT1(0xCC); /* int3 */ <----------------------------------------'
> }