cgroups: if you list_empty() a head then don't list_del() it
list_del() leaves poison in the prev and next pointers. The next list_empty() will compare those poisons, and say the list isn't empty. Any list operations that assume the node is on a list because of such a check will be fooled into dereferencing poison. One needs to INIT the node after the del, and fortunately there's already a wrapper for that - list_del_init(). Some of the dels are followed by deallocations, so can be ignored, and one can be merged with an add to make a move. Apart from that, I erred on the side of caution in making nodes list_empty()-queriable. Signed-off-by: Phil Carmody <ext-phil.2.carmody@nokia.com> Reviewed-by: Paul Menage <menage@google.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Acked-by: Kirill A. Shutemov <kirill@shutemov.name> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
edd45544c6
Коммит
8d2587970b
|
@ -1813,10 +1813,8 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
|
|||
|
||||
/* Update the css_set linked lists if we're using them */
|
||||
write_lock(&css_set_lock);
|
||||
if (!list_empty(&tsk->cg_list)) {
|
||||
list_del(&tsk->cg_list);
|
||||
list_add(&tsk->cg_list, &newcg->tasks);
|
||||
}
|
||||
if (!list_empty(&tsk->cg_list))
|
||||
list_move(&tsk->cg_list, &newcg->tasks);
|
||||
write_unlock(&css_set_lock);
|
||||
|
||||
for_each_subsys(root, ss) {
|
||||
|
@ -3655,12 +3653,12 @@ again:
|
|||
spin_lock(&release_list_lock);
|
||||
set_bit(CGRP_REMOVED, &cgrp->flags);
|
||||
if (!list_empty(&cgrp->release_list))
|
||||
list_del(&cgrp->release_list);
|
||||
list_del_init(&cgrp->release_list);
|
||||
spin_unlock(&release_list_lock);
|
||||
|
||||
cgroup_lock_hierarchy(cgrp->root);
|
||||
/* delete this cgroup from parent->children */
|
||||
list_del(&cgrp->sibling);
|
||||
list_del_init(&cgrp->sibling);
|
||||
cgroup_unlock_hierarchy(cgrp->root);
|
||||
|
||||
d = dget(cgrp->dentry);
|
||||
|
@ -3879,7 +3877,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
|
|||
subsys[ss->subsys_id] = NULL;
|
||||
|
||||
/* remove subsystem from rootnode's list of subsystems */
|
||||
list_del(&ss->sibling);
|
||||
list_del_init(&ss->sibling);
|
||||
|
||||
/*
|
||||
* disentangle the css from all css_sets attached to the dummytop. as
|
||||
|
@ -4241,7 +4239,7 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
|
|||
if (!list_empty(&tsk->cg_list)) {
|
||||
write_lock(&css_set_lock);
|
||||
if (!list_empty(&tsk->cg_list))
|
||||
list_del(&tsk->cg_list);
|
||||
list_del_init(&tsk->cg_list);
|
||||
write_unlock(&css_set_lock);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче