Skip to content

Commit f799243

Browse files
Hou TaoNobody
authored andcommitted
bpf: Introduce bpf_int_jit_abort()
It will be used to do cleanup for subprog which has been jited in first pass but extra pass has not been done. The scenario is possible when extra pass for subprog in the middle fails. The failure may lead to oops due to inconsistent status for pack allocator (e.g. ro_hdr->size and use_bpf_prog_pack) and memory leak in aux->jit_data. For x86-64, bpf_int_jit_abort() will free allocated memories saved in aux->jit_data and fall back to interpreter mode to bypass the calling of bpf_jit_binary_pack_free() in bpf_jit_free(). Signed-off-by: Hou Tao <[email protected]>
1 parent 029caed commit f799243

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

arch/x86/net/bpf_jit_comp.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,6 +2244,30 @@ struct x64_jit_data {
22442244
struct jit_context ctx;
22452245
};
22462246

2247+
void bpf_int_jit_abort(struct bpf_prog *prog)
2248+
{
2249+
struct x64_jit_data *jit_data = prog->aux->jit_data;
2250+
struct bpf_binary_header *header, *rw_header;
2251+
2252+
if (!jit_data)
2253+
return;
2254+
2255+
prog->bpf_func = NULL;
2256+
prog->jited = 0;
2257+
prog->jited_len = 0;
2258+
2259+
header = jit_data->header;
2260+
rw_header = jit_data->rw_header;
2261+
bpf_arch_text_copy(&header->size, &rw_header->size,
2262+
sizeof(rw_header->size));
2263+
bpf_jit_binary_pack_free(header, rw_header);
2264+
2265+
kvfree(jit_data->addrs);
2266+
kfree(jit_data);
2267+
2268+
prog->aux->jit_data = NULL;
2269+
}
2270+
22472271
#define MAX_PASSES 20
22482272
#define PADDING_PASSES (MAX_PASSES - 5)
22492273

include/linux/filter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
945945
(void *)__bpf_call_base)
946946

947947
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog);
948+
void bpf_int_jit_abort(struct bpf_prog *prog);
948949
void bpf_jit_compile(struct bpf_prog *prog);
949950
bool bpf_jit_needs_zext(void);
950951
bool bpf_jit_supports_kfunc_call(void);

kernel/bpf/core.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,6 +2636,15 @@ struct bpf_prog * __weak bpf_int_jit_compile(struct bpf_prog *prog)
26362636
return prog;
26372637
}
26382638

2639+
/*
2640+
* If arch JIT uses aux->jit_data to save temporary allocated status and
2641+
* supports subprog, it needs to override the function to free allocated
2642+
* memories and fall back to interpreter mode for passed prog.
2643+
*/
2644+
void __weak bpf_int_jit_abort(struct bpf_prog *prog)
2645+
{
2646+
}
2647+
26392648
/* Stub for JITs that support eBPF. All cBPF code gets transformed into
26402649
* eBPF by the kernel and is later compiled by bpf_int_jit_compile().
26412650
*/

kernel/bpf/verifier.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13085,6 +13085,9 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1308513085
if (tmp != func[i] || func[i]->bpf_func != old_bpf_func) {
1308613086
verbose(env, "JIT doesn't support bpf-to-bpf calls\n");
1308713087
err = -ENOTSUPP;
13088+
/* Abort extra pass for the remaining subprogs */
13089+
while (++i < env->subprog_cnt)
13090+
bpf_int_jit_abort(func[i]);
1308813091
goto out_free;
1308913092
}
1309013093
cond_resched();

0 commit comments

Comments
 (0)