diff options
author | Xi Wang <xi.wang@gmail.com> | 2015-06-25 21:39:15 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2015-06-26 09:15:39 -0400 |
commit | d63903bbc30c7ccad040851dfdb4da12d9a17bcf (patch) | |
tree | 6ddc09f1a2289e833b51b373049649f416a586bf | |
parent | 8eee539ddea09bccae2426f09b0ba6a18b72b691 (diff) |
arm64: bpf: fix endianness conversion bugs
Upper bits should be zeroed in endianness conversion:
- even when there's no need to change endianness (i.e., BPF_FROM_BE
on big endian or BPF_FROM_LE on little endian);
- after rev16.
This patch fixes such bugs by emitting extra instructions to clear
upper bits.
Cc: Zi Shen Lim <zlim.lnx@gmail.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Fixes: e54bcde3d69d ("arm64: eBPF JIT compiler")
Cc: <stable@vger.kernel.org> # 3.18+
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r-- | arch/arm64/net/bpf_jit.h | 4 | ||||
-rw-r--r-- | arch/arm64/net/bpf_jit_comp.c | 22 |
2 files changed, 24 insertions, 2 deletions
diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h index de0a81a539a0..98a26ce82d26 100644 --- a/arch/arm64/net/bpf_jit.h +++ b/arch/arm64/net/bpf_jit.h | |||
@@ -110,6 +110,10 @@ | |||
110 | /* Rd = Rn >> shift; signed */ | 110 | /* Rd = Rn >> shift; signed */ |
111 | #define A64_ASR(sf, Rd, Rn, shift) A64_SBFM(sf, Rd, Rn, shift, (sf) ? 63 : 31) | 111 | #define A64_ASR(sf, Rd, Rn, shift) A64_SBFM(sf, Rd, Rn, shift, (sf) ? 63 : 31) |
112 | 112 | ||
113 | /* Zero extend */ | ||
114 | #define A64_UXTH(sf, Rd, Rn) A64_UBFM(sf, Rd, Rn, 0, 15) | ||
115 | #define A64_UXTW(sf, Rd, Rn) A64_UBFM(sf, Rd, Rn, 0, 31) | ||
116 | |||
113 | /* Move wide (immediate) */ | 117 | /* Move wide (immediate) */ |
114 | #define A64_MOVEW(sf, Rd, imm16, shift, type) \ | 118 | #define A64_MOVEW(sf, Rd, imm16, shift, type) \ |
115 | aarch64_insn_gen_movewide(Rd, imm16, shift, \ | 119 | aarch64_insn_gen_movewide(Rd, imm16, shift, \ |
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index c81ddd4ff7f7..c047598b09e0 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c | |||
@@ -289,23 +289,41 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) | |||
289 | case BPF_ALU | BPF_END | BPF_FROM_BE: | 289 | case BPF_ALU | BPF_END | BPF_FROM_BE: |
290 | #ifdef CONFIG_CPU_BIG_ENDIAN | 290 | #ifdef CONFIG_CPU_BIG_ENDIAN |
291 | if (BPF_SRC(code) == BPF_FROM_BE) | 291 | if (BPF_SRC(code) == BPF_FROM_BE) |
292 | break; | 292 | goto emit_bswap_uxt; |
293 | #else /* !CONFIG_CPU_BIG_ENDIAN */ | 293 | #else /* !CONFIG_CPU_BIG_ENDIAN */ |
294 | if (BPF_SRC(code) == BPF_FROM_LE) | 294 | if (BPF_SRC(code) == BPF_FROM_LE) |
295 | break; | 295 | goto emit_bswap_uxt; |
296 | #endif | 296 | #endif |
297 | switch (imm) { | 297 | switch (imm) { |
298 | case 16: | 298 | case 16: |
299 | emit(A64_REV16(is64, dst, dst), ctx); | 299 | emit(A64_REV16(is64, dst, dst), ctx); |
300 | /* zero-extend 16 bits into 64 bits */ | ||
301 | emit(A64_UXTH(is64, dst, dst), ctx); | ||
300 | break; | 302 | break; |
301 | case 32: | 303 | case 32: |
302 | emit(A64_REV32(is64, dst, dst), ctx); | 304 | emit(A64_REV32(is64, dst, dst), ctx); |
305 | /* upper 32 bits already cleared */ | ||
303 | break; | 306 | break; |
304 | case 64: | 307 | case 64: |
305 | emit(A64_REV64(dst, dst), ctx); | 308 | emit(A64_REV64(dst, dst), ctx); |
306 | break; | 309 | break; |
307 | } | 310 | } |
308 | break; | 311 | break; |
312 | emit_bswap_uxt: | ||
313 | switch (imm) { | ||
314 | case 16: | ||
315 | /* zero-extend 16 bits into 64 bits */ | ||
316 | emit(A64_UXTH(is64, dst, dst), ctx); | ||
317 | break; | ||
318 | case 32: | ||
319 | /* zero-extend 32 bits into 64 bits */ | ||
320 | emit(A64_UXTW(is64, dst, dst), ctx); | ||
321 | break; | ||
322 | case 64: | ||
323 | /* nop */ | ||
324 | break; | ||
325 | } | ||
326 | break; | ||
309 | /* dst = imm */ | 327 | /* dst = imm */ |
310 | case BPF_ALU | BPF_MOV | BPF_K: | 328 | case BPF_ALU | BPF_MOV | BPF_K: |
311 | case BPF_ALU64 | BPF_MOV | BPF_K: | 329 | case BPF_ALU64 | BPF_MOV | BPF_K: |