diff options
author | Eric Dumazet <edumazet@google.com> | 2014-01-15 09:50:07 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-06 14:08:16 -0500 |
commit | cd7361dc9fa60c35d011d674d48eababcc3eb767 (patch) | |
tree | 51c5b5cdfabf829671688e9df26623fa64feb5ea /arch/s390 | |
parent | 8c035b62e21a2d26c1a5181ee0d27a76c8996be8 (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.c | 17 |
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) */ |