diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2012-03-17 22:40:48 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-03-19 17:41:44 -0400 |
commit | dc72d99dabb870ca5bd6d9fff674be853bb4a88d (patch) | |
tree | 20fbc871a5f19e4e243425d78c5a2e50cbb66912 /arch/x86/net | |
parent | 3af79302b400e05b45e377993a8870869500466b (diff) |
net: bpf_jit: fix BPF_S_LDX_B_MSH compilation
Matt Evans spotted that x86 bpf_jit was incorrectly handling negative
constant offsets in BPF_S_LDX_B_MSH instruction.
We need to abort JIT compilation like we do in common_load so that
filter uses the interpreter code and can call __load_pointer()
Reference: http://lists.openwall.net/netdev/2011/07/19/11
Thanks to Indan Zupancic to bring back this issue.
Reported-by: Matt Evans <matt@ozlabs.org>
Reported-by: Indan Zupancic <indan@nul.nu>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/x86/net')
-rw-r--r-- | arch/x86/net/bpf_jit_comp.c | 14 |
1 files changed, 5 insertions, 9 deletions
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 7c1b765ecc59..5671752f8d9c 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -475,8 +475,10 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
475 | case BPF_S_LD_W_ABS: | 475 | case BPF_S_LD_W_ABS: |
476 | func = sk_load_word; | 476 | func = sk_load_word; |
477 | common_load: seen |= SEEN_DATAREF; | 477 | common_load: seen |= SEEN_DATAREF; |
478 | if ((int)K < 0) | 478 | if ((int)K < 0) { |
479 | /* Abort the JIT because __load_pointer() is needed. */ | ||
479 | goto out; | 480 | goto out; |
481 | } | ||
480 | t_offset = func - (image + addrs[i]); | 482 | t_offset = func - (image + addrs[i]); |
481 | EMIT1_off32(0xbe, K); /* mov imm32,%esi */ | 483 | EMIT1_off32(0xbe, K); /* mov imm32,%esi */ |
482 | EMIT1_off32(0xe8, t_offset); /* call */ | 484 | EMIT1_off32(0xe8, t_offset); /* call */ |
@@ -489,14 +491,8 @@ common_load: seen |= SEEN_DATAREF; | |||
489 | goto common_load; | 491 | goto common_load; |
490 | case BPF_S_LDX_B_MSH: | 492 | case BPF_S_LDX_B_MSH: |
491 | if ((int)K < 0) { | 493 | if ((int)K < 0) { |
492 | if (pc_ret0 > 0) { | 494 | /* Abort the JIT because __load_pointer() is needed. */ |
493 | /* addrs[pc_ret0 - 1] is the start address */ | 495 | goto out; |
494 | EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]); | ||
495 | break; | ||
496 | } | ||
497 | CLEAR_A(); | ||
498 | EMIT_JMP(cleanup_addr - addrs[i]); | ||
499 | break; | ||
500 | } | 496 | } |
501 | seen |= SEEN_DATAREF | SEEN_XREG; | 497 | seen |= SEEN_DATAREF | SEEN_XREG; |
502 | t_offset = sk_load_byte_msh - (image + addrs[i]); | 498 | t_offset = sk_load_byte_msh - (image + addrs[i]); |