Skip to content

Commit a7f8961

Browse files
committed
Merge branch 'for-5.3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fix from Tejun Heo: "Roman found and fixed a bug in the cgroup2 freezer which allows new child cgroup to escape frozen state" * 'for-5.3-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: freezer: fix frozen state inheritance kselftests: cgroup: add freezer mkdir test
2 parents 1b304a1 + 97a6136 commit a7f8961

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

kernel/cgroup/cgroup.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5255,8 +5255,16 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
52555255
* if the parent has to be frozen, the child has too.
52565256
*/
52575257
cgrp->freezer.e_freeze = parent->freezer.e_freeze;
5258-
if (cgrp->freezer.e_freeze)
5258+
if (cgrp->freezer.e_freeze) {
5259+
/*
5260+
* Set the CGRP_FREEZE flag, so when a process will be
5261+
* attached to the child cgroup, it will become frozen.
5262+
* At this point the new cgroup is unpopulated, so we can
5263+
* consider it frozen immediately.
5264+
*/
5265+
set_bit(CGRP_FREEZE, &cgrp->flags);
52595266
set_bit(CGRP_FROZEN, &cgrp->flags);
5267+
}
52605268

52615269
spin_lock_irq(&css_set_lock);
52625270
for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) {

tools/testing/selftests/cgroup/test_freezer.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,59 @@ static int test_cgfreezer_forkbomb(const char *root)
447447
return ret;
448448
}
449449

450+
/*
451+
* The test creates a cgroups and freezes it. Then it creates a child cgroup
452+
* and populates it with a task. After that it checks that the child cgroup
453+
* is frozen and the parent cgroup remains frozen too.
454+
*/
455+
static int test_cgfreezer_mkdir(const char *root)
456+
{
457+
int ret = KSFT_FAIL;
458+
char *parent, *child = NULL;
459+
int pid;
460+
461+
parent = cg_name(root, "cg_test_mkdir_A");
462+
if (!parent)
463+
goto cleanup;
464+
465+
child = cg_name(parent, "cg_test_mkdir_B");
466+
if (!child)
467+
goto cleanup;
468+
469+
if (cg_create(parent))
470+
goto cleanup;
471+
472+
if (cg_freeze_wait(parent, true))
473+
goto cleanup;
474+
475+
if (cg_create(child))
476+
goto cleanup;
477+
478+
pid = cg_run_nowait(child, child_fn, NULL);
479+
if (pid < 0)
480+
goto cleanup;
481+
482+
if (cg_wait_for_proc_count(child, 1))
483+
goto cleanup;
484+
485+
if (cg_check_frozen(child, true))
486+
goto cleanup;
487+
488+
if (cg_check_frozen(parent, true))
489+
goto cleanup;
490+
491+
ret = KSFT_PASS;
492+
493+
cleanup:
494+
if (child)
495+
cg_destroy(child);
496+
free(child);
497+
if (parent)
498+
cg_destroy(parent);
499+
free(parent);
500+
return ret;
501+
}
502+
450503
/*
451504
* The test creates two nested cgroups, freezes the parent
452505
* and removes the child. Then it checks that the parent cgroup
@@ -815,6 +868,7 @@ struct cgfreezer_test {
815868
T(test_cgfreezer_simple),
816869
T(test_cgfreezer_tree),
817870
T(test_cgfreezer_forkbomb),
871+
T(test_cgfreezer_mkdir),
818872
T(test_cgfreezer_rmdir),
819873
T(test_cgfreezer_migrate),
820874
T(test_cgfreezer_ptrace),

0 commit comments

Comments
 (0)