]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
cgroup: fix fail path in cgroup_load_subsys()
authorVladimir Davydov <vdavydov@parallels.com>
Thu, 12 Dec 2013 19:17:08 +0000 (23:17 +0400)
committerTejun Heo <tj@kernel.org>
Fri, 13 Dec 2013 20:46:49 +0000 (15:46 -0500)
Calling cgroup_unload_subsys() from cgroup_load_subsys() after
online_css() failure will result in a NULL ptr dereference on attempt to
offline_css(), because online_css() only assigns css to cgroup on
success. Let's fix that by skipping calls to offline_css() and
css_free() in cgroup_unload_subsys() if there is no css, and freeing css
in cgroup_load_subsys() on online_css() failure.

Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
kernel/cgroup.c

index 402f7aab8b2d9e5bf51bb3b5da150b81787d7cdd..7030f04f2890219fc428163e10b0056d207a3815 100644 (file)
@@ -4652,8 +4652,10 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
        write_unlock(&css_set_lock);
 
        ret = online_css(css);
-       if (ret)
+       if (ret) {
+               ss->css_free(css);
                goto err_unload;
+       }
 
        /* success! */
        mutex_unlock(&cgroup_root_mutex);
@@ -4680,6 +4682,7 @@ EXPORT_SYMBOL_GPL(cgroup_load_subsys);
 void cgroup_unload_subsys(struct cgroup_subsys *ss)
 {
        struct cgrp_cset_link *link;
+       struct cgroup_subsys_state *css;
 
        BUG_ON(ss->module == NULL);
 
@@ -4693,7 +4696,9 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
        mutex_lock(&cgroup_mutex);
        mutex_lock(&cgroup_root_mutex);
 
-       offline_css(cgroup_css(cgroup_dummy_top, ss));
+       css = cgroup_css(cgroup_dummy_top, ss);
+       if (css)
+               offline_css(css);
 
        /* deassign the subsys_id */
        cgroup_subsys[ss->subsys_id] = NULL;
@@ -4720,7 +4725,8 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
         * need to free before marking as null because ss->css_free needs
         * the cgrp->subsys pointer to find their state.
         */
-       ss->css_free(cgroup_css(cgroup_dummy_top, ss));
+       if (css)
+               ss->css_free(css);
        RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL);
 
        mutex_unlock(&cgroup_root_mutex);