Commit f324cda693e53b4fafdeb043f1e90fd5bd749dfb

Authored by Zi Shen Lim
Committed by Greg Kroah-Hartman
1 parent 516e433a15

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: e54bcde3d69d ("arm64: eBPF JIT compiler")
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Signed-off-by: Zi Shen Lim <zlim.lnx@gmail.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 8 additions and 5 deletions Side-by-side Diff

arch/arm64/net/bpf_jit_comp.c
... ... @@ -60,7 +60,7 @@
60 60 const struct bpf_prog *prog;
61 61 int idx;
62 62 int tmp_used;
63   - int body_offset;
  63 + int epilogue_offset;
64 64 int *offset;
65 65 u32 *image;
66 66 };
... ... @@ -130,8 +130,8 @@
130 130  
131 131 static inline int epilogue_offset(const struct jit_ctx *ctx)
132 132 {
133   - int to = ctx->offset[ctx->prog->len - 1];
134   - int from = ctx->idx - ctx->body_offset;
  133 + int to = ctx->epilogue_offset;
  134 + int from = ctx->idx;
135 135  
136 136 return to - from;
137 137 }
... ... @@ -463,6 +463,8 @@
463 463 }
464 464 /* function return */
465 465 case BPF_JMP | BPF_EXIT:
  466 + /* Optimization: when last instruction is EXIT,
  467 + simply fallthrough to epilogue. */
466 468 if (i == ctx->prog->len - 1)
467 469 break;
468 470 jmp_offset = epilogue_offset(ctx);
469 471  
... ... @@ -685,11 +687,13 @@
685 687  
686 688 /* 1. Initial fake pass to compute ctx->idx. */
687 689  
688   - /* Fake pass to fill in ctx->offset. */
  690 + /* Fake pass to fill in ctx->offset and ctx->tmp_used. */
689 691 if (build_body(&ctx))
690 692 goto out;
691 693  
692 694 build_prologue(&ctx);
  695 +
  696 + ctx.epilogue_offset = ctx.idx;
693 697 build_epilogue(&ctx);
694 698  
695 699 /* Now we know the actual image size. */
... ... @@ -706,7 +710,6 @@
706 710  
707 711 build_prologue(&ctx);
708 712  
709   - ctx.body_offset = ctx.idx;
710 713 if (build_body(&ctx)) {
711 714 bpf_jit_binary_free(header);
712 715 goto out;