Date: Tue, 03 Sep 2019 14:06:30 -0000 From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r346009 - in head: sys/kern tests/sys/kern Message-ID: <201904071426.x37EQFVB068638@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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->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], &status, sizeof(status)); + } while (n == -1 && errno == EINTR); + _exit(status); + } + + CHILD_REQUIRE(write(cpipe1[1], &gchild, sizeof(gchild)) == + sizeof(gchild)); + CHILD_REQUIRE(read(cpipe2[0], &status, sizeof(status)) == + sizeof(status)); + _exit(status); + } + + ATF_REQUIRE(read(cpipe1[0], &gchild, sizeof(gchild)) == sizeof(gchild)); + + ATF_REQUIRE(ptrace(PT_ATTACH, gchild, NULL, 0) == 0); + + status = 0; + ATF_REQUIRE(write(cpipe2[1], &status, sizeof(status)) == + sizeof(status)); + ATF_REQUIRE(waitpid(child, &status, 0) == child); + ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 0); + + status = 0; + ATF_REQUIRE(write(gcpipe[1], &status, sizeof(status)) == + sizeof(status)); + ATF_REQUIRE(waitpid(gchild, &status, 0) == gchild); + ATF_REQUIRE(WIFSTOPPED(status)); + ATF_REQUIRE(ptrace(PT_DETACH, gchild, (caddr_t)1, 0) == 0); + ATF_REQUIRE(waitpid(gchild, &status, 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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904071426.x37EQFVB068638>