aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2014-01-15 09:50:07 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-15 20:02:08 -0500
commitaee636c4809fa54848ff07a899b326eb1f9987a2 (patch)
tree8f0c327f82dd7d5056dc487064f05f3f804f2fea
parentba42fad0964a41f0830e80c1b6be49c1e6bfcc01 (diff)
bpf: do not use reciprocal divide
At first Jakub Zawadzki noticed that some divisions by reciprocal_divide were not correct. (off by one in some cases) http://www.wireshark.org/~darkjames/reciprocal-buggy.c He could also show this with BPF: http://www.wireshark.org/~darkjames/set-and-dump-filter-k-bug.c The reciprocal divide in linux kernel is not generic enough, lets remove its use in BPF, as it is not worth the pain with current cpus. Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Jakub Zawadzki <darkjames-ws@darkjames.pl> Cc: Mircea Gherzan <mgherzan@gmail.com> Cc: Daniel Borkmann <dxchgb@gmail.com> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org> Cc: Matt Evans <matt@ozlabs.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/arm/net/bpf_jit_32.c6
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c7
-rw-r--r--arch/s390/net/bpf_jit_comp.c17
-rw-r--r--arch/sparc/net/bpf_jit_comp.c17
-rw-r--r--arch/x86/net/bpf_jit_comp.c14
-rw-r--r--net/core/filter.c30
6 files changed, 45 insertions, 46 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 9ed155ad0f97..271b5e971568 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -641,10 +641,10 @@ load_ind:
641 emit(ARM_MUL(r_A, r_A, r_X), ctx); 641 emit(ARM_MUL(r_A, r_A, r_X), ctx);
642 break; 642 break;
643 case BPF_S_ALU_DIV_K: 643 case BPF_S_ALU_DIV_K:
644 /* current k == reciprocal_value(userspace k) */ 644 if (k == 1)
645 break;
645 emit_mov_i(r_scratch, k, ctx); 646 emit_mov_i(r_scratch, k, ctx);
646 /* A = top 32 bits of the product */ 647 emit_udiv(r_A, r_A, r_scratch, ctx);
647 emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
648 break; 648 break;
649 case BPF_S_ALU_DIV_X: 649 case BPF_S_ALU_DIV_X:
650 update_on_xread(ctx); 650 update_on_xread(ctx);
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index ac3c2a10dafd..555034f8505e 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -223,10 +223,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
223 } 223 }
224 PPC_DIVWU(r_A, r_A, r_X); 224 PPC_DIVWU(r_A, r_A, r_X);
225 break; 225 break;
226 case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ 226 case BPF_S_ALU_DIV_K: /* A /= K */
227 if (K == 1)
228 break;
227 PPC_LI32(r_scratch1, K); 229 PPC_LI32(r_scratch1, K);
228 /* Top 32 bits of 64bit result -> A */ 230 PPC_DIVWU(r_A, r_A, r_scratch1);
229 PPC_MULHWU(r_A, r_A, r_scratch1);
230 break; 231 break;
231 case BPF_S_ALU_AND_X: 232 case BPF_S_ALU_AND_X:
232 ctx->seen |= SEEN_XREG; 233 ctx->seen |= SEEN_XREG;
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 16871da37371..fc0fa77728e1 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -371,11 +371,13 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
371 /* dr %r4,%r12 */ 371 /* dr %r4,%r12 */
372 EMIT2(0x1d4c); 372 EMIT2(0x1d4c);
373 break; 373 break;
374 case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */ 374 case BPF_S_ALU_DIV_K: /* A /= K */
375 /* m %r4,<d(K)>(%r13) */ 375 if (K == 1)
376 EMIT4_DISP(0x5c40d000, EMIT_CONST(K)); 376 break;
377 /* lr %r5,%r4 */ 377 /* lhi %r4,0 */
378 EMIT2(0x1854); 378 EMIT4(0xa7480000);
379 /* d %r4,<d(K)>(%r13) */
380 EMIT4_DISP(0x5d40d000, EMIT_CONST(K));
379 break; 381 break;
380 case BPF_S_ALU_MOD_X: /* A %= X */ 382 case BPF_S_ALU_MOD_X: /* A %= X */
381 jit->seen |= SEEN_XREG | SEEN_RET0; 383 jit->seen |= SEEN_XREG | SEEN_RET0;
@@ -391,6 +393,11 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
391 EMIT2(0x1854); 393 EMIT2(0x1854);
392 break; 394 break;
393 case BPF_S_ALU_MOD_K: /* A %= K */ 395 case BPF_S_ALU_MOD_K: /* A %= K */
396 if (K == 1) {
397 /* lhi %r5,0 */
398 EMIT4(0xa7580000);
399 break;
400 }
394 /* lhi %r4,0 */ 401 /* lhi %r4,0 */
395 EMIT4(0xa7480000); 402 EMIT4(0xa7480000);
396 /* d %r4,<d(K)>(%r13) */ 403 /* d %r4,<d(K)>(%r13) */
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 218b6b23c378..01fe9946d388 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -497,9 +497,20 @@ void bpf_jit_compile(struct sk_filter *fp)
497 case BPF_S_ALU_MUL_K: /* A *= K */ 497 case BPF_S_ALU_MUL_K: /* A *= K */
498 emit_alu_K(MUL, K); 498 emit_alu_K(MUL, K);
499 break; 499 break;
500 case BPF_S_ALU_DIV_K: /* A /= K */ 500 case BPF_S_ALU_DIV_K: /* A /= K with K != 0*/
501 emit_alu_K(MUL, K); 501 if (K == 1)
502 emit_read_y(r_A); 502 break;
503 emit_write_y(G0);
504#ifdef CONFIG_SPARC32
505 /* The Sparc v8 architecture requires
506 * three instructions between a %y
507 * register write and the first use.
508 */
509 emit_nop();
510 emit_nop();
511 emit_nop();
512#endif
513 emit_alu_K(DIV, K);
503 break; 514 break;
504 case BPF_S_ALU_DIV_X: /* A /= X; */ 515 case BPF_S_ALU_DIV_X: /* A /= X; */
505 emit_cmpi(r_X, 0); 516 emit_cmpi(r_X, 0);
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 26328e800869..4ed75dd81d05 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -359,15 +359,21 @@ void bpf_jit_compile(struct sk_filter *fp)
359 EMIT2(0x89, 0xd0); /* mov %edx,%eax */ 359 EMIT2(0x89, 0xd0); /* mov %edx,%eax */
360 break; 360 break;
361 case BPF_S_ALU_MOD_K: /* A %= K; */ 361 case BPF_S_ALU_MOD_K: /* A %= K; */
362 if (K == 1) {
363 CLEAR_A();
364 break;
365 }
362 EMIT2(0x31, 0xd2); /* xor %edx,%edx */ 366 EMIT2(0x31, 0xd2); /* xor %edx,%edx */
363 EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ 367 EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
364 EMIT2(0xf7, 0xf1); /* div %ecx */ 368 EMIT2(0xf7, 0xf1); /* div %ecx */
365 EMIT2(0x89, 0xd0); /* mov %edx,%eax */ 369 EMIT2(0x89, 0xd0); /* mov %edx,%eax */
366 break; 370 break;
367 case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ 371 case BPF_S_ALU_DIV_K: /* A /= K */
368 EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */ 372 if (K == 1)
369 EMIT(K, 4); 373 break;
370 EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ 374 EMIT2(0x31, 0xd2); /* xor %edx,%edx */
375 EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */
376 EMIT2(0xf7, 0xf1); /* div %ecx */
371 break; 377 break;
372 case BPF_S_ALU_AND_X: 378 case BPF_S_ALU_AND_X:
373 seen |= SEEN_XREG; 379 seen |= SEEN_XREG;
diff --git a/net/core/filter.c b/net/core/filter.c
index 01b780856db2..ad30d626a5bd 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -36,7 +36,6 @@
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37#include <asm/unaligned.h> 37#include <asm/unaligned.h>
38#include <linux/filter.h> 38#include <linux/filter.h>
39#include <linux/reciprocal_div.h>
40#include <linux/ratelimit.h> 39#include <linux/ratelimit.h>
41#include <linux/seccomp.h> 40#include <linux/seccomp.h>
42#include <linux/if_vlan.h> 41#include <linux/if_vlan.h>
@@ -166,7 +165,7 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
166 A /= X; 165 A /= X;
167 continue; 166 continue;
168 case BPF_S_ALU_DIV_K: 167 case BPF_S_ALU_DIV_K:
169 A = reciprocal_divide(A, K); 168 A /= K;
170 continue; 169 continue;
171 case BPF_S_ALU_MOD_X: 170 case BPF_S_ALU_MOD_X:
172 if (X == 0) 171 if (X == 0)
@@ -553,11 +552,6 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
553 /* Some instructions need special checks */ 552 /* Some instructions need special checks */
554 switch (code) { 553 switch (code) {
555 case BPF_S_ALU_DIV_K: 554 case BPF_S_ALU_DIV_K:
556 /* check for division by zero */
557 if (ftest->k == 0)
558 return -EINVAL;
559 ftest->k = reciprocal_value(ftest->k);
560 break;
561 case BPF_S_ALU_MOD_K: 555 case BPF_S_ALU_MOD_K:
562 /* check for division by zero */ 556 /* check for division by zero */
563 if (ftest->k == 0) 557 if (ftest->k == 0)
@@ -853,27 +847,7 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
853 to->code = decodes[code]; 847 to->code = decodes[code];
854 to->jt = filt->jt; 848 to->jt = filt->jt;
855 to->jf = filt->jf; 849 to->jf = filt->jf;
856 850 to->k = filt->k;
857 if (code == BPF_S_ALU_DIV_K) {
858 /*
859 * When loaded this rule user gave us X, which was
860 * translated into R = r(X). Now we calculate the
861 * RR = r(R) and report it back. If next time this
862 * value is loaded and RRR = r(RR) is calculated
863 * then the R == RRR will be true.
864 *
865 * One exception. X == 1 translates into R == 0 and
866 * we can't calculate RR out of it with r().
867 */
868
869 if (filt->k == 0)
870 to->k = 1;
871 else
872 to->k = reciprocal_value(filt->k);
873
874 BUG_ON(reciprocal_value(to->k) != filt->k);
875 } else
876 to->k = filt->k;
877} 851}
878 852
879int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len) 853int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len)