Commit 35607b02dbef304fa5037236a3b43c1d8ab2aa52

Authored by Alexei Starovoitov
Committed by David S. Miller
1 parent 543a2dff5e

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>

Showing 2 changed files with 4 additions and 1 deletions Side-by-side Diff

arch/sparc/net/bpf_jit_asm.S
... ... @@ -6,10 +6,12 @@
6 6 #define SAVE_SZ 176
7 7 #define SCRATCH_OFF STACK_BIAS + 128
8 8 #define BE_PTR(label) be,pn %xcc, label
  9 +#define SIGN_EXTEND(reg) sra reg, 0, reg
9 10 #else
10 11 #define SAVE_SZ 96
11 12 #define SCRATCH_OFF 72
12 13 #define BE_PTR(label) be label
  14 +#define SIGN_EXTEND(reg)
13 15 #endif
14 16  
15 17 #define SKF_MAX_NEG_OFF (-0x200000) /* SKF_LL_OFF from filter.h */
... ... @@ -135,6 +137,7 @@
135 137 save %sp, -SAVE_SZ, %sp; \
136 138 mov %i0, %o0; \
137 139 mov r_OFF, %o1; \
  140 + SIGN_EXTEND(%o1); \
138 141 call bpf_internal_load_pointer_neg_helper; \
139 142 mov (LEN), %o2; \
140 143 mov %o0, r_TMP; \
arch/sparc/net/bpf_jit_comp.c
... ... @@ -184,7 +184,7 @@
184 184 */
185 185 #define emit_alu_K(OPCODE, K) \
186 186 do { \
187   - if (K) { \
  187 + if (K || OPCODE == AND || OPCODE == MUL) { \
188 188 unsigned int _insn = OPCODE; \
189 189 _insn |= RS1(r_A) | RD(r_A); \
190 190 if (is_simm13(K)) { \