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: e54bcde3d6
("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>
This commit is contained in:
@@ -289,23 +289,41 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
|
||||
case BPF_ALU | BPF_END | BPF_FROM_BE:
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
if (BPF_SRC(code) == BPF_FROM_BE)
|
||||
break;
|
||||
goto emit_bswap_uxt;
|
||||
#else /* !CONFIG_CPU_BIG_ENDIAN */
|
||||
if (BPF_SRC(code) == BPF_FROM_LE)
|
||||
break;
|
||||
goto emit_bswap_uxt;
|
||||
#endif
|
||||
switch (imm) {
|
||||
case 16:
|
||||
emit(A64_REV16(is64, dst, dst), ctx);
|
||||
/* zero-extend 16 bits into 64 bits */
|
||||
emit(A64_UXTH(is64, dst, dst), ctx);
|
||||
break;
|
||||
case 32:
|
||||
emit(A64_REV32(is64, dst, dst), ctx);
|
||||
/* upper 32 bits already cleared */
|
||||
break;
|
||||
case 64:
|
||||
emit(A64_REV64(dst, dst), ctx);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
emit_bswap_uxt:
|
||||
switch (imm) {
|
||||
case 16:
|
||||
/* zero-extend 16 bits into 64 bits */
|
||||
emit(A64_UXTH(is64, dst, dst), ctx);
|
||||
break;
|
||||
case 32:
|
||||
/* zero-extend 32 bits into 64 bits */
|
||||
emit(A64_UXTW(is64, dst, dst), ctx);
|
||||
break;
|
||||
case 64:
|
||||
/* nop */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* dst = imm */
|
||||
case BPF_ALU | BPF_MOV | BPF_K:
|
||||
case BPF_ALU64 | BPF_MOV | BPF_K:
|
||||
|
Reference in New Issue
Block a user