svn commit: r346009 - in head: sys/kern tests/sys/kern

2019-09-03 Thread Mark Johnston
Author: markj
Date: Sun Apr  7 14:26:14 2019
New Revision: 346009
URL: https://svnweb.freebsd.org/changeset/base/346009

Log:
  Set the p_oppid field of orphans when exiting.
  
  Such processes will be reparented to the reaper when the current
  parent is done with them (i.e., ptrace detached), so p_oppid must be
  updated accordingly.
  
  Add a regression test to exercise this code path.  Previously it
  would not be possible to reap an orphan with a stale oppid.
  
  Reviewed by:  kib, mjg
  Tested by:pho
  MFC after:2 weeks
  Sponsored by: The FreeBSD Foundation
  Differential Revision:https://reviews.freebsd.org/D19825

Modified:
  head/sys/kern/kern_exit.c
  head/tests/sys/kern/ptrace_test.c

Modified: head/sys/kern/kern_exit.c
==
--- head/sys/kern/kern_exit.c   Sun Apr  7 14:07:28 2019(r346008)
+++ head/sys/kern/kern_exit.c   Sun Apr  7 14:26:14 2019(r346009)
@@ -543,6 +543,11 @@ exit1(struct thread *td, int rval, int signo)
 */
while ((q = LIST_FIRST(>p_orphans)) != NULL) {
PROC_LOCK(q);
+   KASSERT(q->p_oppid == p->p_pid,
+   ("orphan %p of %p has unexpected oppid %d", q, p,
+   q->p_oppid));
+   q->p_oppid = q->p_reaper->p_pid;
+
/*
 * If we are the real parent of this process
 * but it has been reparented to a debugger, then

Modified: head/tests/sys/kern/ptrace_test.c
==
--- head/tests/sys/kern/ptrace_test.c   Sun Apr  7 14:07:28 2019
(r346008)
+++ head/tests/sys/kern/ptrace_test.c   Sun Apr  7 14:26:14 2019
(r346009)
@@ -452,6 +452,67 @@ ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_d
 }
 
 /*
+ * Make sure that we can collect the exit status of an orphaned process.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
+ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
+{
+   ssize_t n;
+   int cpipe1[2], cpipe2[2], gcpipe[2], status;
+   pid_t child, gchild;
+
+   ATF_REQUIRE(pipe(cpipe1) == 0);
+   ATF_REQUIRE(pipe(cpipe2) == 0);
+   ATF_REQUIRE(pipe(gcpipe) == 0);
+
+   ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
+
+   ATF_REQUIRE((child = fork()) != -1);
+   if (child == 0) {
+   CHILD_REQUIRE((gchild = fork()) != -1);
+   if (gchild == 0) {
+   status = 1;
+   do {
+   n = read(gcpipe[0], , sizeof(status));
+   } while (n == -1 && errno == EINTR);
+   _exit(status);
+   }
+
+   CHILD_REQUIRE(write(cpipe1[1], , sizeof(gchild)) ==
+   sizeof(gchild));
+   CHILD_REQUIRE(read(cpipe2[0], , sizeof(status)) ==
+   sizeof(status));
+   _exit(status);
+   }
+
+   ATF_REQUIRE(read(cpipe1[0], , sizeof(gchild)) == sizeof(gchild));
+
+   ATF_REQUIRE(ptrace(PT_ATTACH, gchild, NULL, 0) == 0);
+
+   status = 0;
+   ATF_REQUIRE(write(cpipe2[1], , sizeof(status)) ==
+   sizeof(status));
+   ATF_REQUIRE(waitpid(child, , 0) == child);
+   ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+
+   status = 0;
+   ATF_REQUIRE(write(gcpipe[1], , sizeof(status)) ==
+   sizeof(status));
+   ATF_REQUIRE(waitpid(gchild, , 0) == gchild);
+   ATF_REQUIRE(WIFSTOPPED(status));
+   ATF_REQUIRE(ptrace(PT_DETACH, gchild, (caddr_t)1, 0) == 0);
+   ATF_REQUIRE(waitpid(gchild, , 0) == gchild);
+   ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+
+   ATF_REQUIRE(close(cpipe1[0]) == 0);
+   ATF_REQUIRE(close(cpipe1[1]) == 0);
+   ATF_REQUIRE(close(cpipe2[0]) == 0);
+   ATF_REQUIRE(close(cpipe2[1]) == 0);
+   ATF_REQUIRE(close(gcpipe[0]) == 0);
+   ATF_REQUIRE(close(gcpipe[1]) == 0);
+}
+
+/*
  * The parent process should always act the same regardless of how the
  * debugger is attached to it.
  */
@@ -3850,6 +3911,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
+   ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);


___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"


svn commit: r346009 - in head: sys/kern tests/sys/kern

2019-04-07 Thread Mark Johnston
Author: markj
Date: Sun Apr  7 14:26:14 2019
New Revision: 346009
URL: https://svnweb.freebsd.org/changeset/base/346009

Log:
  Set the p_oppid field of orphans when exiting.
  
  Such processes will be reparented to the reaper when the current
  parent is done with them (i.e., ptrace detached), so p_oppid must be
  updated accordingly.
  
  Add a regression test to exercise this code path.  Previously it
  would not be possible to reap an orphan with a stale oppid.
  
  Reviewed by:  kib, mjg
  Tested by:pho
  MFC after:2 weeks
  Sponsored by: The FreeBSD Foundation
  Differential Revision:https://reviews.freebsd.org/D19825

Modified:
  head/sys/kern/kern_exit.c
  head/tests/sys/kern/ptrace_test.c

Modified: head/sys/kern/kern_exit.c
==
--- head/sys/kern/kern_exit.c   Sun Apr  7 14:07:28 2019(r346008)
+++ head/sys/kern/kern_exit.c   Sun Apr  7 14:26:14 2019(r346009)
@@ -543,6 +543,11 @@ exit1(struct thread *td, int rval, int signo)
 */
while ((q = LIST_FIRST(>p_orphans)) != NULL) {
PROC_LOCK(q);
+   KASSERT(q->p_oppid == p->p_pid,
+   ("orphan %p of %p has unexpected oppid %d", q, p,
+   q->p_oppid));
+   q->p_oppid = q->p_reaper->p_pid;
+
/*
 * If we are the real parent of this process
 * but it has been reparented to a debugger, then

Modified: head/tests/sys/kern/ptrace_test.c
==
--- head/tests/sys/kern/ptrace_test.c   Sun Apr  7 14:07:28 2019
(r346008)
+++ head/tests/sys/kern/ptrace_test.c   Sun Apr  7 14:26:14 2019
(r346009)
@@ -452,6 +452,67 @@ ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_d
 }
 
 /*
+ * Make sure that we can collect the exit status of an orphaned process.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__parent_exits_before_child);
+ATF_TC_BODY(ptrace__parent_exits_before_child, tc)
+{
+   ssize_t n;
+   int cpipe1[2], cpipe2[2], gcpipe[2], status;
+   pid_t child, gchild;
+
+   ATF_REQUIRE(pipe(cpipe1) == 0);
+   ATF_REQUIRE(pipe(cpipe2) == 0);
+   ATF_REQUIRE(pipe(gcpipe) == 0);
+
+   ATF_REQUIRE(procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) == 0);
+
+   ATF_REQUIRE((child = fork()) != -1);
+   if (child == 0) {
+   CHILD_REQUIRE((gchild = fork()) != -1);
+   if (gchild == 0) {
+   status = 1;
+   do {
+   n = read(gcpipe[0], , sizeof(status));
+   } while (n == -1 && errno == EINTR);
+   _exit(status);
+   }
+
+   CHILD_REQUIRE(write(cpipe1[1], , sizeof(gchild)) ==
+   sizeof(gchild));
+   CHILD_REQUIRE(read(cpipe2[0], , sizeof(status)) ==
+   sizeof(status));
+   _exit(status);
+   }
+
+   ATF_REQUIRE(read(cpipe1[0], , sizeof(gchild)) == sizeof(gchild));
+
+   ATF_REQUIRE(ptrace(PT_ATTACH, gchild, NULL, 0) == 0);
+
+   status = 0;
+   ATF_REQUIRE(write(cpipe2[1], , sizeof(status)) ==
+   sizeof(status));
+   ATF_REQUIRE(waitpid(child, , 0) == child);
+   ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+
+   status = 0;
+   ATF_REQUIRE(write(gcpipe[1], , sizeof(status)) ==
+   sizeof(status));
+   ATF_REQUIRE(waitpid(gchild, , 0) == gchild);
+   ATF_REQUIRE(WIFSTOPPED(status));
+   ATF_REQUIRE(ptrace(PT_DETACH, gchild, (caddr_t)1, 0) == 0);
+   ATF_REQUIRE(waitpid(gchild, , 0) == gchild);
+   ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
+
+   ATF_REQUIRE(close(cpipe1[0]) == 0);
+   ATF_REQUIRE(close(cpipe1[1]) == 0);
+   ATF_REQUIRE(close(cpipe2[0]) == 0);
+   ATF_REQUIRE(close(cpipe2[1]) == 0);
+   ATF_REQUIRE(close(gcpipe[0]) == 0);
+   ATF_REQUIRE(close(gcpipe[1]) == 0);
+}
+
+/*
  * The parent process should always act the same regardless of how the
  * debugger is attached to it.
  */
@@ -3850,6 +3911,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
+   ATF_TP_ADD_TC(tp, ptrace__parent_exits_before_child);
ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"