| From 1e9d54fb995b9fb49b723b0ebf79782fb15071f7 Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <eric.dumazet@gmail.com> |
| Date: Sun, 18 Mar 2012 02:40:48 +0000 |
| Subject: net: bpf_jit: fix BPF_S_LDX_B_MSH compilation |
| |
| |
| From: Eric Dumazet <eric.dumazet@gmail.com> |
| |
| [ Upstream commit dc72d99dabb870ca5bd6d9fff674be853bb4a88d ] |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/net/bpf_jit_comp.c | 14 +++++--------- |
| 1 file changed, 5 insertions(+), 9 deletions(-) |
| |
| --- 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 *f |
| case BPF_S_LD_W_ABS: |
| func = sk_load_word; |
| common_load: seen |= SEEN_DATAREF; |
| - if ((int)K < 0) |
| + if ((int)K < 0) { |
| + /* Abort the JIT because __load_pointer() is needed. */ |
| goto out; |
| + } |
| t_offset = func - (image + addrs[i]); |
| EMIT1_off32(0xbe, K); /* mov imm32,%esi */ |
| EMIT1_off32(0xe8, t_offset); /* call */ |
| @@ -489,14 +491,8 @@ common_load: seen |= SEEN_DATAREF; |
| goto common_load; |
| case BPF_S_LDX_B_MSH: |
| if ((int)K < 0) { |
| - if (pc_ret0 > 0) { |
| - /* addrs[pc_ret0 - 1] is the start address */ |
| - EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]); |
| - break; |
| - } |
| - CLEAR_A(); |
| - EMIT_JMP(cleanup_addr - addrs[i]); |
| - break; |
| + /* Abort the JIT because __load_pointer() is needed. */ |
| + goto out; |
| } |
| seen |= SEEN_DATAREF | SEEN_XREG; |
| t_offset = sk_load_byte_msh - (image + addrs[i]); |