4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Russell King <rmk+ker...@armlinux.org.uk>

commit f4483f2cc1fdc03488c8a1452e545545ae5bda93 upstream.

When a tail call fails, it is documented that the tail call should
continue execution at the following instruction.  An example tail call
sequence is:

  12: (85) call bpf_tail_call#12
  13: (b7) r0 = 0
  14: (95) exit

The ARM assembler for the tail call in this case ends up branching to
instruction 14 instead of instruction 13, resulting in the BPF filter
returning a non-zero value:

  178:  ldr     r8, [sp, #588]  ; insn 12
  17c:  ldr     r6, [r8, r6]
  180:  ldr     r8, [sp, #580]
  184:  cmp     r8, r6
  188:  bcs     0x1e8
  18c:  ldr     r6, [sp, #524]
  190:  ldr     r7, [sp, #528]
  194:  cmp     r7, #0
  198:  cmpeq   r6, #32
  19c:  bhi     0x1e8
  1a0:  adds    r6, r6, #1
  1a4:  adc     r7, r7, #0
  1a8:  str     r6, [sp, #524]
  1ac:  str     r7, [sp, #528]
  1b0:  mov     r6, #104
  1b4:  ldr     r8, [sp, #588]
  1b8:  add     r6, r8, r6
  1bc:  ldr     r8, [sp, #580]
  1c0:  lsl     r7, r8, #2
  1c4:  ldr     r6, [r6, r7]
  1c8:  cmp     r6, #0
  1cc:  beq     0x1e8
  1d0:  mov     r8, #32
  1d4:  ldr     r6, [r6, r8]
  1d8:  add     r6, r6, #44
  1dc:  bx      r6
  1e0:  mov     r0, #0          ; insn 13
  1e4:  mov     r1, #0
  1e8:  add     sp, sp, #596    ; insn 14
  1ec:  pop     {r4, r5, r6, r7, r8, sl, pc}

For other sequences, the tail call could end up branching midway through
the following BPF instructions, or maybe off the end of the function,
leading to unknown behaviours.

Fixes: 39c13c204bb1 ("arm: eBPF JIT compiler")
Signed-off-by: Russell King <rmk+ker...@armlinux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

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

--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -949,7 +949,7 @@ static int emit_bpf_tail_call(struct jit
        const u8 *tcc = bpf2a32[TCALL_CNT];
        const int idx0 = ctx->idx;
 #define cur_offset (ctx->idx - idx0)
-#define jmp_offset (out_offset - (cur_offset))
+#define jmp_offset (out_offset - (cur_offset) - 2)
        u32 off, lo, hi;
 
        /* if (index >= array->map.max_entries)


Reply via email to