bpf: Fix a potential use-after-free in bpf_link_free()
After commit1a80dbcb2d
, bpf_link can be freed by link->ops->dealloc_deferred, but the code still tests and uses link->ops->dealloc afterward, which leads to a use-after-free as reported by syzbot. Actually, one of them should be sufficient, so just call one of them instead of both. Also add a WARN_ON() in case of any problematic implementation. Fixes:1a80dbcb2d
("bpf: support deferring bpf_link dealloc to after RCU grace period") Reported-by: syzbot+1989ee16d94720836244@syzkaller.appspotmail.com Signed-off-by: Cong Wang <cong.wang@bytedance.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Jiri Olsa <jolsa@kernel.org> Link: https://lore.kernel.org/bpf/20240602182703.207276-1-xiyou.wangcong@gmail.com
This commit is contained in:
parent
2317dc2c22
commit
2884dc7d08
|
@ -2998,6 +2998,7 @@ static int bpf_obj_get(const union bpf_attr *attr)
|
|||
void bpf_link_init(struct bpf_link *link, enum bpf_link_type type,
|
||||
const struct bpf_link_ops *ops, struct bpf_prog *prog)
|
||||
{
|
||||
WARN_ON(ops->dealloc && ops->dealloc_deferred);
|
||||
atomic64_set(&link->refcnt, 1);
|
||||
link->type = type;
|
||||
link->id = 0;
|
||||
|
@ -3056,16 +3057,17 @@ static void bpf_link_defer_dealloc_mult_rcu_gp(struct rcu_head *rcu)
|
|||
/* bpf_link_free is guaranteed to be called from process context */
|
||||
static void bpf_link_free(struct bpf_link *link)
|
||||
{
|
||||
const struct bpf_link_ops *ops = link->ops;
|
||||
bool sleepable = false;
|
||||
|
||||
bpf_link_free_id(link->id);
|
||||
if (link->prog) {
|
||||
sleepable = link->prog->sleepable;
|
||||
/* detach BPF program, clean up used resources */
|
||||
link->ops->release(link);
|
||||
ops->release(link);
|
||||
bpf_prog_put(link->prog);
|
||||
}
|
||||
if (link->ops->dealloc_deferred) {
|
||||
if (ops->dealloc_deferred) {
|
||||
/* schedule BPF link deallocation; if underlying BPF program
|
||||
* is sleepable, we need to first wait for RCU tasks trace
|
||||
* sync, then go through "classic" RCU grace period
|
||||
|
@ -3074,9 +3076,8 @@ static void bpf_link_free(struct bpf_link *link)
|
|||
call_rcu_tasks_trace(&link->rcu, bpf_link_defer_dealloc_mult_rcu_gp);
|
||||
else
|
||||
call_rcu(&link->rcu, bpf_link_defer_dealloc_rcu_gp);
|
||||
}
|
||||
if (link->ops->dealloc)
|
||||
link->ops->dealloc(link);
|
||||
} else if (ops->dealloc)
|
||||
ops->dealloc(link);
|
||||
}
|
||||
|
||||
static void bpf_link_put_deferred(struct work_struct *work)
|
||||
|
|
Loading…
Reference in New Issue