Skip to content

Commit d63903b

Browse files
xiwctmarinas
authored andcommitted
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: e54bcde ("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>
1 parent 8eee539 commit d63903b

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

arch/arm64/net/bpf_jit.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@
110110
/* Rd = Rn >> shift; signed */
111111
#define A64_ASR(sf, Rd, Rn, shift) A64_SBFM(sf, Rd, Rn, shift, (sf) ? 63 : 31)
112112

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+
113117
/* Move wide (immediate) */
114118
#define A64_MOVEW(sf, Rd, imm16, shift, type) \
115119
aarch64_insn_gen_movewide(Rd, imm16, shift, \

arch/arm64/net/bpf_jit_comp.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,23 +289,41 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
289289
case BPF_ALU | BPF_END | BPF_FROM_BE:
290290
#ifdef CONFIG_CPU_BIG_ENDIAN
291291
if (BPF_SRC(code) == BPF_FROM_BE)
292-
break;
292+
goto emit_bswap_uxt;
293293
#else /* !CONFIG_CPU_BIG_ENDIAN */
294294
if (BPF_SRC(code) == BPF_FROM_LE)
295-
break;
295+
goto emit_bswap_uxt;
296296
#endif
297297
switch (imm) {
298298
case 16:
299299
emit(A64_REV16(is64, dst, dst), ctx);
300+
/* zero-extend 16 bits into 64 bits */
301+
emit(A64_UXTH(is64, dst, dst), ctx);
300302
break;
301303
case 32:
302304
emit(A64_REV32(is64, dst, dst), ctx);
305+
/* upper 32 bits already cleared */
303306
break;
304307
case 64:
305308
emit(A64_REV64(dst, dst), ctx);
306309
break;
307310
}
308311
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;
309327
/* dst = imm */
310328
case BPF_ALU | BPF_MOV | BPF_K:
311329
case BPF_ALU64 | BPF_MOV | BPF_K:

0 commit comments

Comments
 (0)