[PATCH v2] LoongArch: BPF: Fix off-by-one error for insn_is_cast_user

Tiezhu Yang posted 1 patch 3 weeks, 5 days ago
arch/loongarch/net/bpf_jit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH v2] LoongArch: BPF: Fix off-by-one error for insn_is_cast_user
Posted by Tiezhu Yang 3 weeks, 5 days ago
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.

Fixes: 4fdb5dd8aeba ("LoongArch: BPF: Implement bpf_addr_space_cast instruction")
Cc: stable@vger.kernel.org
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
v2: Update the commit message, no code changes.

 arch/loongarch/net/bpf_jit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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;
-- 
2.42.0
Re: [PATCH v2] LoongArch: BPF: Fix off-by-one error for insn_is_cast_user
Posted by Huacai Chen 3 weeks ago
Applied, thanks.


Huacai

On Mon, Aug 31, 2026 at 10:31 AM Tiezhu Yang <yangtiezhu@loongson.cn> wrote:
>
> 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.
>
> Fixes: 4fdb5dd8aeba ("LoongArch: BPF: Implement bpf_addr_space_cast instruction")
> Cc: stable@vger.kernel.org
> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
> v2: Update the commit message, no code changes.
>
>  arch/loongarch/net/bpf_jit.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> 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;
> --
> 2.42.0
>