Page MenuHomeFreeBSD

D20361.id57897.diff
No OneTemporary

D20361.id57897.diff

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;
@@ -1353,6 +1353,24 @@
goto loop;
}
+void
+proc_add_orphan(struct proc *child, struct proc *parent)
+{
+
+ sx_assert(&proctree_lock, SX_XLOCKED);
+ KASSERT((child->p_flag & P_TRACED) != 0,
+ ("proc_add_orphan: not traced"));
+
+ if (LIST_EMPTY(&parent->p_orphans)) {
+ child->p_treeflag |= P_TREE_FIRST_ORPHAN;
+ LIST_INSERT_HEAD(&parent->p_orphans, child, p_orphan);
+ } else {
+ LIST_INSERT_AFTER(LIST_FIRST(&parent->p_orphans),
+ child, p_orphan);
+ }
+ child->p_treeflag |= P_TREE_ORPHANED;
+}
+
/*
* Make process 'parent' the new parent of process 'child'.
* Must be called with an exclusive hold of proctree lock.
@@ -1373,16 +1391,8 @@
LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
clear_orphan(child);
- if (child->p_flag & P_TRACED) {
- if (LIST_EMPTY(&child->p_pptr->p_orphans)) {
- child->p_treeflag |= P_TREE_FIRST_ORPHAN;
- LIST_INSERT_HEAD(&child->p_pptr->p_orphans, child,
- p_orphan);
- } else {
- LIST_INSERT_AFTER(LIST_FIRST(&child->p_pptr->p_orphans),
- child, p_orphan);
- }
- child->p_treeflag |= P_TREE_ORPHANED;
+ if ((child->p_flag & P_TRACED) != 0) {
+ proc_add_orphan(child, child->p_pptr);
}
child->p_pptr = parent;
Index: sys/kern/sys_procdesc.c
===================================================================
--- sys/kern/sys_procdesc.c
+++ sys/kern/sys_procdesc.c
@@ -416,7 +416,13 @@
* terminate with prejudice.
*/
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;
+ proc_add_orphan(p, p->p_reaper);
+ }
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
@@ -1068,12 +1068,14 @@
struct proc *proc_realparent(struct proc *child);
void proc_reap(struct thread *td, struct proc *p, int *status, int options);
void proc_reparent(struct proc *child, struct proc *newparent, bool set_oppid);
+void proc_add_orphan(struct proc *child, struct proc *parent);
void proc_set_traced(struct proc *p, bool stop);
void proc_wkilled(struct proc *p);
struct pstats *pstats_alloc(void);
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 <sys/file.h>
#include <sys/time.h>
#include <sys/procctl.h>
+#include <sys/procdesc.h>
#include <sys/ptrace.h>
#include <sys/queue.h>
#include <sys/runq.h>
@@ -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());
}

File Metadata

Mime Type
text/plain
Expires
Sat, Feb 22, 11:37 AM (7 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16770669
Default Alt Text
D20361.id57897.diff (4 KB)

Event Timeline