aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2017-05-02 14:34:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-14 08:00:21 -0400
commit493d0a7be31caba12734942d14fa28bed389862a (patch)
tree44b8c3de1e743c848ff94c321fb158a952e1f15f
parent7bca0a9702edfc8d0e7e46f984ca422ffdbe0498 (diff)
bpf, arm64: fix jit branch offset related to ldimm64
[ Upstream commit ddc665a4bb4b728b4e6ecec8db1b64efa9184b9c ] 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 // #3 00000028: d2800041 mov x1, #0x2 // #2 0000002c: eb01001f cmp x0, x1 00000030: 54ffff82 b.cs 0x00000020 00000034: d29fffe7 mov x7, #0xffff // #65535 00000038: f2bfffe7 movk x7, #0xffff, lsl #16 0000003c: f2dfffe7 movk x7, #0xffff, lsl #32 00000040: f2ffffe7 movk x7, #0xffff, lsl #48 00000044: d29dddc7 mov x7, #0xeeee // #61166 00000048: f2bdddc7 movk x7, #0xeeee, lsl #16 0000004c: f2ddddc7 movk x7, #0xeeee, lsl #32 00000050: f2fdddc7 movk x7, #0xeeee, lsl #48 [...] After (ldimm64 test 1): [...] 00000020: 52800007 mov w7, #0x0 // #0 00000024: d2800060 mov x0, #0x3 // #3 00000028: d2800041 mov x1, #0x2 // #2 0000002c: eb01001f cmp x0, x1 00000030: 540000a2 b.cs 0x00000044 00000034: d29fffe7 mov x7, #0xffff // #65535 00000038: f2bfffe7 movk x7, #0xffff, lsl #16 0000003c: f2dfffe7 movk x7, #0xffff, lsl #32 00000040: f2ffffe7 movk x7, #0xffff, lsl #48 00000044: d29dddc7 mov x7, #0xeeee // #61166 00000048: f2bdddc7 movk x7, #0xeeee, lsl #16 0000004c: f2ddddc7 movk x7, #0xeeee, lsl #32 00000050: f2fdddc7 movk x7, #0xeeee, lsl #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: 8eee539ddea0 ("arm64: bpf: fix out-of-bounds read in bpf2a64_offset()") Reported-by: David S. Miller <davem@davemloft.net> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Cc: Xi Wang <xi.wang@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/arm64/net/bpf_jit_comp.c8
-rw-r--r--lib/test_bpf.c45
2 files changed, 49 insertions, 4 deletions
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index b2fc97a2c56c..9c4b57a7b265 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -779,14 +779,14 @@ static int build_body(struct jit_ctx *ctx)
779 int ret; 779 int ret;
780 780
781 ret = build_insn(insn, ctx); 781 ret = build_insn(insn, ctx);
782
783 if (ctx->image == NULL)
784 ctx->offset[i] = ctx->idx;
785
786 if (ret > 0) { 782 if (ret > 0) {
787 i++; 783 i++;
784 if (ctx->image == NULL)
785 ctx->offset[i] = ctx->idx;
788 continue; 786 continue;
789 } 787 }
788 if (ctx->image == NULL)
789 ctx->offset[i] = ctx->idx;
790 if (ret) 790 if (ret)
791 return ret; 791 return ret;
792 } 792 }
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 0362da0b66c3..2e385026915c 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -4656,6 +4656,51 @@ static struct bpf_test tests[] = {
4656 { }, 4656 { },
4657 { { 0, 1 } }, 4657 { { 0, 1 } },
4658 }, 4658 },
4659 {
4660 /* Mainly testing JIT + imm64 here. */
4661 "JMP_JGE_X: ldimm64 test 1",
4662 .u.insns_int = {
4663 BPF_ALU32_IMM(BPF_MOV, R0, 0),
4664 BPF_LD_IMM64(R1, 3),
4665 BPF_LD_IMM64(R2, 2),
4666 BPF_JMP_REG(BPF_JGE, R1, R2, 2),
4667 BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
4668 BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
4669 BPF_EXIT_INSN(),
4670 },
4671 INTERNAL,
4672 { },
4673 { { 0, 0xeeeeeeeeU } },
4674 },
4675 {
4676 "JMP_JGE_X: ldimm64 test 2",
4677 .u.insns_int = {
4678 BPF_ALU32_IMM(BPF_MOV, R0, 0),
4679 BPF_LD_IMM64(R1, 3),
4680 BPF_LD_IMM64(R2, 2),
4681 BPF_JMP_REG(BPF_JGE, R1, R2, 0),
4682 BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
4683 BPF_EXIT_INSN(),
4684 },
4685 INTERNAL,
4686 { },
4687 { { 0, 0xffffffffU } },
4688 },
4689 {
4690 "JMP_JGE_X: ldimm64 test 3",
4691 .u.insns_int = {
4692 BPF_ALU32_IMM(BPF_MOV, R0, 1),
4693 BPF_LD_IMM64(R1, 3),
4694 BPF_LD_IMM64(R2, 2),
4695 BPF_JMP_REG(BPF_JGE, R1, R2, 4),
4696 BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
4697 BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
4698 BPF_EXIT_INSN(),
4699 },
4700 INTERNAL,
4701 { },
4702 { { 0, 1 } },
4703 },
4659 /* BPF_JMP | BPF_JNE | BPF_X */ 4704 /* BPF_JMP | BPF_JNE | BPF_X */
4660 { 4705 {
4661 "JMP_JNE_X: if (3 != 2) return 1", 4706 "JMP_JNE_X: if (3 != 2) return 1",