Commit 14a67b42 authored by Chen Ridong's avatar Chen Ridong Committed by Tejun Heo
Browse files

Revert "cgroup_freezer: cgroup_freezing: Check if not frozen"



This reverts commit cff5f49d.

Commit cff5f49d ("cgroup_freezer: cgroup_freezing: Check if not
frozen") modified the cgroup_freezing() logic to verify that the FROZEN
flag is not set, affecting the return value of the freezing() function,
in order to address a warning in __thaw_task.

A race condition exists that may allow tasks to escape being frozen. The
following scenario demonstrates this issue:

CPU 0 (get_signal path)		CPU 1 (freezer.state reader)
try_to_freeze			read freezer.state
__refrigerator			freezer_read
				update_if_frozen
WRITE_ONCE(current->__state, TASK_FROZEN);
				...
				/* Task is now marked frozen */
				/* frozen(task) == true */
				/* Assuming other tasks are frozen */
				freezer->state |= CGROUP_FROZEN;
/* freezing(current) returns false */
/* because cgroup is frozen (not freezing) */
break out
__set_current_state(TASK_RUNNING);
/* Bug: Task resumes running when it should remain frozen */

The existing !frozen(p) check in __thaw_task makes the
WARN_ON_ONCE(freezing(p)) warning redundant. Removing this warning enables
reverting the commit cff5f49d ("cgroup_freezer: cgroup_freezing: Check
if not frozen") to resolve the issue.

The warning has been removed in the previous patch. This patch revert the
commit cff5f49d ("cgroup_freezer: cgroup_freezing: Check if not
frozen") to complete the fix.

Fixes: cff5f49d ("cgroup_freezer: cgroup_freezing: Check if not frozen")
Reported-by: default avatarZhong <Jiawei&lt;zhongjiawei1@huawei.com>
Signed-off-by: default avatarChen Ridong <chenridong@huawei.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 9beb8c5e
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -66,15 +66,9 @@ static struct freezer *parent_freezer(struct freezer *freezer)
bool cgroup_freezing(struct task_struct *task)
{
	bool ret;
	unsigned int state;

	rcu_read_lock();
	/* Check if the cgroup is still FREEZING, but not FROZEN. The extra
	 * !FROZEN check is required, because the FREEZING bit is not cleared
	 * when the state FROZEN is reached.
	 */
	state = task_freezer(task)->state;
	ret = (state & CGROUP_FREEZING) && !(state & CGROUP_FROZEN);
	ret = task_freezer(task)->state & CGROUP_FREEZING;
	rcu_read_unlock();

	return ret;