summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTiezhu Yang <yangtiezhu@loongson.cn>2026-09-04 21:44:43 +0800
committerHuacai Chen <chenhuacai@loongson.cn>2026-09-04 21:44:43 +0800
commit30419a0aa128135a81be917eaa3bd2f1a10c9ca3 (patch)
tree6a1631e831a65d7d08e92b0903c89ea402815f16
parent72ce4b24676e8b3b75376c4c559dd81c1ac52d5a (diff)
downloadlinux-30419a0aa128135a81be917eaa3bd2f1a10c9ca3.tar.gz
linux-30419a0aa128135a81be917eaa3bd2f1a10c9ca3.zip
LoongArch: BPF: Fix off-by-one error for insn_is_cast_user()
In the LoongArch BPF JIT code, the branch offset represents the number of instructions. An offset of 1 means the target of the "beq" is the current PC plus 1 instruction (PC + 4 bytes). This matches the exact same path as the sequential non-branch execution, the "or" instruction is always executed for the cast_user JIT arm in build_insn(). If the pointer is not NULL, there is no side effect. But if the pointer is NULL, it is incorrectly combined with the base address and turns into a non-zero address, meaning a zero arena offset no longer casts to NULL. Fix this by changing the branch offset from 1 to 2, which properly skips the "or" instruction and jumps directly to the "move_reg" instruction if the pointer is NULL, ensuring the destination register is safely cleared to 0. Cc: stable@vger.kernel.org Fixes: 4fdb5dd8aeba ("LoongArch: BPF: Implement bpf_addr_space_cast instruction") Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
-rw-r--r--arch/loongarch/net/bpf_jit.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index 1eb588e443c9..4da278900938 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -717,7 +717,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
move_reg(ctx, t1, src);
emit_zext_32(ctx, t1, true);
move_imm(ctx, dst, (ctx->user_vm_start >> 32) << 32, false);
- emit_insn(ctx, beq, t1, LOONGARCH_GPR_ZERO, 1);
+ emit_insn(ctx, beq, t1, LOONGARCH_GPR_ZERO, 2);
emit_insn(ctx, or, t1, dst, t1);
move_reg(ctx, dst, t1);
break;