Skip to content

Commit d0b97f3

Browse files
committed
Merge tag 'cgroup-for-5.19-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fix from Tejun Heo: "Fix an old and subtle bug in the migration path. css_sets are used to track tasks and migrations are tasks moving from a group of css_sets to another group of css_sets. The migration path pins all source and destination css_sets in the prep stage. Unfortunately, it was overloading the same list_head entry to track sources and destinations, which got confused for migrations which are partially identity leading to use-after-frees. Fixed by using dedicated list_heads for tracking sources and destinations" * tag 'cgroup-for-5.19-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: Use separate src/dst nodes when preloading css_sets for migration
2 parents 5750676 + 07fd5b6 commit d0b97f3

2 files changed

Lines changed: 25 additions & 15 deletions

File tree

include/linux/cgroup-defs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ struct css_set {
264264
* List of csets participating in the on-going migration either as
265265
* source or destination. Protected by cgroup_mutex.
266266
*/
267-
struct list_head mg_preload_node;
267+
struct list_head mg_src_preload_node;
268+
struct list_head mg_dst_preload_node;
268269
struct list_head mg_node;
269270

270271
/*

kernel/cgroup/cgroup.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,8 @@ struct css_set init_css_set = {
765765
.task_iters = LIST_HEAD_INIT(init_css_set.task_iters),
766766
.threaded_csets = LIST_HEAD_INIT(init_css_set.threaded_csets),
767767
.cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links),
768-
.mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node),
768+
.mg_src_preload_node = LIST_HEAD_INIT(init_css_set.mg_src_preload_node),
769+
.mg_dst_preload_node = LIST_HEAD_INIT(init_css_set.mg_dst_preload_node),
769770
.mg_node = LIST_HEAD_INIT(init_css_set.mg_node),
770771

771772
/*
@@ -1240,7 +1241,8 @@ static struct css_set *find_css_set(struct css_set *old_cset,
12401241
INIT_LIST_HEAD(&cset->threaded_csets);
12411242
INIT_HLIST_NODE(&cset->hlist);
12421243
INIT_LIST_HEAD(&cset->cgrp_links);
1243-
INIT_LIST_HEAD(&cset->mg_preload_node);
1244+
INIT_LIST_HEAD(&cset->mg_src_preload_node);
1245+
INIT_LIST_HEAD(&cset->mg_dst_preload_node);
12441246
INIT_LIST_HEAD(&cset->mg_node);
12451247

12461248
/* Copy the set of subsystem state objects generated in
@@ -2597,21 +2599,27 @@ int cgroup_migrate_vet_dst(struct cgroup *dst_cgrp)
25972599
*/
25982600
void cgroup_migrate_finish(struct cgroup_mgctx *mgctx)
25992601
{
2600-
LIST_HEAD(preloaded);
26012602
struct css_set *cset, *tmp_cset;
26022603

26032604
lockdep_assert_held(&cgroup_mutex);
26042605

26052606
spin_lock_irq(&css_set_lock);
26062607

2607-
list_splice_tail_init(&mgctx->preloaded_src_csets, &preloaded);
2608-
list_splice_tail_init(&mgctx->preloaded_dst_csets, &preloaded);
2608+
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_src_csets,
2609+
mg_src_preload_node) {
2610+
cset->mg_src_cgrp = NULL;
2611+
cset->mg_dst_cgrp = NULL;
2612+
cset->mg_dst_cset = NULL;
2613+
list_del_init(&cset->mg_src_preload_node);
2614+
put_css_set_locked(cset);
2615+
}
26092616

2610-
list_for_each_entry_safe(cset, tmp_cset, &preloaded, mg_preload_node) {
2617+
list_for_each_entry_safe(cset, tmp_cset, &mgctx->preloaded_dst_csets,
2618+
mg_dst_preload_node) {
26112619
cset->mg_src_cgrp = NULL;
26122620
cset->mg_dst_cgrp = NULL;
26132621
cset->mg_dst_cset = NULL;
2614-
list_del_init(&cset->mg_preload_node);
2622+
list_del_init(&cset->mg_dst_preload_node);
26152623
put_css_set_locked(cset);
26162624
}
26172625

@@ -2651,7 +2659,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
26512659
if (src_cset->dead)
26522660
return;
26532661

2654-
if (!list_empty(&src_cset->mg_preload_node))
2662+
if (!list_empty(&src_cset->mg_src_preload_node))
26552663
return;
26562664

26572665
src_cgrp = cset_cgroup_from_root(src_cset, dst_cgrp->root);
@@ -2664,7 +2672,7 @@ void cgroup_migrate_add_src(struct css_set *src_cset,
26642672
src_cset->mg_src_cgrp = src_cgrp;
26652673
src_cset->mg_dst_cgrp = dst_cgrp;
26662674
get_css_set(src_cset);
2667-
list_add_tail(&src_cset->mg_preload_node, &mgctx->preloaded_src_csets);
2675+
list_add_tail(&src_cset->mg_src_preload_node, &mgctx->preloaded_src_csets);
26682676
}
26692677

26702678
/**
@@ -2689,7 +2697,7 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
26892697

26902698
/* look up the dst cset for each src cset and link it to src */
26912699
list_for_each_entry_safe(src_cset, tmp_cset, &mgctx->preloaded_src_csets,
2692-
mg_preload_node) {
2700+
mg_src_preload_node) {
26932701
struct css_set *dst_cset;
26942702
struct cgroup_subsys *ss;
26952703
int ssid;
@@ -2708,16 +2716,16 @@ int cgroup_migrate_prepare_dst(struct cgroup_mgctx *mgctx)
27082716
if (src_cset == dst_cset) {
27092717
src_cset->mg_src_cgrp = NULL;
27102718
src_cset->mg_dst_cgrp = NULL;
2711-
list_del_init(&src_cset->mg_preload_node);
2719+
list_del_init(&src_cset->mg_src_preload_node);
27122720
put_css_set(src_cset);
27132721
put_css_set(dst_cset);
27142722
continue;
27152723
}
27162724

27172725
src_cset->mg_dst_cset = dst_cset;
27182726

2719-
if (list_empty(&dst_cset->mg_preload_node))
2720-
list_add_tail(&dst_cset->mg_preload_node,
2727+
if (list_empty(&dst_cset->mg_dst_preload_node))
2728+
list_add_tail(&dst_cset->mg_dst_preload_node,
27212729
&mgctx->preloaded_dst_csets);
27222730
else
27232731
put_css_set(dst_cset);
@@ -2963,7 +2971,8 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
29632971
goto out_finish;
29642972

29652973
spin_lock_irq(&css_set_lock);
2966-
list_for_each_entry(src_cset, &mgctx.preloaded_src_csets, mg_preload_node) {
2974+
list_for_each_entry(src_cset, &mgctx.preloaded_src_csets,
2975+
mg_src_preload_node) {
29672976
struct task_struct *task, *ntask;
29682977

29692978
/* all tasks in src_csets need to be migrated */

0 commit comments

Comments
 (0)