Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14e589ff authored by Zi Shen Lim's avatar Zi Shen Lim Committed by Catalin Marinas
Browse files

arm64: bpf: fix mod-by-zero case

Turns out in the case of modulo by zero in a BPF program:
	A = A % X;  (X == 0)
the expected behavior is to terminate with return value 0.

The bug in JIT is exposed by a new test case [1].

[1] https://lkml.org/lkml/2015/11/4/499



Signed-off-by: default avatarZi Shen Lim <zlim.lnx@gmail.com>
Reported-by: default avatarYang Shi <yang.shi@linaro.org>
Reported-by: default avatarXi Wang <xi.wang@gmail.com>
CC: Alexei Starovoitov <ast@plumgrid.com>
Fixes: e54bcde3 ("arm64: eBPF JIT compiler")
Cc: <stable@vger.kernel.org> # 3.18+
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 251599e1
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -269,6 +269,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
		break;
	case BPF_ALU | BPF_DIV | BPF_X:
	case BPF_ALU64 | BPF_DIV | BPF_X:
	case BPF_ALU | BPF_MOD | BPF_X:
	case BPF_ALU64 | BPF_MOD | BPF_X:
	{
		const u8 r0 = bpf2a64[BPF_REG_0];

@@ -281,16 +283,19 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
		check_imm26(jmp_offset);
		emit(A64_B(jmp_offset), ctx);
		/* else */
		switch (BPF_OP(code)) {
		case BPF_DIV:
			emit(A64_UDIV(is64, dst, dst, src), ctx);
			break;
	}
	case BPF_ALU | BPF_MOD | BPF_X:
	case BPF_ALU64 | BPF_MOD | BPF_X:
		case BPF_MOD:
			ctx->tmp_used = 1;
			emit(A64_UDIV(is64, tmp, dst, src), ctx);
			emit(A64_MUL(is64, tmp, tmp, src), ctx);
			emit(A64_SUB(is64, dst, dst, tmp), ctx);
			break;
		}
		break;
	}
	case BPF_ALU | BPF_LSH | BPF_X:
	case BPF_ALU64 | BPF_LSH | BPF_X:
		emit(A64_LSLV(is64, dst, dst, src), ctx);