aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2017-05-02 14:34:54 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-02 15:04:50 -0400
commitddc665a4bb4b728b4e6ecec8db1b64efa9184b9c (patch)
treef28372bae13b016fa9f9d30a074d0b77f111aac6
parent85f68fe89832057584a9e66e1e7e53d53e50faff (diff)
bpf, arm64: fix jit branch offset related to ldimm64
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>
-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 4f2b35130f3c..d68abde52740 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -776,14 +776,14 @@ static int build_body(struct jit_ctx *ctx)
776 int ret; 776 int ret;
777 777
778 ret = build_insn(insn, ctx); 778 ret = build_insn(insn, ctx);
779
780 if (ctx->image == NULL)
781 ctx->offset[i] = ctx->idx;
782
783 if (ret > 0) { 779 if (ret > 0) {
784 i++; 780 i++;
781 if (ctx->image == NULL)
782 ctx->offset[i] = ctx->idx;
785 continue; 783 continue;
786 } 784 }
785 if (ctx->image == NULL)
786 ctx->offset[i] = ctx->idx;
787 if (ret) 787 if (ret)
788 return ret; 788 return ret;
789 } 789 }
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 3a7730ca81be..a0f66280ea50 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -4761,6 +4761,51 @@ static struct bpf_test tests[] = {
4761 { }, 4761 { },
4762 { { 0, 1 } }, 4762 { { 0, 1 } },
4763 }, 4763 },
4764 {
4765 /* Mainly testing JIT + imm64 here. */
4766 "JMP_JGE_X: ldimm64 test 1",
4767 .u.insns_int = {
4768 BPF_ALU32_IMM(BPF_MOV, R0, 0),
4769 BPF_LD_IMM64(R1, 3),
4770 BPF_LD_IMM64(R2, 2),
4771 BPF_JMP_REG(BPF_JGE, R1, R2, 2),
4772 BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
4773 BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
4774 BPF_EXIT_INSN(),
4775 },
4776 INTERNAL,
4777 { },
4778 { { 0, 0xeeeeeeeeU } },
4779 },
4780 {
4781 "JMP_JGE_X: ldimm64 test 2",
4782 .u.insns_int = {
4783 BPF_ALU32_IMM(BPF_MOV, R0, 0),
4784 BPF_LD_IMM64(R1, 3),
4785 BPF_LD_IMM64(R2, 2),
4786 BPF_JMP_REG(BPF_JGE, R1, R2, 0),
4787 BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
4788 BPF_EXIT_INSN(),
4789 },
4790 INTERNAL,
4791 { },
4792 { { 0, 0xffffffffU } },
4793 },
4794 {
4795 "JMP_JGE_X: ldimm64 test 3",
4796 .u.insns_int = {
4797 BPF_ALU32_IMM(BPF_MOV, R0, 1),
4798 BPF_LD_IMM64(R1, 3),
4799 BPF_LD_IMM64(R2, 2),
4800 BPF_JMP_REG(BPF_JGE, R1, R2, 4),
4801 BPF_LD_IMM64(R0, 0xffffffffffffffffUL),
4802 BPF_LD_IMM64(R0, 0xeeeeeeeeeeeeeeeeUL),
4803 BPF_EXIT_INSN(),
4804 },
4805 INTERNAL,
4806 { },
4807 { { 0, 1 } },
4808 },
4764 /* BPF_JMP | BPF_JNE | BPF_X */ 4809 /* BPF_JMP | BPF_JNE | BPF_X */
4765 { 4810 {
4766 "JMP_JNE_X: if (3 != 2) return 1", 4811 "JMP_JNE_X: if (3 != 2) return 1",