Page MenuHomeFreeBSD

D20362.id57853.diff
No OneTemporary

D20362.id57853.diff

Index: sys/kern/kern_exit.c
===================================================================
--- sys/kern/kern_exit.c
+++ sys/kern/kern_exit.c
@@ -355,6 +355,9 @@
*/
PROC_LOCK(p);
stopprofclock(p);
+ if ((p->p_flag & P_TRACED) != 0) {
+ p->p_flag2 |= P2_EXIT_TRACED;
+ }
p->p_flag &= ~(P_TRACED | P_PPWAIT | P_PPTRACE);
p->p_ptevents = 0;
@@ -524,7 +527,7 @@
*/
clear_orphan(q);
q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
- q->p_flag2 &= ~P2_PTRACE_FSTP;
+ q->p_flag2 &= ~(P2_PTRACE_FSTP | P2_EXIT_TRACED);
q->p_ptevents = 0;
FOREACH_THREAD_IN_PROC(q, tdt) {
tdt->td_dbgflags &= ~(TDB_SUSPEND | TDB_XSIG |
@@ -996,11 +999,15 @@
switch (idtype) {
case P_ALL:
- if (p->p_procdesc != NULL) {
- PROC_UNLOCK(p);
- return (0);
+ if (p->p_procdesc == NULL ||
+ (p->p_pptr == td->td_proc &&
+ ((p->p_flag & P_TRACED) != 0 ||
+ (p->p_flag2 & P2_EXIT_TRACED) != 0))) {
+ break;
}
- break;
+
+ PROC_UNLOCK(p);
+ return (0);
case P_PID:
if (p->p_pid != (pid_t)id) {
PROC_UNLOCK(p);
@@ -1394,6 +1401,12 @@
clear_orphan(child);
if ((child->p_flag & P_TRACED) != 0) {
proc_add_orphan(child, child->p_pptr);
+ } else if ((child->p_flag2 & P2_EXIT_TRACED) != 0) {
+ /*
+ * If process is not traced and it's getting reparent,
+ * we don't allow any more to collect it exit status.
+ */
+ child->p_flag2 &= ~P2_EXIT_TRACED;
}
child->p_pptr = parent;
Index: sys/kern/sys_procdesc.c
===================================================================
--- sys/kern/sys_procdesc.c
+++ sys/kern/sys_procdesc.c
@@ -60,7 +60,6 @@
*
* Open questions:
*
- * - How to handle ptrace(2)?
* - Will we want to add a pidtoprocdesc(2) system call to allow process
* descriptors to be created for processes without pdfork(2)?
*/
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c
+++ sys/kern/sys_process.c
@@ -1116,6 +1116,7 @@
* as an orphan of the debugger.
*/
p->p_flag &= ~(P_TRACED | P_WAITED);
+ p->p_flag2 &= ~P2_EXIT_TRACED;
if (p->p_oppid != p->p_pptr->p_pid) {
PROC_LOCK(p->p_pptr);
sigqueue_take(p->p_ksi);
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -761,6 +761,7 @@
#define P2_ASLR_ENABLE 0x00000040 /* Force enable ASLR. */
#define P2_ASLR_DISABLE 0x00000080 /* Force disable ASLR. */
#define P2_ASLR_IGNSTART 0x00000100 /* Enable ASLR to consume sbrk area. */
+#define P2_EXIT_TRACED 0x00000200 /* The process exited while it was traced. */
/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
Index: tests/sys/kern/ptrace_test.c
===================================================================
--- tests/sys/kern/ptrace_test.c
+++ tests/sys/kern/ptrace_test.c
@@ -3959,6 +3959,103 @@
ATF_REQUIRE(errno == ECHILD);
}
+/*
+ * Ensure that traced processes created with pdfork(2) are visible to
+ * waitid(P_ALL).
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__procdesc_wait_child);
+ATF_TC_BODY(ptrace__procdesc_wait_child, tc)
+{
+ pid_t child, wpid;
+ int pd, status;
+
+ child = pdfork(&pd, 0);
+ ATF_REQUIRE(child >= 0);
+
+ if (child == 0) {
+ trace_me();
+ (void)raise(SIGSTOP);
+ exit(0);
+ }
+
+ wpid = waitpid(child, &status, 0);
+ ATF_REQUIRE(wpid == child);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == child);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == child);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 0);
+
+ ATF_REQUIRE(close(pd) != -1);
+}
+
+/*
+ * Ensure that traced processes created with pdfork(2) are not visible
+ * after returning to parent - waitid(P_ALL).
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__procdesc_reparent_wait_child);
+ATF_TC_BODY(ptrace__procdesc_reparent_wait_child, 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);
+
+ /* Allow process to die. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, traced, (caddr_t)1, 0) == 0);
+ wpid = waitpid(traced, &status, 0);
+ ATF_REQUIRE(wpid == traced);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 0);
+
+ /* Reparent back to the orginal process. */
+ ATF_REQUIRE(close(pd) == 0);
+ exit(0);
+ }
+
+ wpid = waitpid(debuger, &status, 0);
+ ATF_REQUIRE(wpid == debuger);
+ ATF_REQUIRE(WEXITSTATUS(status) == 0);
+
+ /*
+ * We have a child but it has a process descriptori
+ * so we should not be able to collect it process.
+ */
+ wpid = wait(&status);
+ printf("%d %d %d\n", wpid, debuger, traced);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+
+ ATF_REQUIRE(close(pd) == 0);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -4021,6 +4118,8 @@
#endif
ATF_TP_ADD_TC(tp, ptrace__PT_LWPINFO_stale_siginfo);
ATF_TP_ADD_TC(tp, ptrace__proc_reparent);
+ ATF_TP_ADD_TC(tp, ptrace__procdesc_wait_child);
+ ATF_TP_ADD_TC(tp, ptrace__procdesc_reparent_wait_child);
return (atf_no_error());
}

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 23, 4:05 PM (9 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32032616
Default Alt Text
D20362.id57853.diff (5 KB)

Event Timeline