Index: sys/kern/kern_exit.c =================================================================== --- sys/kern/kern_exit.c +++ sys/kern/kern_exit.c @@ -167,7 +167,7 @@ proc_id_clear(PROC_ID_REAP, p->p_reapsubtree); } -static void +void clear_orphan(struct proc *p) { struct proc *p1; Index: sys/kern/sys_procdesc.c =================================================================== --- sys/kern/sys_procdesc.c +++ sys/kern/sys_procdesc.c @@ -417,6 +417,12 @@ */ p->p_sigparent = SIGCHLD; proc_reparent(p, p->p_reaper, true); + if ((p->p_flag & P_TRACED) == 0) { + proc_reparent(p, p->p_reaper, true); + } else { + clear_orphan(p); + p->p_oppid = p->p_reaper->p_pid; + } if ((pd->pd_flags & PDF_DAEMON) == 0) kern_psignal(p, SIGKILL); PROC_UNLOCK(p); Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -1074,6 +1074,7 @@ void pstats_fork(struct pstats *src, struct pstats *dst); void pstats_free(struct pstats *ps); void reaper_abandon_children(struct proc *p, bool exiting); +void clear_orphan(struct proc *p); int securelevel_ge(struct ucred *cr, int level); int securelevel_gt(struct ucred *cr, int level); void sess_hold(struct session *); Index: tests/sys/kern/ptrace_test.c =================================================================== --- tests/sys/kern/ptrace_test.c +++ tests/sys/kern/ptrace_test.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -3904,6 +3905,60 @@ ATF_REQUIRE(errno == ECHILD); } +/* + * Verify that when the process is traced that it isn't reparent + * to the init process when we close all process descriptors. + */ +ATF_TC(ptrace__proc_reparent); +ATF_TC_HEAD(ptrace__proc_reparent, tc) +{ + + atf_tc_set_md_var(tc, "timeout", "2"); +} +ATF_TC_BODY(ptrace__proc_reparent, tc) +{ + pid_t traced, debuger, wpid; + int pd, status; + + traced = pdfork(&pd, 0); + ATF_REQUIRE(traced >= 0); + if (traced == 0) { + raise(SIGSTOP); + exit(0); + } + ATF_REQUIRE(pd >= 0); + + debuger = fork(); + ATF_REQUIRE(debuger >= 0); + if (debuger == 0) { + /* The traced process is reparented to debuger. */ + ATF_REQUIRE(ptrace(PT_ATTACH, traced, 0, 0) == 0); + wpid = waitpid(traced, &status, 0); + ATF_REQUIRE(wpid == traced); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); + ATF_REQUIRE(close(pd) == 0); + ATF_REQUIRE(ptrace(PT_DETACH, traced, (caddr_t)1, 0) == 0); + + /* We closed pd so we should not have any child. */ + wpid = wait(&status); + ATF_REQUIRE(wpid == -1); + ATF_REQUIRE(errno == ECHILD); + + exit(0); + } + + ATF_REQUIRE(close(pd) == 0); + wpid = waitpid(debuger, &status, 0); + ATF_REQUIRE(wpid == debuger); + ATF_REQUIRE(WEXITSTATUS(status) == 0); + + /* Check if we still have any child. */ + wpid = wait(&status); + ATF_REQUIRE(wpid == -1); + ATF_REQUIRE(errno == ECHILD); +} + ATF_TP_ADD_TCS(tp) { @@ -3965,6 +4020,7 @@ ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread); #endif ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo); + ATF_TP_ADD_TC(tp, ptrace__proc_reparent); return (atf_no_error()); }