Skip to content

Commit 7e25869

Browse files
chenhengqichenhuacai
authored andcommitted
LoongArch: BPF: Fix off-by-one error in build_prologue()
Vincent reported that running BPF progs with tailcalls on LoongArch causes kernel hard lockup. Debugging the issues shows that the JITed image missing a jirl instruction at the end of the epilogue. There are two passes in JIT compiling, the first pass set the flags and the second pass generates JIT code based on those flags. With BPF progs mixing bpf2bpf and tailcalls, build_prologue() generates N insns in the first pass and then generates N+1 insns in the second pass. This makes epilogue_offset off by one and we will jump to some unexpected insn and cause lockup. Fix this by inserting a nop insn. Cc: stable@vger.kernel.org Fixes: 5dc6155 ("LoongArch: Add BPF JIT support") Fixes: bb035ef ("LoongArch: BPF: Support mixing bpf2bpf and tailcalls") Reported-by: Vincent Li <vincent.mc.li@gmail.com> Tested-by: Vincent Li <vincent.mc.li@gmail.com> Closes: https://lore.kernel.org/loongarch/CAK3+h2w6WESdBN3UCr3WKHByD7D6Q_Ve1EDAjotVrnx6Or_c8g@mail.gmail.com/ Closes: https://lore.kernel.org/bpf/CAK3+h2woEjG_N=-XzqEGaAeCmgu2eTCUc7p6bP4u8Q+DFHm-7g@mail.gmail.com/ Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 29c92a4 commit 7e25869

File tree

2 files changed

+7
-0
lines changed

2 files changed

+7
-0
lines changed

arch/loongarch/net/bpf_jit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ static void build_prologue(struct jit_ctx *ctx)
142142
*/
143143
if (seen_tail_call(ctx) && seen_call(ctx))
144144
move_reg(ctx, TCC_SAVED, REG_TCC);
145+
else
146+
emit_insn(ctx, nop);
145147

146148
ctx->stack_size = stack_adjust;
147149
}

arch/loongarch/net/bpf_jit.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ struct jit_data {
2727
struct jit_ctx ctx;
2828
};
2929

30+
static inline void emit_nop(union loongarch_instruction *insn)
31+
{
32+
insn->word = INSN_NOP;
33+
}
34+
3035
#define emit_insn(ctx, func, ...) \
3136
do { \
3237
if (ctx->image != NULL) { \

0 commit comments

Comments
 (0)