lkml.org 
[lkml]   [2017]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 16/26] exit: Fix reporting a ptraced !reparented leader has exited
    When a task exits and uses do_notify_parent to send tsk->exit_signal
    or SIGCHLD this has one of two possible meanings.
    - The ptraced task has exited
    - The thread group has exited

    Linux resolves this ambiguity by preferring the thread group exit
    interpretation if it is possible. As the exit of a thread group
    containing a task is a superset of the exit of a task.

    The code attempts to implement this in it's selection of signal
    before calling do_notify_parent for a ptraced task. Unfortunately
    it fails to properly handle the case when the thread_group is still
    running (but it's leader has exited).

    Fix this for a ptraced child leader by skipping the notification
    instead of changing the exit signal. If we skip sending the signal in
    exit_noitfy, when the last of the other threads are reaped
    release_task will send the signal for us.

    Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
    ---
    kernel/exit.c | 15 +++++----------
    1 file changed, 5 insertions(+), 10 deletions(-)

    diff --git a/kernel/exit.c b/kernel/exit.c
    index 85b34eff8807..72591eb5e361 100644
    --- a/kernel/exit.c
    +++ b/kernel/exit.c
    @@ -639,7 +639,7 @@ static void forget_original_parent(struct task_struct *father,
    */
    static void exit_notify(struct task_struct *tsk, int group_dead)
    {
    - bool autoreap;
    + bool autoreap = true;
    struct task_struct *p, *n;
    LIST_HEAD(dead);

    @@ -649,17 +649,12 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
    if (group_dead)
    kill_orphaned_pgrp(tsk->group_leader, NULL);

    - if (unlikely(tsk->ptrace)) {
    - int sig = thread_group_leader(tsk) &&
    - thread_group_empty(tsk) &&
    - !ptrace_reparented(tsk) ?
    - tsk->exit_signal : SIGCHLD;
    - autoreap = do_notify_parent(tsk, sig);
    - } else if (thread_group_leader(tsk)) {
    + if (thread_group_leader(tsk) && !ptrace_reparented(tsk)) {
    autoreap = thread_group_empty(tsk) &&
    do_notify_parent(tsk, tsk->exit_signal);
    - } else {
    - autoreap = true;
    + }
    + else if (unlikely(tsk->ptrace)) {
    + autoreap = do_notify_parent(tsk, SIGCHLD);
    }

    tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
    --
    2.10.1
    \
     
     \ /
      Last update: 2017-06-12 00:53    [W:2.379 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site