Commit 51c9fbb1 authored by Zi Shen Lim's avatar Zi Shen Lim Committed by Will Deacon

arm64: bpf: lift restriction on last instruction

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>
parent e4f88d83
...@@ -60,7 +60,7 @@ struct jit_ctx { ...@@ -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) ...@@ -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 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) ...@@ -463,6 +463,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
} }
/* 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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment