@@ -141,14 +141,17 @@ static inline void emit_addr_mov_i64(const int reg, const u64 val,
141141 }
142142}
143143
144- static inline int bpf2a64_offset (int bpf_to , int bpf_from ,
144+ static inline int bpf2a64_offset (int bpf_insn , int off ,
145145 const struct jit_ctx * ctx )
146146{
147- int to = ctx -> offset [bpf_to ];
148- /* -1 to account for the Branch instruction */
149- int from = ctx -> offset [bpf_from ] - 1 ;
150-
151- return to - from ;
147+ /* BPF JMP offset is relative to the next instruction */
148+ bpf_insn ++ ;
149+ /*
150+ * Whereas arm64 branch instructions encode the offset
151+ * from the branch itself, so we must subtract 1 from the
152+ * instruction offset.
153+ */
154+ return ctx -> offset [bpf_insn + off ] - (ctx -> offset [bpf_insn ] - 1 );
152155}
153156
154157static void jit_fill_hole (void * area , unsigned int size )
@@ -578,7 +581,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
578581
579582 /* JUMP off */
580583 case BPF_JMP | BPF_JA :
581- jmp_offset = bpf2a64_offset (i + off , i , ctx );
584+ jmp_offset = bpf2a64_offset (i , off , ctx );
582585 check_imm26 (jmp_offset );
583586 emit (A64_B (jmp_offset ), ctx );
584587 break ;
@@ -605,7 +608,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
605608 case BPF_JMP32 | BPF_JSLE | BPF_X :
606609 emit (A64_CMP (is64 , dst , src ), ctx );
607610emit_cond_jmp :
608- jmp_offset = bpf2a64_offset (i + off , i , ctx );
611+ jmp_offset = bpf2a64_offset (i , off , ctx );
609612 check_imm19 (jmp_offset );
610613 switch (BPF_OP (code )) {
611614 case BPF_JEQ :
@@ -837,22 +840,38 @@ static int build_body(struct jit_ctx *ctx, bool extra_pass)
837840 const struct bpf_prog * prog = ctx -> prog ;
838841 int i ;
839842
843+ /*
844+ * - offset[0] offset of the end of prologue,
845+ * start of the 1st instruction.
846+ * - offset[1] - offset of the end of 1st instruction,
847+ * start of the 2nd instruction
848+ * [....]
849+ * - offset[3] - offset of the end of 3rd instruction,
850+ * start of 4th instruction
851+ */
840852 for (i = 0 ; i < prog -> len ; i ++ ) {
841853 const struct bpf_insn * insn = & prog -> insnsi [i ];
842854 int ret ;
843855
856+ if (ctx -> image == NULL )
857+ ctx -> offset [i ] = ctx -> idx ;
844858 ret = build_insn (insn , ctx , extra_pass );
845859 if (ret > 0 ) {
846860 i ++ ;
847861 if (ctx -> image == NULL )
848862 ctx -> offset [i ] = ctx -> idx ;
849863 continue ;
850864 }
851- if (ctx -> image == NULL )
852- ctx -> offset [i ] = ctx -> idx ;
853865 if (ret )
854866 return ret ;
855867 }
868+ /*
869+ * offset is allocated with prog->len + 1 so fill in
870+ * the last element with the offset after the last
871+ * instruction (end of program)
872+ */
873+ if (ctx -> image == NULL )
874+ ctx -> offset [i ] = ctx -> idx ;
856875
857876 return 0 ;
858877}
@@ -928,7 +947,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
928947 memset (& ctx , 0 , sizeof (ctx ));
929948 ctx .prog = prog ;
930949
931- ctx .offset = kcalloc (prog -> len , sizeof (int ), GFP_KERNEL );
950+ ctx .offset = kcalloc (prog -> len + 1 , sizeof (int ), GFP_KERNEL );
932951 if (ctx .offset == NULL ) {
933952 prog = orig_prog ;
934953 goto out_off ;
@@ -1008,7 +1027,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
10081027 prog -> jited_len = image_size ;
10091028
10101029 if (!prog -> is_func || extra_pass ) {
1011- bpf_prog_fill_jited_linfo (prog , ctx .offset );
1030+ bpf_prog_fill_jited_linfo (prog , ctx .offset + 1 );
10121031out_off :
10131032 kfree (ctx .offset );
10141033 kfree (jit_data );
0 commit comments