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

Commit f324cda6 authored by Zi Shen Lim's avatar Zi Shen Lim Committed by Greg Kroah-Hartman
Browse files

arm64: bpf: lift restriction on last instruction

commit 51c9fbb1b146f3336a93d398c439b6fbfe5ab489 upstream.

Earlier implementation assumed last instruction is BPF_EXIT.
Since this is no longer a restriction in eBPF, we remove this
limitation.

Per Alexei Starovoitov [1]:
> classic BPF has a restriction that last insn is always BPF_RET.
> eBPF doesn't have BPF_RET instruction and this restriction.
> It has BPF_EXIT insn which can appear anywhere in the program
> one or more times and it doesn't have to be last insn.

[1] https://lkml.org/lkml/2014/11/27/2



Fixes: e54bcde3 ("arm64: eBPF JIT compiler")
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarZi Shen Lim <zlim.lnx@gmail.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 516e433a
Loading
Loading
Loading
Loading
+8 −5
Original line number Original line Diff line number Diff line
@@ -60,7 +60,7 @@ struct jit_ctx {
	const struct bpf_prog *prog;
	const struct bpf_prog *prog;
	int idx;
	int idx;
	int tmp_used;
	int tmp_used;
	int body_offset;
	int epilogue_offset;
	int *offset;
	int *offset;
	u32 *image;
	u32 *image;
};
};
@@ -130,8 +130,8 @@ static void jit_fill_hole(void *area, unsigned int size)


static inline int epilogue_offset(const struct jit_ctx *ctx)
static inline int epilogue_offset(const struct jit_ctx *ctx)
{
{
	int to = ctx->offset[ctx->prog->len - 1];
	int to = ctx->epilogue_offset;
	int from = ctx->idx - ctx->body_offset;
	int from = ctx->idx;


	return to - from;
	return to - from;
}
}
@@ -463,6 +463,8 @@ emit_cond_jmp:
	}
	}
	/* function return */
	/* function return */
	case BPF_JMP | BPF_EXIT:
	case BPF_JMP | BPF_EXIT:
		/* Optimization: when last instruction is EXIT,
		   simply fallthrough to epilogue. */
		if (i == ctx->prog->len - 1)
		if (i == ctx->prog->len - 1)
			break;
			break;
		jmp_offset = epilogue_offset(ctx);
		jmp_offset = epilogue_offset(ctx);
@@ -685,11 +687,13 @@ void bpf_int_jit_compile(struct bpf_prog *prog)


	/* 1. Initial fake pass to compute ctx->idx. */
	/* 1. Initial fake pass to compute ctx->idx. */


	/* Fake pass to fill in ctx->offset. */
	/* Fake pass to fill in ctx->offset and ctx->tmp_used. */
	if (build_body(&ctx))
	if (build_body(&ctx))
		goto out;
		goto out;


	build_prologue(&ctx);
	build_prologue(&ctx);

	ctx.epilogue_offset = ctx.idx;
	build_epilogue(&ctx);
	build_epilogue(&ctx);


	/* Now we know the actual image size. */
	/* Now we know the actual image size. */
@@ -706,7 +710,6 @@ void bpf_int_jit_compile(struct bpf_prog *prog)


	build_prologue(&ctx);
	build_prologue(&ctx);


	ctx.body_offset = ctx.idx;
	if (build_body(&ctx)) {
	if (build_body(&ctx)) {
		bpf_jit_binary_free(header);
		bpf_jit_binary_free(header);
		goto out;
		goto out;