aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2014-01-15 09:50:07 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-06 14:08:16 -0500
commitcd7361dc9fa60c35d011d674d48eababcc3eb767 (patch)
tree51c5b5cdfabf829671688e9df26623fa64feb5ea /arch/s390
parent8c035b62e21a2d26c1a5181ee0d27a76c8996be8 (diff)
bpf: do not use reciprocal divide
[ Upstream commit aee636c4809fa54848ff07a899b326eb1f9987a2 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/net/bpf_jit_comp.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 82f165f8078c..b7792d499da6 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -338,11 +338,13 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
338 /* dr %r4,%r12 */ 338 /* dr %r4,%r12 */
339 EMIT2(0x1d4c); 339 EMIT2(0x1d4c);
340 break; 340 break;
341 case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */ 341 case BPF_S_ALU_DIV_K: /* A /= K */
342 /* m %r4,<d(K)>(%r13) */ 342 if (K == 1)
343 EMIT4_DISP(0x5c40d000, EMIT_CONST(K)); 343 break;
344 /* lr %r5,%r4 */ 344 /* lhi %r4,0 */
345 EMIT2(0x1854); 345 EMIT4(0xa7480000);
346 /* d %r4,<d(K)>(%r13) */
347 EMIT4_DISP(0x5d40d000, EMIT_CONST(K));
346 break; 348 break;
347 case BPF_S_ALU_MOD_X: /* A %= X */ 349 case BPF_S_ALU_MOD_X: /* A %= X */
348 jit->seen |= SEEN_XREG | SEEN_RET0; 350 jit->seen |= SEEN_XREG | SEEN_RET0;
@@ -358,6 +360,11 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
358 EMIT2(0x1854); 360 EMIT2(0x1854);
359 break; 361 break;
360 case BPF_S_ALU_MOD_K: /* A %= K */ 362 case BPF_S_ALU_MOD_K: /* A %= K */
363 if (K == 1) {
364 /* lhi %r5,0 */
365 EMIT4(0xa7580000);
366 break;
367 }
361 /* lhi %r4,0 */ 368 /* lhi %r4,0 */
362 EMIT4(0xa7480000); 369 EMIT4(0xa7480000);
363 /* d %r4,<d(K)>(%r13) */ 370 /* d %r4,<d(K)>(%r13) */