Skip to content

Commit 7d1982b

Browse files
borkmannAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: fix panic in prog load calls cleanup
While testing I found that when hitting error path in bpf_prog_load() where we jump to free_used_maps and prog contained BPF to BPF calls that were JITed earlier, then we never clean up the bpf_prog_kallsyms_add() done under jit_subprogs(). Add proper API to make BPF kallsyms deletion more clear and fix that. Fixes: 1c2a088 ("bpf: x64: add JIT support for multi-function programs") Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 26bf8a8 commit 7d1982b

File tree

3 files changed

+19
-6
lines changed

3 files changed

+19
-6
lines changed

include/linux/filter.h

+3
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,9 @@ static inline void bpf_prog_kallsyms_del(struct bpf_prog *fp)
961961
}
962962
#endif /* CONFIG_BPF_JIT */
963963

964+
void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp);
965+
void bpf_prog_kallsyms_del_all(struct bpf_prog *fp);
966+
964967
#define BPF_ANC BIT(15)
965968

966969
static inline bool bpf_needs_clear_a(const struct sock_filter *first)

kernel/bpf/core.c

+14
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,20 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
350350
return prog_adj;
351351
}
352352

353+
void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
354+
{
355+
int i;
356+
357+
for (i = 0; i < fp->aux->func_cnt; i++)
358+
bpf_prog_kallsyms_del(fp->aux->func[i]);
359+
}
360+
361+
void bpf_prog_kallsyms_del_all(struct bpf_prog *fp)
362+
{
363+
bpf_prog_kallsyms_del_subprogs(fp);
364+
bpf_prog_kallsyms_del(fp);
365+
}
366+
353367
#ifdef CONFIG_BPF_JIT
354368
/* All BPF JIT sysctl knobs here. */
355369
int bpf_jit_enable __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_ALWAYS_ON);

kernel/bpf/syscall.c

+2-6
Original file line numberDiff line numberDiff line change
@@ -1034,14 +1034,9 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu)
10341034
static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
10351035
{
10361036
if (atomic_dec_and_test(&prog->aux->refcnt)) {
1037-
int i;
1038-
10391037
/* bpf_prog_free_id() must be called first */
10401038
bpf_prog_free_id(prog, do_idr_lock);
1041-
1042-
for (i = 0; i < prog->aux->func_cnt; i++)
1043-
bpf_prog_kallsyms_del(prog->aux->func[i]);
1044-
bpf_prog_kallsyms_del(prog);
1039+
bpf_prog_kallsyms_del_all(prog);
10451040

10461041
call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
10471042
}
@@ -1384,6 +1379,7 @@ static int bpf_prog_load(union bpf_attr *attr)
13841379
return err;
13851380

13861381
free_used_maps:
1382+
bpf_prog_kallsyms_del_subprogs(prog);
13871383
free_used_maps(prog->aux);
13881384
free_prog:
13891385
bpf_prog_uncharge_memlock(prog);

0 commit comments

Comments
 (0)