Skip to content

Commit

Permalink
bpf, arm64: fix jit branch offset related to ldimm64
Browse files Browse the repository at this point in the history
When the instruction right before the branch destination is
a 64 bit load immediate, we currently calculate the wrong
jump offset in the ctx->offset[] array as we only account
one instruction slot for the 64 bit load immediate although
it uses two BPF instructions. Fix it up by setting the offset
into the right slot after we incremented the index.

Before (ldimm64 test 1):

  [...]
  00000020:  52800007  mov w7, #0x0 // #0
  00000024:  d2800060  mov x0, #0x3 // open-power-host-os#3
  00000028:  d2800041  mov x1, #0x2 // open-power-host-os#2
  0000002c:  eb01001f  cmp x0, x1
  00000030:  54ffff82  b.cs 0x00000020
  00000034:  d29fffe7  mov x7, #0xffff // #65535
  00000038:  f2bfffe7  movk x7, #0xffff, lsl open-power-host-os#16
  0000003c:  f2dfffe7  movk x7, #0xffff, lsl open-power-host-os#32
  00000040:  f2ffffe7  movk x7, #0xffff, lsl torvalds#48
  00000044:  d29dddc7  mov x7, #0xeeee // #61166
  00000048:  f2bdddc7  movk x7, #0xeeee, lsl open-power-host-os#16
  0000004c:  f2ddddc7  movk x7, #0xeeee, lsl open-power-host-os#32
  00000050:  f2fdddc7  movk x7, #0xeeee, lsl torvalds#48
  [...]

After (ldimm64 test 1):

  [...]
  00000020:  52800007  mov w7, #0x0 // #0
  00000024:  d2800060  mov x0, #0x3 // open-power-host-os#3
  00000028:  d2800041  mov x1, #0x2 // open-power-host-os#2
  0000002c:  eb01001f  cmp x0, x1
  00000030:  540000a2  b.cs 0x00000044
  00000034:  d29fffe7  mov x7, #0xffff // #65535
  00000038:  f2bfffe7  movk x7, #0xffff, lsl open-power-host-os#16
  0000003c:  f2dfffe7  movk x7, #0xffff, lsl open-power-host-os#32
  00000040:  f2ffffe7  movk x7, #0xffff, lsl torvalds#48
  00000044:  d29dddc7  mov x7, #0xeeee // #61166
  00000048:  f2bdddc7  movk x7, #0xeeee, lsl open-power-host-os#16
  0000004c:  f2ddddc7  movk x7, #0xeeee, lsl open-power-host-os#32
  00000050:  f2fdddc7  movk x7, #0xeeee, lsl torvalds#48
  [...]

Also, add a couple of test cases to make sure JITs pass
this test. Tested on Cavium ThunderX ARMv8. The added
test cases all pass after the fix.

Fixes: 8eee539 ("arm64: bpf: fix out-of-bounds read in bpf2a64_offset()")
Reported-by: David S. Miller <[email protected]>
Signed-off-by: Daniel Borkmann <[email protected]>
Acked-by: Alexei Starovoitov <[email protected]>
Cc: Xi Wang <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
borkmann authored and davem330 committed May 2, 2017
1 parent 85f68fe commit ddc665a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
8 changes: 4 additions & 4 deletions arch/arm64/net/bpf_jit_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,14 +776,14 @@ static int build_body(struct jit_ctx *ctx)
int ret;

ret = build_insn(insn, ctx);

if (ctx->image == NULL)
ctx->offset[i] = ctx->idx;

if (ret > 0) {
i++;
if (ctx->image == NULL)
ctx->offset[i] = ctx->idx;
continue;
}
if (ctx->image == NULL)
ctx->offset[i] = ctx->idx;
if (ret)
return ret;
}
Expand Down
45 changes: 45 additions & 0 deletions lib/test_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4761,6 +4761,51 @@ static struct bpf_test tests[] = {
{ },
{ { 0, 1 } },
},
{
/* Mainly testing JIT + imm64 here. */
"JMP_JGE_X: ldimm64 test 1",
.u.insns_int = {
BPF_ALU32_IMM(BPF_MOV, R0, 0),
BPF_LD_IMM64(R1, 3),
BPF_LD_IMM64(R2, 2),
BPF_JMP_REG(BPF_JGE, R1, R2, 2),
BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
BPF_EXIT_INSN(),
},
INTERNAL,
{ },
{ { 0, 0xeeeeeeeeU } },
},
{
"JMP_JGE_X: ldimm64 test 2",
.u.insns_int = {
BPF_ALU32_IMM(BPF_MOV, R0, 0),
BPF_LD_IMM64(R1, 3),
BPF_LD_IMM64(R2, 2),
BPF_JMP_REG(BPF_JGE, R1, R2, 0),
BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
BPF_EXIT_INSN(),
},
INTERNAL,
{ },
{ { 0, 0xffffffffU } },
},
{
"JMP_JGE_X: ldimm64 test 3",
.u.insns_int = {
BPF_ALU32_IMM(BPF_MOV, R0, 1),
BPF_LD_IMM64(R1, 3),
BPF_LD_IMM64(R2, 2),
BPF_JMP_REG(BPF_JGE, R1, R2, 4),
BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
BPF_EXIT_INSN(),
},
INTERNAL,
{ },
{ { 0, 1 } },
},
/* BPF_JMP | BPF_JNE | BPF_X */
{
"JMP_JNE_X: if (3 != 2) return 1",
Expand Down

0 comments on commit ddc665a

Please sign in to comment.