bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* arm64 jit ctx.offset[-1] access
@ 2020-09-07 15:14 Yauheni Kaliuta
  2020-09-09 21:50 ` Luke Nelson
  0 siblings, 1 reply; 2+ messages in thread
From: Yauheni Kaliuta @ 2020-09-07 15:14 UTC (permalink / raw)
  To: bpf; +Cc: Zi Shen Lim

Hi!

Looks like my first message did not reach the list, resending:

I have a question about arm64 bpf jit implementation.

The problem I observe is "taken loop with back jump to 1st insn"
verifier test, the subprogram is:

BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1),
BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, -3),
BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
BPF_EXIT_INSN(),

Jitting the program causes invocation of bpf2a64_offset(-1, 2, ctx)
from
        jmp_offset = bpf2a64_offset(i + off, i, ctx);

which does ctx->offset[-1] then (and works by accident when it
returns 0).

As far as I see, the offset[] keeps actually offsets of the next
instruction:

                ret = build_insn(insn, ctx, extra_pass);
                if (ret > 0) {
                        i++;
                        if (ctx->image == NULL)
                                ctx->offset[i] = ctx->idx;
                        continue;
                }
                if (ctx->image == NULL)
                        ctx->offset[i] = ctx->idx;


ctx->idx is updated by build_insn() already.

How is that supposed to work?

-- 
WBR, Yauheni


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: arm64 jit ctx.offset[-1] access
  2020-09-07 15:14 arm64 jit ctx.offset[-1] access Yauheni Kaliuta
@ 2020-09-09 21:50 ` Luke Nelson
  0 siblings, 0 replies; 2+ messages in thread
From: Luke Nelson @ 2020-09-09 21:50 UTC (permalink / raw)
  To: Yauheni Kaliuta; +Cc: bpf, Zi Shen Lim

Hi Yauheni,

Thanks for the report!

>
> Jitting the program causes invocation of bpf2a64_offset(-1, 2, ctx)
> from
>         jmp_offset = bpf2a64_offset(i + off, i, ctx);
>
> which does ctx->offset[-1] then (and works by accident when it
> returns 0).
>

This definitely looks like a bug to me, I ran your test program and
printed out the values of bpf_to in bpf2a64_offset and it is being called
with bpf_to = -1.

One way to fix this is to do something similar to what the RISC-V JITs
do here, by checking for the < 0 case explicitly:

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/riscv/net/bpf_jit.h?h=v5.8.8#n145

I imagine it would look something like the following:

--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -146,11 +146,11 @@ static inline void emit_addr_mov_i64(const int
reg, const u64 val,
 static inline int bpf2a64_offset(int bpf_to, int bpf_from,
                                 const struct jit_ctx *ctx)
 {
-       int to = ctx->offset[bpf_to];
-       /* -1 to account for the Branch instruction */
-       int from = ctx->offset[bpf_from] - 1;
+       int to = (bpf_to >= 0) ? ctx->offset[bpf_to] : 0;
+       int from = (bpf_from >= 0) ? ctx->offset[bpf_from] : 0;

-       return to - from;
+       /* -1 to account for the Branch instruction. */
+       return to - (from - 1);
 }

Anybody else have any thoughts? I can turn around and submit this as an
actual patch if it seems reasonable to others.

- Luke

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-09-09 21:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-07 15:14 arm64 jit ctx.offset[-1] access Yauheni Kaliuta
2020-09-09 21:50 ` Luke Nelson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).