lkml.org 
[lkml]   [2016]   [May]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 024/163] sched/cgroup: Fix/cleanup cgroup teardown/init
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Peter Zijlstra <peterz@infradead.org>

    commit 2f5177f0fd7e531b26d54633be62d1d4cb94621c upstream.

    The CPU controller hasn't kept up with the various changes in the whole
    cgroup initialization / destruction sequence, and commit:

    2e91fa7f6d45 ("cgroup: keep zombies associated with their original cgroups")

    caused it to explode.

    The reason for this is that zombies do not inhibit css_offline() from
    being called, but do stall css_released(). Now we tear down the cfs_rq
    structures on css_offline() but zombies can run after that, leading to
    use-after-free issues.

    The solution is to move the tear-down to css_released(), which
    guarantees nobody (including no zombies) is still using our cgroup.

    Furthermore, a few simple cleanups are possible too. There doesn't
    appear to be any point to us using css_online() (anymore?) so fold that
    in css_alloc().

    And since cgroup code guarantees an RCU grace period between
    css_released() and css_free() we can forgo using call_rcu() and free the
    stuff immediately.

    Suggested-by: Tejun Heo <tj@kernel.org>
    Reported-by: Kazuki Yamaguchi <k@rhe.jp>
    Reported-by: Niklas Cassel <niklas.cassel@axis.com>
    Tested-by: Niklas Cassel <niklas.cassel@axis.com>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Acked-by: Tejun Heo <tj@kernel.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Fixes: 2e91fa7f6d45 ("cgroup: keep zombies associated with their original cgroups")
    Link: http://lkml.kernel.org/r/20160316152245.GY6344@twins.programming.kicks-ass.net
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    kernel/sched/core.c | 35 ++++++++++++++---------------------
    1 file changed, 14 insertions(+), 21 deletions(-)

    --- a/kernel/sched/core.c
    +++ b/kernel/sched/core.c
    @@ -7693,7 +7693,7 @@ void set_curr_task(int cpu, struct task_
    /* task_group_lock serializes the addition/removal of task groups */
    static DEFINE_SPINLOCK(task_group_lock);

    -static void free_sched_group(struct task_group *tg)
    +static void sched_free_group(struct task_group *tg)
    {
    free_fair_sched_group(tg);
    free_rt_sched_group(tg);
    @@ -7719,7 +7719,7 @@ struct task_group *sched_create_group(st
    return tg;

    err:
    - free_sched_group(tg);
    + sched_free_group(tg);
    return ERR_PTR(-ENOMEM);
    }

    @@ -7739,17 +7739,16 @@ void sched_online_group(struct task_grou
    }

    /* rcu callback to free various structures associated with a task group */
    -static void free_sched_group_rcu(struct rcu_head *rhp)
    +static void sched_free_group_rcu(struct rcu_head *rhp)
    {
    /* now it should be safe to free those cfs_rqs */
    - free_sched_group(container_of(rhp, struct task_group, rcu));
    + sched_free_group(container_of(rhp, struct task_group, rcu));
    }

    -/* Destroy runqueue etc associated with a task group */
    void sched_destroy_group(struct task_group *tg)
    {
    /* wait for possible concurrent references to cfs_rqs complete */
    - call_rcu(&tg->rcu, free_sched_group_rcu);
    + call_rcu(&tg->rcu, sched_free_group_rcu);
    }

    void sched_offline_group(struct task_group *tg)
    @@ -8210,31 +8209,26 @@ cpu_cgroup_css_alloc(struct cgroup_subsy
    if (IS_ERR(tg))
    return ERR_PTR(-ENOMEM);

    + sched_online_group(tg, parent);
    +
    return &tg->css;
    }

    -static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
    +static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
    {
    struct task_group *tg = css_tg(css);
    - struct task_group *parent = css_tg(css->parent);

    - if (parent)
    - sched_online_group(tg, parent);
    - return 0;
    + sched_offline_group(tg);
    }

    static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
    {
    struct task_group *tg = css_tg(css);

    - sched_destroy_group(tg);
    -}
    -
    -static void cpu_cgroup_css_offline(struct cgroup_subsys_state *css)
    -{
    - struct task_group *tg = css_tg(css);
    -
    - sched_offline_group(tg);
    + /*
    + * Relies on the RCU grace period between css_released() and this.
    + */
    + sched_free_group(tg);
    }

    static void cpu_cgroup_fork(struct task_struct *task, void *private)
    @@ -8594,9 +8588,8 @@ static struct cftype cpu_files[] = {

    struct cgroup_subsys cpu_cgrp_subsys = {
    .css_alloc = cpu_cgroup_css_alloc,
    + .css_released = cpu_cgroup_css_released,
    .css_free = cpu_cgroup_css_free,
    - .css_online = cpu_cgroup_css_online,
    - .css_offline = cpu_cgroup_css_offline,
    .fork = cpu_cgroup_fork,
    .can_attach = cpu_cgroup_can_attach,
    .attach = cpu_cgroup_attach,

    \
     
     \ /
      Last update: 2016-05-03 04:21    [W:4.423 / U:0.884 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site