Running a 3.4 kernel + Fedora-18 (systemd) userland on my Allwinner A10 (arm cortex a8), I'm seeing repeated, reproducable list_del list corruption errors when build with CONFIG_DEBUG_LIST, and the backtrace always shows free_css_set_work as the function making the problematic list_del call. I've tracked this doen to a use after free of the cgrp struct, specifically of the cgrp->css_sets list_head, which gets cleared by free_css_set_work. Since free_css_set_work runs form a workqueue, it is possible for it to not be done with clearing the list when the cgrp gets free-ed. To avoid this the code adding the links increases cgrp->count, and the freeing code running from the workqueue decreases cgrp->count *after* doing list_del, and then if the count goes to 0 calls cgroup_wakeup_rmdir_waiter(). However cgroup_rmdir() is missing a check for cgrp->count != 0, causing it to still continue with the rmdir (which leads to the free-ing of the cgrp), before free_css_set_work is done. Sometimes the free-ed memory is re-used before free_css_set_work gets around to unlinking link->cgrp_link_list, triggering the list_del list corruption messages. This patch fixes this by properly checking for cgrp->count != 0 and waiting for the cgroup_rmdir_waitq in that case. Changes in v2: -The cgrp->count check must be done before the cgroup_clear_css_refs() call/check, since on success cgroup_clear_css_refs has decremented all the css refs, and that *must* be done only once Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- kernel/cgroup.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 59e711a..9b0e1b4 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4022,7 +4022,12 @@ again: return -EBUSY; } prepare_to_wait(&cgroup_rmdir_waitq, &wait, TASK_INTERRUPTIBLE); - if (!cgroup_clear_css_refs(cgrp)) { + /* + * Note the cgrp->count check *must* be done before the + * cgroup_clear_css_refs() call, because on success that call has + * decremented all the css refs, and that *must* be done only once! + */ + if (atomic_read(&cgrp->count) != 0 || !cgroup_clear_css_refs(cgrp)) { mutex_unlock(&cgroup_mutex); /* * Because someone may call cgroup_wakeup_rmdir_waiter() before -- 1.8.0.2 -- To unsubscribe from this list: send the line "unsubscribe cgroups" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html