Message ID | 20221121073440.1828292-2-houtao@huaweicloud.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 1a5160d4d8fe63ba4964cfff4a85831b6af75f2d |
Delegated to: | BPF |
Headers | show |
Series | bpf: Pin the start cgroup for cgroup iterator | expand |
On 11/20/22 11:34 PM, Hou Tao wrote: > From: Hou Tao <houtao1@huawei.com> > > bpf_iter_attach_cgroup() has already acquired an extra reference for the > start cgroup, but the reference may be released if the iterator link fd > is closed after the creation of iterator fd, and it may lead to > user-after-free problem when reading the iterator fd. > > An alternative fix is pinning iterator link when opening iterator, > but it will make iterator link being still visible after the close of > iterator link fd and the behavior is different with other link types, so > just fixing it by acquiring another reference for the start cgroup. > > Fixes: d4ccaf58a847 ("bpf: Introduce cgroup iter") > Signed-off-by: Hou Tao <houtao1@huawei.com> Acked-by: Yonghong Song <yhs@fb.com>
diff --git a/kernel/bpf/cgroup_iter.c b/kernel/bpf/cgroup_iter.c index fbc6167c3599..06989d278846 100644 --- a/kernel/bpf/cgroup_iter.c +++ b/kernel/bpf/cgroup_iter.c @@ -164,16 +164,30 @@ static int cgroup_iter_seq_init(void *priv, struct bpf_iter_aux_info *aux) struct cgroup_iter_priv *p = (struct cgroup_iter_priv *)priv; struct cgroup *cgrp = aux->cgroup.start; + /* bpf_iter_attach_cgroup() has already acquired an extra reference + * for the start cgroup, but the reference may be released after + * cgroup_iter_seq_init(), so acquire another reference for the + * start cgroup. + */ p->start_css = &cgrp->self; + css_get(p->start_css); p->terminate = false; p->visited_all = false; p->order = aux->cgroup.order; return 0; } +static void cgroup_iter_seq_fini(void *priv) +{ + struct cgroup_iter_priv *p = (struct cgroup_iter_priv *)priv; + + css_put(p->start_css); +} + static const struct bpf_iter_seq_info cgroup_iter_seq_info = { .seq_ops = &cgroup_iter_seq_ops, .init_seq_private = cgroup_iter_seq_init, + .fini_seq_private = cgroup_iter_seq_fini, .seq_priv_size = sizeof(struct cgroup_iter_priv), };