[PATCH] cgroup_freezer: Freezing and task move race fix

From: Tomasz Buchert
Date: Tue Aug 10 2010 - 15:53:37 EST


Writing 'FROZEN' to freezer.state file does not
forbid the task to be moved away from its cgroup
(for a very short time). Nevertheless the moved task
can become frozen OUTSIDE its cgroup which puts
discussed task in a permanent 'D' state.

This patch forbids migration of either FROZEN
or FREEZING tasks.

This behavior was observed and easily reproduced on
a single core laptop. Program and instructions how
to reproduce the bug can be fetched from:
http://pentium.hopto.org/~thinred/repos/linux-misc/freezer_bug.c

Signed-off-by: Tomasz Buchert <tomasz.buchert@xxxxxxxx>
---
kernel/cgroup_freezer.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index ce71ed5..e49aa8c 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -161,6 +161,12 @@ static bool is_task_frozen_enough(struct task_struct *task)
(task_is_stopped_or_traced(task) && freezing(task));
}

+/* Task is in a state that forbids any cgroup migration. */
+static bool is_task_pinned_down(struct task_struct *task)
+{
+ return freezing(task) || frozen(task);
+}
+
/*
* The call to cgroup_lock() in the freezer.state write method prevents
* a write to that file racing against an attach, and hence the
@@ -179,7 +185,7 @@ static int freezer_can_attach(struct cgroup_subsys *ss,
* frozen, so it's sufficient to check the latter condition.
*/

- if (is_task_frozen_enough(task))
+ if (is_task_pinned_down(task))
return -EBUSY;

freezer = cgroup_freezer(new_cgroup);
@@ -191,7 +197,7 @@ static int freezer_can_attach(struct cgroup_subsys *ss,

rcu_read_lock();
list_for_each_entry_rcu(c, &task->thread_group, thread_group) {
- if (is_task_frozen_enough(c)) {
+ if (is_task_pinned_down(c)) {
rcu_read_unlock();
return -EBUSY;
}
--
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/