Author: mjg
Date: Sun Aug 24 09:02:16 2014
New Revision: 270443
URL: http://svnweb.freebsd.org/changeset/base/270443

Log:
  Properly reparent traced processes when the tracer dies.
  
  Previously they were uncoditionally reparented to init. In effect
  it was possible that tracee was never returned to original parent.
  
  Reviewed by:  kib
  MFC after:    1 week

Modified:
  head/sys/kern/kern_exit.c

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c   Sun Aug 24 08:03:59 2014        (r270442)
+++ head/sys/kern/kern_exit.c   Sun Aug 24 09:02:16 2014        (r270443)
@@ -156,7 +156,8 @@ sys_sys_exit(struct thread *td, struct s
 void
 exit1(struct thread *td, int rv)
 {
-       struct proc *p, *nq, *q;
+       struct proc *p, *nq, *q, *t;
+       struct thread *tdt;
        struct vnode *ttyvp = NULL;
 
        mtx_assert(&Giant, MA_NOTOWNED);
@@ -437,7 +438,9 @@ exit1(struct thread *td, int rv)
        WITNESS_WARN(WARN_PANIC, NULL, "process (pid %d) exiting", p->p_pid);
 
        /*
-        * Reparent all of our children to init.
+        * Reparent all children processes:
+        * - traced ones to the original parent (or init if we are that parent)
+        * - the rest to init
         */
        sx_xlock(&proctree_lock);
        q = LIST_FIRST(&p->p_children);
@@ -446,15 +449,23 @@ exit1(struct thread *td, int rv)
        for (; q != NULL; q = nq) {
                nq = LIST_NEXT(q, p_sibling);
                PROC_LOCK(q);
-               proc_reparent(q, initproc);
                q->p_sigparent = SIGCHLD;
-               /*
-                * Traced processes are killed
-                * since their existence means someone is screwing up.
-                */
-               if (q->p_flag & P_TRACED) {
-                       struct thread *temp;
 
+               if (!(q->p_flag & P_TRACED)) {
+                       proc_reparent(q, initproc);
+               } else {
+                       /*
+                        * Traced processes are killed since their existence
+                        * means someone is screwing up.
+                        */
+                       t = proc_realparent(q);
+                       if (t == p) {
+                               proc_reparent(q, initproc);
+                       } else {
+                               PROC_LOCK(t);
+                               proc_reparent(q, t);
+                               PROC_UNLOCK(t);
+                       }
                        /*
                         * Since q was found on our children list, the
                         * proc_reparent() call moved q to the orphan
@@ -463,8 +474,8 @@ exit1(struct thread *td, int rv)
                         */
                        clear_orphan(q);
                        q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
-                       FOREACH_THREAD_IN_PROC(q, temp)
-                               temp->td_dbgflags &= ~TDB_SUSPEND;
+                       FOREACH_THREAD_IN_PROC(q, tdt)
+                               tdt->td_dbgflags &= ~TDB_SUSPEND;
                        kern_psignal(q, SIGKILL);
                }
                PROC_UNLOCK(q);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to