lkml.org 
[lkml]   [2017]   [Aug]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 17/20] pids: make task_tgid_nr_ns() safe
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

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

    From: Oleg Nesterov <oleg@redhat.com>

    commit dd1c1f2f2028a7b851f701fc6a8ebe39dcb95e7c upstream.

    This was reported many times, and this was even mentioned in commit
    52ee2dfdd4f5 ("pids: refactor vnr/nr_ns helpers to make them safe") but
    somehow nobody bothered to fix the obvious problem: task_tgid_nr_ns() is
    not safe because task->group_leader points to nowhere after the exiting
    task passes exit_notify(), rcu_read_lock() can not help.

    We really need to change __unhash_process() to nullify group_leader,
    parent, and real_parent, but this needs some cleanups. Until then we
    can turn task_tgid_nr_ns() into another user of __task_pid_nr_ns() and
    fix the problem.

    Reported-by: Troy Kensinger <tkensinger@google.com>
    Signed-off-by: Oleg Nesterov <oleg@redhat.com>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    include/linux/pid.h | 4 +++-
    include/linux/sched.h | 50 +++++++++++++++++++++++++++-----------------------
    kernel/pid.c | 11 ++++-------
    3 files changed, 34 insertions(+), 31 deletions(-)

    --- a/include/linux/pid.h
    +++ b/include/linux/pid.h
    @@ -8,7 +8,9 @@ enum pid_type
    PIDTYPE_PID,
    PIDTYPE_PGID,
    PIDTYPE_SID,
    - PIDTYPE_MAX
    + PIDTYPE_MAX,
    + /* only valid to __task_pid_nr_ns() */
    + __PIDTYPE_TGID
    };

    /*
    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -1949,31 +1949,8 @@ static inline pid_t task_tgid_nr(struct
    return tsk->tgid;
    }

    -pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
    -
    -static inline pid_t task_tgid_vnr(struct task_struct *tsk)
    -{
    - return pid_vnr(task_tgid(tsk));
    -}
    -

    static inline int pid_alive(const struct task_struct *p);
    -static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns)
    -{
    - pid_t pid = 0;
    -
    - rcu_read_lock();
    - if (pid_alive(tsk))
    - pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns);
    - rcu_read_unlock();
    -
    - return pid;
    -}
    -
    -static inline pid_t task_ppid_nr(const struct task_struct *tsk)
    -{
    - return task_ppid_nr_ns(tsk, &init_pid_ns);
    -}

    static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk,
    struct pid_namespace *ns)
    @@ -1998,6 +1975,33 @@ static inline pid_t task_session_vnr(str
    return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL);
    }

    +static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
    +{
    + return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns);
    +}
    +
    +static inline pid_t task_tgid_vnr(struct task_struct *tsk)
    +{
    + return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL);
    +}
    +
    +static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns)
    +{
    + pid_t pid = 0;
    +
    + rcu_read_lock();
    + if (pid_alive(tsk))
    + pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns);
    + rcu_read_unlock();
    +
    + return pid;
    +}
    +
    +static inline pid_t task_ppid_nr(const struct task_struct *tsk)
    +{
    + return task_ppid_nr_ns(tsk, &init_pid_ns);
    +}
    +
    /* obsolete, do not use */
    static inline pid_t task_pgrp_nr(struct task_struct *tsk)
    {
    --- a/kernel/pid.c
    +++ b/kernel/pid.c
    @@ -526,8 +526,11 @@ pid_t __task_pid_nr_ns(struct task_struc
    if (!ns)
    ns = task_active_pid_ns(current);
    if (likely(pid_alive(task))) {
    - if (type != PIDTYPE_PID)
    + if (type != PIDTYPE_PID) {
    + if (type == __PIDTYPE_TGID)
    + type = PIDTYPE_PID;
    task = task->group_leader;
    + }
    nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns);
    }
    rcu_read_unlock();
    @@ -536,12 +539,6 @@ pid_t __task_pid_nr_ns(struct task_struc
    }
    EXPORT_SYMBOL(__task_pid_nr_ns);

    -pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
    -{
    - return pid_nr_ns(task_tgid(tsk), ns);
    -}
    -EXPORT_SYMBOL(task_tgid_nr_ns);
    -
    struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
    {
    return ns_of_pid(task_pid(tsk));

    \
     
     \ /
      Last update: 2017-08-22 21:13    [W:3.604 / U:0.596 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site