diff options
author | Alexei Starovoitov <ast@plumgrid.com> | 2014-09-23 13:50:10 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-24 15:04:07 -0400 |
commit | 35607b02dbef304fa5037236a3b43c1d8ab2aa52 (patch) | |
tree | c219ac28ef9d9691122fb445be7a6dfbcf120a3d /arch/sparc/net | |
parent | Merge tag 'master-2014-09-23' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless (diff) | |
download | wireguard-linux-35607b02dbef304fa5037236a3b43c1d8ab2aa52.tar.xz wireguard-linux-35607b02dbef304fa5037236a3b43c1d8ab2aa52.zip |
sparc: bpf_jit: fix loads from negative offsets
- fix BPF_LD|ABS|IND from negative offsets:
make sure to sign extend lower 32 bits in 64-bit register
before calling C helpers from JITed code, otherwise 'int k'
argument of bpf_internal_load_pointer_neg_helper() function
will be added as large unsigned integer, causing packet size
check to trigger and abort the program.
It's worth noting that JITed code for 'A = A op K' will affect
upper 32 bits differently depending whether K is simm13 or not.
Since small constants are sign extended, whereas large constants
are stored in temp register and zero extended.
That is ok and we don't have to pay a penalty of sign extension
for every sethi, since all classic BPF instructions have 32-bit
semantics and we only need to set correct upper bits when
transitioning from JITed code into C.
- though instructions 'A &= 0' and 'A *= 0' are odd, JIT compiler
should not optimize them out
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/net')
-rw-r--r-- | arch/sparc/net/bpf_jit_asm.S | 3 | ||||
-rw-r--r-- | arch/sparc/net/bpf_jit_comp.c | 2 |
2 files changed, 4 insertions, 1 deletions
diff --git a/arch/sparc/net/bpf_jit_asm.S b/arch/sparc/net/bpf_jit_asm.S index 9d016c7017f7..8c83f4b8eb15 100644 --- a/arch/sparc/net/bpf_jit_asm.S +++ b/arch/sparc/net/bpf_jit_asm.S @@ -6,10 +6,12 @@ #define SAVE_SZ 176 #define SCRATCH_OFF STACK_BIAS + 128 #define BE_PTR(label) be,pn %xcc, label +#define SIGN_EXTEND(reg) sra reg, 0, reg #else #define SAVE_SZ 96 #define SCRATCH_OFF 72 #define BE_PTR(label) be label +#define SIGN_EXTEND(reg) #endif #define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */ @@ -135,6 +137,7 @@ bpf_slow_path_byte_msh: save %sp, -SAVE_SZ, %sp; \ mov %i0, %o0; \ mov r_OFF, %o1; \ + SIGN_EXTEND(%o1); \ call bpf_internal_load_pointer_neg_helper; \ mov (LEN), %o2; \ mov %o0, r_TMP; \ diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index 51ae87b483e0..ece4af0575e9 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c @@ -184,7 +184,7 @@ do { \ */ #define emit_alu_K(OPCODE, K) \ do { \ - if (K) { \ + if (K || OPCODE == AND || OPCODE == MUL) { \ unsigned int _insn = OPCODE; \ _insn |= RS1(r_A) | RD(r_A); \ if (is_simm13(K)) { \ |