CRED: Fix get_task_cred() and task_state() to not resurrect dead credentials
[firefly-linux-kernel-4.4.55.git] / kernel / exit.c
index 356d91fa095f8bafff7dbca30121d22d246fb5c4..ceffc67b564ae28eb6b46be67bfcf4f0ab7e8c6a 100644 (file)
 
 static void exit_mm(struct task_struct * tsk);
 
-static void __unhash_process(struct task_struct *p)
+static void __unhash_process(struct task_struct *p, bool group_dead)
 {
        nr_threads--;
        detach_pid(p, PIDTYPE_PID);
-       if (thread_group_leader(p)) {
+       if (group_dead) {
                detach_pid(p, PIDTYPE_PGID);
                detach_pid(p, PIDTYPE_SID);
 
@@ -79,20 +79,17 @@ static void __unhash_process(struct task_struct *p)
 static void __exit_signal(struct task_struct *tsk)
 {
        struct signal_struct *sig = tsk->signal;
+       bool group_dead = thread_group_leader(tsk);
        struct sighand_struct *sighand;
        struct tty_struct *uninitialized_var(tty);
 
-       BUG_ON(!sig);
-       BUG_ON(!atomic_read(&sig->count));
-
        sighand = rcu_dereference_check(tsk->sighand,
                                        rcu_read_lock_held() ||
                                        lockdep_tasklist_lock_is_held());
        spin_lock(&sighand->siglock);
-       atomic_dec(&sig->count);
 
        posix_cpu_timers_exit(tsk);
-       if (thread_group_leader(tsk)) {
+       if (group_dead) {
                posix_cpu_timers_exit_group(tsk);
                tty = sig->tty;
                sig->tty = NULL;
@@ -127,10 +124,10 @@ static void __exit_signal(struct task_struct *tsk)
                sig->oublock += task_io_get_oublock(tsk);
                task_io_accounting_add(&sig->ioac, &tsk->ioac);
                sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
-               sig = NULL; /* Marker for below. */
        }
 
-       __unhash_process(tsk);
+       sig->nr_threads--;
+       __unhash_process(tsk, group_dead);
 
        /*
         * Do this under ->siglock, we can race with another thread
@@ -142,14 +139,8 @@ static void __exit_signal(struct task_struct *tsk)
 
        __cleanup_sighand(sighand);
        clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
-       if (sig) {
+       if (group_dead) {
                flush_sigqueue(&sig->shared_pending);
-               taskstats_tgid_free(sig);
-               /*
-                * Make sure ->signal can't go away under rq->lock,
-                * see account_group_exec_runtime().
-                */
-               task_rq_unlock_wait(tsk);
                tty_kref_put(tty);
        }
 }