[4.2.y-ckt stable] Patch "arm64: bpf: fix div-by-zero case" has been added to staging queue

2016-01-04 Thread Kamal Mostafa
This is a note to let you know that I have just added a patch titled

arm64: bpf: fix div-by-zero case

to the linux-4.2.y-queue branch of the 4.2.y-ckt extended stable tree 
which can be found at:

http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-4.2.y-queue

This patch is scheduled to be released in version 4.2.8-ckt1.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 4.2.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

--

>From 2d1726efaefaee9e95587f83a3b15e18c5d8f436 Mon Sep 17 00:00:00 2001
From: Zi Shen Lim 
Date: Tue, 3 Nov 2015 22:56:44 -0800
Subject: arm64: bpf: fix div-by-zero case

commit 251599e1d6906621f49218d7b474ddd159e58f3b upstream.

In the case of division by zero in a BPF program:
A = A / X;  (X == 0)
the expected behavior is to terminate with return value 0.

This is confirmed by the test case introduced in commit 86bf1721b226
("test_bpf: add tests checking that JIT/interpreter sets A and X to 0.").

Reported-by: Yang Shi 
Tested-by: Yang Shi 
CC: Xi Wang 
CC: Alexei Starovoitov 
CC: linux-arm-ker...@lists.infradead.org
CC: linux-kernel@vger.kernel.org
Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
Signed-off-by: Zi Shen Lim 
Signed-off-by: Catalin Marinas 
Signed-off-by: Kamal Mostafa 
---
 arch/arm64/net/bpf_jit.h  |  3 ++-
 arch/arm64/net/bpf_jit_comp.c | 37 +
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index 98a26ce..aee5637 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -35,6 +35,7 @@
aarch64_insn_gen_comp_branch_imm(0, offset, Rt, A64_VARIANT(sf), \
AARCH64_INSN_BRANCH_COMP_##type)
 #define A64_CBZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, ZERO)
+#define A64_CBNZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, NONZERO)

 /* Conditional branch (immediate) */
 #define A64_COND_BRANCH(cond, offset) \
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index c047598..9ae6f23 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -225,6 +225,17 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
u8 jmp_cond;
s32 jmp_offset;

+#define check_imm(bits, imm) do {  \
+   if imm) > 0) && ((imm) >> (bits))) ||   \
+   (((imm) < 0) && (~(imm) >> (bits {  \
+   pr_info("[%2d] imm=%d(0x%x) out of range\n",\
+   i, imm, imm);   \
+   return -EINVAL; \
+   }   \
+} while (0)
+#define check_imm19(imm) check_imm(19, imm)
+#define check_imm26(imm) check_imm(26, imm)
+
switch (code) {
/* dst = src */
case BPF_ALU | BPF_MOV | BPF_X:
@@ -258,8 +269,21 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
break;
case BPF_ALU | BPF_DIV | BPF_X:
case BPF_ALU64 | BPF_DIV | BPF_X:
+   {
+   const u8 r0 = bpf2a64[BPF_REG_0];
+
+   /* if (src == 0) return 0 */
+   jmp_offset = 3; /* skip ahead to else path */
+   check_imm19(jmp_offset);
+   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
+   emit(A64_MOVZ(1, r0, 0, 0), ctx);
+   jmp_offset = epilogue_offset(ctx);
+   check_imm26(jmp_offset);
+   emit(A64_B(jmp_offset), ctx);
+   /* else */
emit(A64_UDIV(is64, dst, dst, src), ctx);
break;
+   }
case BPF_ALU | BPF_MOD | BPF_X:
case BPF_ALU64 | BPF_MOD | BPF_X:
ctx->tmp_used = 1;
@@ -393,17 +417,6 @@ emit_bswap_uxt:
emit(A64_ASR(is64, dst, dst, imm), ctx);
break;

-#define check_imm(bits, imm) do {  \
-   if imm) > 0) && ((imm) >> (bits))) ||   \
-   (((imm) < 0) && (~(imm) >> (bits {  \
-   pr_info("[%2d] imm=%d(0x%x) out of range\n",\
-   i, imm, imm);   \
-   return -EINVAL;

[3.19.y-ckt stable] Patch "arm64: bpf: fix div-by-zero case" has been added to staging queue

2015-11-30 Thread Kamal Mostafa
This is a note to let you know that I have just added a patch titled

arm64: bpf: fix div-by-zero case

to the linux-3.19.y-queue branch of the 3.19.y-ckt extended stable tree 
which can be found at:

http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-3.19.y-queue

This patch is scheduled to be released in version 3.19.8-ckt11.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.19.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

--

>From eb0c40a4a3aef5b7997b29196511e36cd9234915 Mon Sep 17 00:00:00 2001
From: Zi Shen Lim 
Date: Tue, 3 Nov 2015 22:56:44 -0800
Subject: arm64: bpf: fix div-by-zero case

commit 251599e1d6906621f49218d7b474ddd159e58f3b upstream.

In the case of division by zero in a BPF program:
A = A / X;  (X == 0)
the expected behavior is to terminate with return value 0.

This is confirmed by the test case introduced in commit 86bf1721b226
("test_bpf: add tests checking that JIT/interpreter sets A and X to 0.").

Reported-by: Yang Shi 
Tested-by: Yang Shi 
CC: Xi Wang 
CC: Alexei Starovoitov 
CC: linux-arm-ker...@lists.infradead.org
CC: linux-kernel@vger.kernel.org
Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
Signed-off-by: Zi Shen Lim 
Signed-off-by: Catalin Marinas 
Signed-off-by: Kamal Mostafa 
---
 arch/arm64/net/bpf_jit.h  |  3 ++-
 arch/arm64/net/bpf_jit_comp.c | 37 +
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index 98a26ce..aee5637 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -35,6 +35,7 @@
aarch64_insn_gen_comp_branch_imm(0, offset, Rt, A64_VARIANT(sf), \
AARCH64_INSN_BRANCH_COMP_##type)
 #define A64_CBZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, ZERO)
+#define A64_CBNZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, NONZERO)

 /* Conditional branch (immediate) */
 #define A64_COND_BRANCH(cond, offset) \
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index c047598..9ae6f23 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -225,6 +225,17 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
u8 jmp_cond;
s32 jmp_offset;

+#define check_imm(bits, imm) do {  \
+   if imm) > 0) && ((imm) >> (bits))) ||   \
+   (((imm) < 0) && (~(imm) >> (bits {  \
+   pr_info("[%2d] imm=%d(0x%x) out of range\n",\
+   i, imm, imm);   \
+   return -EINVAL; \
+   }   \
+} while (0)
+#define check_imm19(imm) check_imm(19, imm)
+#define check_imm26(imm) check_imm(26, imm)
+
switch (code) {
/* dst = src */
case BPF_ALU | BPF_MOV | BPF_X:
@@ -258,8 +269,21 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
break;
case BPF_ALU | BPF_DIV | BPF_X:
case BPF_ALU64 | BPF_DIV | BPF_X:
+   {
+   const u8 r0 = bpf2a64[BPF_REG_0];
+
+   /* if (src == 0) return 0 */
+   jmp_offset = 3; /* skip ahead to else path */
+   check_imm19(jmp_offset);
+   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
+   emit(A64_MOVZ(1, r0, 0, 0), ctx);
+   jmp_offset = epilogue_offset(ctx);
+   check_imm26(jmp_offset);
+   emit(A64_B(jmp_offset), ctx);
+   /* else */
emit(A64_UDIV(is64, dst, dst, src), ctx);
break;
+   }
case BPF_ALU | BPF_MOD | BPF_X:
case BPF_ALU64 | BPF_MOD | BPF_X:
ctx->tmp_used = 1;
@@ -393,17 +417,6 @@ emit_bswap_uxt:
emit(A64_ASR(is64, dst, dst, imm), ctx);
break;

-#define check_imm(bits, imm) do {  \
-   if imm) > 0) && ((imm) >> (bits))) ||   \
-   (((imm) < 0) && (~(imm) >> (bits {  \
-   pr_info("[%2d] imm=%d(0x%x) out of range\n",\
-   i, imm, imm);   \
-   return -EINVAL;  

Re: [PATCH] arm64: bpf: fix div-by-zero case

2015-11-04 Thread Daniel Borkmann

On 11/04/2015 07:41 PM, Shi, Yang wrote:
...

Agreed, and we may need add one more test cases in test_bpf module to cover
MOD?


Let me know if you have a test case ready :)


Does the below change look like a valid test?

+   "MOD default X",
+   .u.insns = {
+   /*
+* A = 0x42
+* A = A mod X ; this halt the filter execution if X is 0
+* ret 0x42
+*/
+   BPF_STMT(BPF_LD | BPF_IMM, 0x42),
+   BPF_STMT(BPF_ALU | BPF_MOD | BPF_X, 0),
+   BPF_STMT(BPF_RET | BPF_K, 0x42),
+   },
+   CLASSIC | FLAG_NO_DATA,
+   {},
+   { {0x1, 0x0 } },
+   },
+   {
+   "MOD default A",
+   .u.insns = {
+   /*
+* A = A mod 1
+* ret A
+*/
+   BPF_STMT(BPF_ALU | BPF_MOD | BPF_K, 0x1),
+   BPF_STMT(BPF_RET | BPF_A, 0x0),
+   },
+   CLASSIC | FLAG_NO_DATA,
+   {},
+   { {0x1, 0x0 } },
+   },

My test result with it:
test_bpf: #284 MOD default X jited:1 ret 66 != 0 FAIL (1 times)
test_bpf: #285 MOD default A jited:1 102 PASS

If it looks right, I will post a patch to add the test cases.


Looks good to me.

Thanks,
Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] arm64: bpf: fix div-by-zero case

2015-11-04 Thread Z Lim
On Wed, Nov 4, 2015 at 10:21 AM, Shi, Yang  wrote:
> On 11/3/2015 11:04 PM, Xi Wang wrote:
>>
>> On Tue, Nov 3, 2015 at 10:56 PM, Zi Shen Lim  wrote:
>>>
>>>  case BPF_ALU | BPF_DIV | BPF_X:
>>>  case BPF_ALU64 | BPF_DIV | BPF_X:
>>> +   {
>>> +   const u8 r0 = bpf2a64[BPF_REG_0];
>>> +
>>> +   /* if (src == 0) return 0 */
>>> +   jmp_offset = 3; /* skip ahead to else path */
>>> +   check_imm19(jmp_offset);
>>> +   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
>>> +   emit(A64_MOVZ(1, r0, 0, 0), ctx);
>>> +   jmp_offset = epilogue_offset(ctx);
>>> +   check_imm26(jmp_offset);
>>> +   emit(A64_B(jmp_offset), ctx);
>>> +   /* else */
>>>  emit(A64_UDIV(is64, dst, dst, src), ctx);
>>>  break;
>>> +   }
>>>  case BPF_ALU | BPF_MOD | BPF_X:
>>>  case BPF_ALU64 | BPF_MOD | BPF_X:
>>
>>
>> BPF_MOD might need the same fix.

I'll post a fix for this case as well.

>
>
> Agreed, and we may need add one more test cases in test_bpf module to cover
> MOD?

Let me know if you have a test case ready :)

>
> Yang
>
>>
>> ___
>> linux-arm-kernel mailing list
>> linux-arm-ker...@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] arm64: bpf: fix div-by-zero case

2015-11-04 Thread Shi, Yang

On 11/4/2015 10:25 AM, Z Lim wrote:

On Wed, Nov 4, 2015 at 10:21 AM, Shi, Yang  wrote:

On 11/3/2015 11:04 PM, Xi Wang wrote:


On Tue, Nov 3, 2015 at 10:56 PM, Zi Shen Lim  wrote:


  case BPF_ALU | BPF_DIV | BPF_X:
  case BPF_ALU64 | BPF_DIV | BPF_X:
+   {
+   const u8 r0 = bpf2a64[BPF_REG_0];
+
+   /* if (src == 0) return 0 */
+   jmp_offset = 3; /* skip ahead to else path */
+   check_imm19(jmp_offset);
+   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
+   emit(A64_MOVZ(1, r0, 0, 0), ctx);
+   jmp_offset = epilogue_offset(ctx);
+   check_imm26(jmp_offset);
+   emit(A64_B(jmp_offset), ctx);
+   /* else */
  emit(A64_UDIV(is64, dst, dst, src), ctx);
  break;
+   }
  case BPF_ALU | BPF_MOD | BPF_X:
  case BPF_ALU64 | BPF_MOD | BPF_X:



BPF_MOD might need the same fix.


I'll post a fix for this case as well.




Agreed, and we may need add one more test cases in test_bpf module to cover
MOD?


Let me know if you have a test case ready :)


Does the below change look like a valid test?

+   "MOD default X",
+   .u.insns = {
+   /*
+* A = 0x42
+* A = A mod X ; this halt the filter execution 
if X is 0

+* ret 0x42
+*/
+   BPF_STMT(BPF_LD | BPF_IMM, 0x42),
+   BPF_STMT(BPF_ALU | BPF_MOD | BPF_X, 0),
+   BPF_STMT(BPF_RET | BPF_K, 0x42),
+   },
+   CLASSIC | FLAG_NO_DATA,
+   {},
+   { {0x1, 0x0 } },
+   },
+   {
+   "MOD default A",
+   .u.insns = {
+   /*
+* A = A mod 1
+* ret A
+*/
+   BPF_STMT(BPF_ALU | BPF_MOD | BPF_K, 0x1),
+   BPF_STMT(BPF_RET | BPF_A, 0x0),
+   },
+   CLASSIC | FLAG_NO_DATA,
+   {},
+   { {0x1, 0x0 } },
+   },

My test result with it:
test_bpf: #284 MOD default X jited:1 ret 66 != 0 FAIL (1 times)
test_bpf: #285 MOD default A jited:1 102 PASS

If it looks right, I will post a patch to add the test cases.

Thanks,
Yang





Yang



___
linux-arm-kernel mailing list
linux-arm-ker...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel





--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] arm64: bpf: fix div-by-zero case

2015-11-04 Thread Shi, Yang

On 11/3/2015 11:04 PM, Xi Wang wrote:

On Tue, Nov 3, 2015 at 10:56 PM, Zi Shen Lim  wrote:

 case BPF_ALU | BPF_DIV | BPF_X:
 case BPF_ALU64 | BPF_DIV | BPF_X:
+   {
+   const u8 r0 = bpf2a64[BPF_REG_0];
+
+   /* if (src == 0) return 0 */
+   jmp_offset = 3; /* skip ahead to else path */
+   check_imm19(jmp_offset);
+   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
+   emit(A64_MOVZ(1, r0, 0, 0), ctx);
+   jmp_offset = epilogue_offset(ctx);
+   check_imm26(jmp_offset);
+   emit(A64_B(jmp_offset), ctx);
+   /* else */
 emit(A64_UDIV(is64, dst, dst, src), ctx);
 break;
+   }
 case BPF_ALU | BPF_MOD | BPF_X:
 case BPF_ALU64 | BPF_MOD | BPF_X:


BPF_MOD might need the same fix.


Agreed, and we may need add one more test cases in test_bpf module to 
cover MOD?


Yang



___
linux-arm-kernel mailing list
linux-arm-ker...@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] arm64: bpf: fix div-by-zero case

2015-11-04 Thread Shi, Yang

On 11/3/2015 10:56 PM, Zi Shen Lim wrote:

In the case of division by zero in a BPF program:
A = A / X;  (X == 0)
the expected behavior is to terminate with return value 0.

This is confirmed by the test case introduced in commit 86bf1721b226
("test_bpf: add tests checking that JIT/interpreter sets A and X to 0.").

Reported-by: Shi, Yang 


Thanks for coming up with the fix promptly.
s/Shi, Yang/Yang Shi

Tested with the latest 4.3 kernel.
Tested-by: Yang Shi 

Yang


CC: Xi Wang 
CC: Alexei Starovoitov 
CC: Catalin Marinas 
CC: linux-arm-ker...@lists.infradead.org
CC: linux-kernel@vger.kernel.org
Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
Cc:  # 3.18+
Signed-off-by: Zi Shen Lim 
---
  arch/arm64/net/bpf_jit.h  |  3 ++-
  arch/arm64/net/bpf_jit_comp.c | 37 +
  2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index 98a26ce..aee5637 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -1,7 +1,7 @@
  /*
   * BPF JIT compiler for ARM64
   *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
@@ -35,6 +35,7 @@
aarch64_insn_gen_comp_branch_imm(0, offset, Rt, A64_VARIANT(sf), \
AARCH64_INSN_BRANCH_COMP_##type)
  #define A64_CBZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, ZERO)
+#define A64_CBNZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, NONZERO)

  /* Conditional branch (immediate) */
  #define A64_COND_BRANCH(cond, offset) \
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index c047598..9ae6f23 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1,7 +1,7 @@
  /*
   * BPF JIT compiler for ARM64
   *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
@@ -225,6 +225,17 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
u8 jmp_cond;
s32 jmp_offset;

+#define check_imm(bits, imm) do {  \
+   if imm) > 0) && ((imm) >> (bits))) ||  \
+   (((imm) < 0) && (~(imm) >> (bits { \
+   pr_info("[%2d] imm=%d(0x%x) out of range\n",  \
+   i, imm, imm);   \
+   return -EINVAL; \
+   }   \
+} while (0)
+#define check_imm19(imm) check_imm(19, imm)
+#define check_imm26(imm) check_imm(26, imm)
+
switch (code) {
/* dst = src */
case BPF_ALU | BPF_MOV | BPF_X:
@@ -258,8 +269,21 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
break;
case BPF_ALU | BPF_DIV | BPF_X:
case BPF_ALU64 | BPF_DIV | BPF_X:
+   {
+   const u8 r0 = bpf2a64[BPF_REG_0];
+
+   /* if (src == 0) return 0 */
+   jmp_offset = 3; /* skip ahead to else path */
+   check_imm19(jmp_offset);
+   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
+   emit(A64_MOVZ(1, r0, 0, 0), ctx);
+   jmp_offset = epilogue_offset(ctx);
+   check_imm26(jmp_offset);
+   emit(A64_B(jmp_offset), ctx);
+   /* else */
emit(A64_UDIV(is64, dst, dst, src), ctx);
break;
+   }
case BPF_ALU | BPF_MOD | BPF_X:
case BPF_ALU64 | BPF_MOD | BPF_X:
ctx->tmp_used = 1;
@@ -393,17 +417,6 @@ emit_bswap_uxt:
emit(A64_ASR(is64, dst, dst, imm), ctx);
break;

-#define check_imm(bits, imm) do {  \
-   if imm) > 0) && ((imm) >> (bits))) ||  \
-   (((imm) < 0) && (~(imm) >> (bits { \
-   pr_info("[%2d] imm=%d(0x%x) out of range\n",  \
-   i, imm, imm);   \
-   return -EINVAL; \
-   }   \
-} while (0)
-#define check_imm19(imm) check_imm(19, imm)
-#define check_imm26(imm) check_imm(26, imm)
-
/* JUMP off */
case BPF_JMP | BPF_JA:
jmp_offset = bpf2a64_offset(i + off, i, ctx);



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] arm64: bpf: fix div-by-zero case

2015-11-03 Thread Xi Wang
On Tue, Nov 3, 2015 at 10:56 PM, Zi Shen Lim  wrote:
> case BPF_ALU | BPF_DIV | BPF_X:
> case BPF_ALU64 | BPF_DIV | BPF_X:
> +   {
> +   const u8 r0 = bpf2a64[BPF_REG_0];
> +
> +   /* if (src == 0) return 0 */
> +   jmp_offset = 3; /* skip ahead to else path */
> +   check_imm19(jmp_offset);
> +   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
> +   emit(A64_MOVZ(1, r0, 0, 0), ctx);
> +   jmp_offset = epilogue_offset(ctx);
> +   check_imm26(jmp_offset);
> +   emit(A64_B(jmp_offset), ctx);
> +   /* else */
> emit(A64_UDIV(is64, dst, dst, src), ctx);
> break;
> +   }
> case BPF_ALU | BPF_MOD | BPF_X:
> case BPF_ALU64 | BPF_MOD | BPF_X:

BPF_MOD might need the same fix.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] arm64: bpf: fix div-by-zero case

2015-11-03 Thread Zi Shen Lim
In the case of division by zero in a BPF program:
A = A / X;  (X == 0)
the expected behavior is to terminate with return value 0.

This is confirmed by the test case introduced in commit 86bf1721b226
("test_bpf: add tests checking that JIT/interpreter sets A and X to 0.").

Reported-by: Shi, Yang 
CC: Xi Wang 
CC: Alexei Starovoitov 
CC: Catalin Marinas 
CC: linux-arm-ker...@lists.infradead.org
CC: linux-kernel@vger.kernel.org
Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
Cc:  # 3.18+
Signed-off-by: Zi Shen Lim 
---
 arch/arm64/net/bpf_jit.h  |  3 ++-
 arch/arm64/net/bpf_jit_comp.c | 37 +
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h
index 98a26ce..aee5637 100644
--- a/arch/arm64/net/bpf_jit.h
+++ b/arch/arm64/net/bpf_jit.h
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -35,6 +35,7 @@
aarch64_insn_gen_comp_branch_imm(0, offset, Rt, A64_VARIANT(sf), \
AARCH64_INSN_BRANCH_COMP_##type)
 #define A64_CBZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, ZERO)
+#define A64_CBNZ(sf, Rt, imm19) A64_COMP_BRANCH(sf, Rt, (imm19) << 2, NONZERO)
 
 /* Conditional branch (immediate) */
 #define A64_COND_BRANCH(cond, offset) \
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index c047598..9ae6f23 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1,7 +1,7 @@
 /*
  * BPF JIT compiler for ARM64
  *
- * Copyright (C) 2014 Zi Shen Lim 
+ * Copyright (C) 2014-2015 Zi Shen Lim 
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -225,6 +225,17 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
u8 jmp_cond;
s32 jmp_offset;
 
+#define check_imm(bits, imm) do {  \
+   if imm) > 0) && ((imm) >> (bits))) ||   \
+   (((imm) < 0) && (~(imm) >> (bits {  \
+   pr_info("[%2d] imm=%d(0x%x) out of range\n",\
+   i, imm, imm);   \
+   return -EINVAL; \
+   }   \
+} while (0)
+#define check_imm19(imm) check_imm(19, imm)
+#define check_imm26(imm) check_imm(26, imm)
+
switch (code) {
/* dst = src */
case BPF_ALU | BPF_MOV | BPF_X:
@@ -258,8 +269,21 @@ static int build_insn(const struct bpf_insn *insn, struct 
jit_ctx *ctx)
break;
case BPF_ALU | BPF_DIV | BPF_X:
case BPF_ALU64 | BPF_DIV | BPF_X:
+   {
+   const u8 r0 = bpf2a64[BPF_REG_0];
+
+   /* if (src == 0) return 0 */
+   jmp_offset = 3; /* skip ahead to else path */
+   check_imm19(jmp_offset);
+   emit(A64_CBNZ(is64, src, jmp_offset), ctx);
+   emit(A64_MOVZ(1, r0, 0, 0), ctx);
+   jmp_offset = epilogue_offset(ctx);
+   check_imm26(jmp_offset);
+   emit(A64_B(jmp_offset), ctx);
+   /* else */
emit(A64_UDIV(is64, dst, dst, src), ctx);
break;
+   }
case BPF_ALU | BPF_MOD | BPF_X:
case BPF_ALU64 | BPF_MOD | BPF_X:
ctx->tmp_used = 1;
@@ -393,17 +417,6 @@ emit_bswap_uxt:
emit(A64_ASR(is64, dst, dst, imm), ctx);
break;
 
-#define check_imm(bits, imm) do {  \
-   if imm) > 0) && ((imm) >> (bits))) ||   \
-   (((imm) < 0) && (~(imm) >> (bits {  \
-   pr_info("[%2d] imm=%d(0x%x) out of range\n",\
-   i, imm, imm);   \
-   return -EINVAL; \
-   }   \
-} while (0)
-#define check_imm19(imm) check_imm(19, imm)
-#define check_imm26(imm) check_imm(26, imm)
-
/* JUMP off */
case BPF_JMP | BPF_JA:
jmp_offset = bpf2a64_offset(i + off, i, ctx);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/