]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - kernel/exit.c
elf_core_dump: use rcu_read_lock() to access ->real_parent
[mirror_ubuntu-zesty-kernel.git] / kernel / exit.c
index 51d1fe3fb7ad5b60666c7f229d6bacd8942479e9..94a9992e6fd9e037921c15a1e8447dd6b3cd8f75 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/tracehook.h>
 #include <linux/fs_struct.h>
 #include <linux/init_task.h>
+#include <linux/perf_counter.h>
 #include <trace/events/sched.h>
 
 #include <asm/uaccess.h>
@@ -154,6 +155,9 @@ static void delayed_put_task_struct(struct rcu_head *rhp)
 {
        struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
 
+#ifdef CONFIG_PERF_COUNTERS
+       WARN_ON_ONCE(tsk->perf_counter_ctxp);
+#endif
        trace_sched_process_free(tsk);
        put_task_struct(tsk);
 }
@@ -170,6 +174,7 @@ repeat:
        atomic_dec(&__task_cred(p)->user->processes);
 
        proc_flush_task(p);
+
        write_lock_irq(&tasklist_lock);
        tracehook_finish_release_task(p);
        __exit_signal(p);
@@ -370,9 +375,8 @@ static void set_special_pids(struct pid *pid)
 }
 
 /*
- * Let kernel threads use this to say that they
- * allow a certain signal (since daemonize() will
- * have disabled all of them by default).
+ * Let kernel threads use this to say that they allow a certain signal.
+ * Must not be used if kthread was cloned with CLONE_SIGHAND.
  */
 int allow_signal(int sig)
 {
@@ -380,14 +384,14 @@ int allow_signal(int sig)
                return -EINVAL;
 
        spin_lock_irq(&current->sighand->siglock);
+       /* This is only needed for daemonize()'ed kthreads */
        sigdelset(&current->blocked, sig);
-       if (!current->mm) {
-               /* Kernel threads handle their own signals.
-                  Let the signal code know it'll be handled, so
-                  that they don't get converted to SIGKILL or
-                  just silently dropped */
-               current->sighand->action[(sig)-1].sa.sa_handler = (void __user *)2;
-       }
+       /*
+        * Kernel threads handle their own signals. Let the signal code
+        * know it'll be handled, so that they don't get converted to
+        * SIGKILL or just silently dropped.
+        */
+       current->sighand->action[(sig)-1].sa.sa_handler = (void __user *)2;
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
        return 0;
@@ -586,7 +590,7 @@ retry:
        /*
         * Search in the siblings
         */
-       list_for_each_entry(c, &p->parent->children, sibling) {
+       list_for_each_entry(c, &p->real_parent->children, sibling) {
                if (c->mm == mm)
                        goto assign_new_owner;
        }
@@ -753,7 +757,7 @@ static void reparent_thread(struct task_struct *father, struct task_struct *p,
        p->exit_signal = SIGCHLD;
 
        /* If it has exited notify the new parent about this child's death. */
-       if (!p->ptrace &&
+       if (!task_ptrace(p) &&
            p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) {
                do_notify_parent(p, p->exit_signal);
                if (task_detached(p)) {
@@ -778,7 +782,7 @@ static void forget_original_parent(struct task_struct *father)
        list_for_each_entry_safe(p, n, &father->children, sibling) {
                p->real_parent = reaper;
                if (p->parent == father) {
-                       BUG_ON(p->ptrace);
+                       BUG_ON(task_ptrace(p));
                        p->parent = p->real_parent;
                }
                reparent_thread(father, p, &dead_children);
@@ -971,16 +975,19 @@ NORET_TYPE void do_exit(long code)
                module_put(tsk->binfmt->module);
 
        proc_exit_connector(tsk);
+
+       /*
+        * Flush inherited counters to the parent - before the parent
+        * gets woken up by child-exit notifications.
+        */
+       perf_counter_exit_task(tsk);
+
        exit_notify(tsk, group_dead);
 #ifdef CONFIG_NUMA
        mpol_put(tsk->mempolicy);
        tsk->mempolicy = NULL;
 #endif
 #ifdef CONFIG_FUTEX
-       /*
-        * This must happen late, after the PID is not
-        * hashed anymore:
-        */
        if (unlikely(!list_empty(&tsk->pi_state_list)))
                exit_pi_state_list(tsk);
        if (unlikely(current->pi_state_cache))
@@ -1184,7 +1191,6 @@ static int wait_task_zombie(struct task_struct *p, int options,
        if (likely(!traced)) {
                struct signal_struct *psig;
                struct signal_struct *sig;
-               struct task_cputime cputime;
 
                /*
                 * The resource counters for the group leader are in its
@@ -1197,26 +1203,23 @@ static int wait_task_zombie(struct task_struct *p, int options,
                 * p->signal fields, because they are only touched by
                 * __exit_signal, which runs with tasklist_lock
                 * write-locked anyway, and so is excluded here.  We do
-                * need to protect the access to p->parent->signal fields,
+                * need to protect the access to parent->signal fields,
                 * as other threads in the parent group can be right
                 * here reaping other children at the same time.
-                *
-                * We use thread_group_cputime() to get times for the thread
-                * group, which consolidates times for all threads in the
-                * group including the group leader.
                 */
-               thread_group_cputime(p, &cputime);
-               spin_lock_irq(&p->parent->sighand->siglock);
-               psig = p->parent->signal;
+               spin_lock_irq(&p->real_parent->sighand->siglock);
+               psig = p->real_parent->signal;
                sig = p->signal;
                psig->cutime =
                        cputime_add(psig->cutime,
-                       cputime_add(cputime.utime,
-                                   sig->cutime));
+                       cputime_add(p->utime,
+                       cputime_add(sig->utime,
+                                   sig->cutime)));
                psig->cstime =
                        cputime_add(psig->cstime,
-                       cputime_add(cputime.stime,
-                                   sig->cstime));
+                       cputime_add(p->stime,
+                       cputime_add(sig->stime,
+                                   sig->cstime)));
                psig->cgtime =
                        cputime_add(psig->cgtime,
                        cputime_add(p->gtime,
@@ -1238,7 +1241,7 @@ static int wait_task_zombie(struct task_struct *p, int options,
                        sig->oublock + sig->coublock;
                task_io_accounting_add(&psig->ioac, &p->ioac);
                task_io_accounting_add(&psig->ioac, &sig->ioac);
-               spin_unlock_irq(&p->parent->sighand->siglock);
+               spin_unlock_irq(&p->real_parent->sighand->siglock);
        }
 
        /*
@@ -1475,7 +1478,7 @@ static int wait_consider_task(struct task_struct *parent, int ptrace,
                return 0;
        }
 
-       if (likely(!ptrace) && unlikely(p->ptrace)) {
+       if (likely(!ptrace) && unlikely(task_ptrace(p))) {
                /*
                 * This child is hidden by ptrace.
                 * We aren't allowed to see it now, but eventually we will.