From: Christophe Fontaine <[email protected]>

The DPDK BPF JIT standalone test test_ld_mbuf1 fails on arm64.
It does:
        r6 = r1                    // mbuf
        r0 = *(u8 *)pkt[0]         // BPF_ABS
        if ((r0 & 0xf0) == 0x40)
                goto parse
        r0 = 0
        exit                       // epilogue E0
parse:
        r0 = *(u8 *)pkt[r0 + 3]    // BPF_IND
        ...
        exit

emit_return_zero_if_src_zero() returns 0 by branching to a function
epilogue. The target maybe a previous epilogue so branch
might be backwards; therefore the offset needs to be negative.

The offset was stored in a uint16_t, so a negative value wrapped to a
large positive number; emit_b() then branched past the end of the
program and faulted at run time.

Fixes: 111e2a747a4f ("bpf/arm: add basic arithmetic operations")
Cc: [email protected]

Signed-off-by: Christophe Fontaine <[email protected]>
Signed-off-by: Stephen Hemminger <[email protected]>
---
 lib/bpf/bpf_jit_arm64.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/bpf/bpf_jit_arm64.c b/lib/bpf/bpf_jit_arm64.c
index a04ef33a9c..67e42015de 100644
--- a/lib/bpf/bpf_jit_arm64.c
+++ b/lib/bpf/bpf_jit_arm64.c
@@ -957,10 +957,12 @@ static void
 emit_return_zero_if_src_zero(struct a64_jit_ctx *ctx, bool is64, uint8_t src)
 {
        uint8_t r0 = ebpf_to_a64_reg(ctx, EBPF_REG_0);
-       uint16_t jump_to_epilogue;
+       int32_t jump_to_epilogue;
 
        emit_cbnz(ctx, is64, src, 3);
        emit_mov_imm(ctx, is64, r0, 0);
+
+       /* maybe backwards branch to earlier epilogue */
        jump_to_epilogue = (ctx->program_start + ctx->program_sz) - ctx->idx;
        emit_b(ctx, jump_to_epilogue);
 }
-- 
2.53.0

Reply via email to