Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7f89616 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 1b304a1a 97a61369
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -5255,8 +5255,16 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
	 * if the parent has to be frozen, the child has too.
	 */
	cgrp->freezer.e_freeze = parent->freezer.e_freeze;
	if (cgrp->freezer.e_freeze)
	if (cgrp->freezer.e_freeze) {
		/*
		 * Set the CGRP_FREEZE flag, so when a process will be
		 * attached to the child cgroup, it will become frozen.
		 * At this point the new cgroup is unpopulated, so we can
		 * consider it frozen immediately.
		 */
		set_bit(CGRP_FREEZE, &cgrp->flags);
		set_bit(CGRP_FROZEN, &cgrp->flags);
	}

	spin_lock_irq(&css_set_lock);
	for (tcgrp = cgrp; tcgrp; tcgrp = cgroup_parent(tcgrp)) {
+54 −0
Original line number Diff line number Diff line
@@ -447,6 +447,59 @@ static int test_cgfreezer_forkbomb(const char *root)
	return ret;
}

/*
 * The test creates a cgroups and freezes it. Then it creates a child cgroup
 * and populates it with a task. After that it checks that the child cgroup
 * is frozen and the parent cgroup remains frozen too.
 */
static int test_cgfreezer_mkdir(const char *root)
{
	int ret = KSFT_FAIL;
	char *parent, *child = NULL;
	int pid;

	parent = cg_name(root, "cg_test_mkdir_A");
	if (!parent)
		goto cleanup;

	child = cg_name(parent, "cg_test_mkdir_B");
	if (!child)
		goto cleanup;

	if (cg_create(parent))
		goto cleanup;

	if (cg_freeze_wait(parent, true))
		goto cleanup;

	if (cg_create(child))
		goto cleanup;

	pid = cg_run_nowait(child, child_fn, NULL);
	if (pid < 0)
		goto cleanup;

	if (cg_wait_for_proc_count(child, 1))
		goto cleanup;

	if (cg_check_frozen(child, true))
		goto cleanup;

	if (cg_check_frozen(parent, true))
		goto cleanup;

	ret = KSFT_PASS;

cleanup:
	if (child)
		cg_destroy(child);
	free(child);
	if (parent)
		cg_destroy(parent);
	free(parent);
	return ret;
}

/*
 * The test creates two nested cgroups, freezes the parent
 * and removes the child. Then it checks that the parent cgroup
@@ -815,6 +868,7 @@ struct cgfreezer_test {
	T(test_cgfreezer_simple),
	T(test_cgfreezer_tree),
	T(test_cgfreezer_forkbomb),
	T(test_cgfreezer_mkdir),
	T(test_cgfreezer_rmdir),
	T(test_cgfreezer_migrate),
	T(test_cgfreezer_ptrace),