t_ptrace_wait.c revision 1.87
11.88Sjonathan/*	$NetBSD: t_ptrace_wait.c,v 1.87 2019/02/15 04:11:39 kamil Exp $	*/
21.8Scgd
31.1Sderaadt/*-
41.1Sderaadt * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc.
51.3Sglass * All rights reserved.
61.3Sglass *
71.1Sderaadt * Redistribution and use in source and binary forms, with or without
81.1Sderaadt * modification, are permitted provided that the following conditions
91.1Sderaadt * are met:
101.1Sderaadt * 1. Redistributions of source code must retain the above copyright
111.1Sderaadt *    notice, this list of conditions and the following disclaimer.
121.1Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
131.1Sderaadt *    notice, this list of conditions and the following disclaimer in the
141.1Sderaadt *    documentation and/or other materials provided with the distribution.
151.1Sderaadt *
161.1Sderaadt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Sderaadt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Sderaadt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Sderaadt * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Sderaadt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Sderaadt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Sderaadt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Sderaadt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Sderaadt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Sderaadt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Sderaadt * POSSIBILITY OF SUCH DAMAGE.
271.1Sderaadt */
281.1Sderaadt
291.1Sderaadt#include <sys/cdefs.h>
301.1Sderaadt__RCSID("$NetBSD: t_ptrace_wait.c,v 1.87 2019/02/15 04:11:39 kamil Exp $");
311.1Sderaadt
321.1Sderaadt#include <sys/param.h>
331.1Sderaadt#include <sys/types.h>
341.1Sderaadt#include <sys/mman.h>
351.1Sderaadt#include <sys/ptrace.h>
361.1Sderaadt#include <sys/resource.h>
371.1Sderaadt#include <sys/stat.h>
381.1Sderaadt#include <sys/syscall.h>
391.1Sderaadt#include <sys/sysctl.h>
401.1Sderaadt#include <sys/wait.h>
411.3Sglass#include <machine/reg.h>
421.8Scgd#include <elf.h>
431.1Sderaadt#include <err.h>
441.1Sderaadt#include <errno.h>
451.78Sjonathan#include <lwp.h>
461.88Sjonathan#include <pthread.h>
471.82Sthorpej#include <sched.h>
481.85Sjonathan#include <signal.h>
491.86Sjonathan#include <stdint.h>
501.86Sjonathan#include <stdio.h>
511.87Sjonathan#include <stdlib.h>
521.87Sjonathan#include <strings.h>
531.88Sjonathan#include <time.h>
541.84Sthorpej#include <unistd.h>
551.82Sthorpej
561.85Sjonathan#include <atf-c.h>
571.78Sjonathan
581.43Sjonathan#include "h_macros.h"
591.57Smhitch
601.37Sjonathan#include "t_ptrace_wait.h"
611.37Sjonathan#include "msg.h"
621.1Sderaadt
631.1Sderaadt#define PARENT_TO_CHILD(info, fds, msg) \
641.23Sjonathan    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
651.1Sderaadt	sizeof(msg)) == 0)
661.1Sderaadt
671.1Sderaadt#define CHILD_FROM_PARENT(info, fds, msg) \
681.1Sderaadt    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
691.1Sderaadt	sizeof(msg)) == 0)
701.1Sderaadt
711.1Sderaadt#define CHILD_TO_PARENT(info, fds, msg) \
721.1Sderaadt    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
731.1Sderaadt	sizeof(msg)) == 0)
741.46Sjonathan
751.58Sjonathan#define PARENT_FROM_CHILD(info, fds, msg) \
761.58Sjonathan    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
771.58Sjonathan	sizeof(msg)) == 0)
781.78Sjonathan
791.78Sjonathan#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
801.78Sjonathan    strerror(errno))
811.78Sjonathan#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
821.82Sthorpej    "%d(%s) != %d", res, strerror(res), exp)
831.82Sthorpej
841.82Sthorpejstatic int debug = 0;
851.82Sthorpej
861.70Sjonathan#define DPRINTF(a, ...)	do  \
871.70Sjonathan	if (debug) printf(a,  ##__VA_ARGS__); \
881.1Sderaadt    while (/*CONSTCOND*/0)
891.70Sjonathan
901.70Sjonathan/// ----------------------------------------------------------------------------
911.70Sjonathan
921.1Sderaadtstatic void
931.16Sjonathantraceme_raise(int sigval)
941.16Sjonathan{
951.37Sjonathan	const int exitval = 5;
961.37Sjonathan	pid_t child, wpid;
971.69Sjonathan#if defined(TWAIT_HAVE_STATUS)
981.69Sjonathan	int status;
991.77Smhitch#endif
1001.69Sjonathan
1011.69Sjonathan	struct ptrace_siginfo info;
1021.37Sjonathan	memset(&info, 0, sizeof(info));
1031.37Sjonathan
1041.37Sjonathan	DPRINTF("Before forking process PID=%d\n", getpid());
1051.37Sjonathan	SYSCALL_REQUIRE((child = fork()) != -1);
1061.51Sis	if (child == 0) {
1071.37Sjonathan		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1081.39Smhitch		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1091.39Smhitch
1101.16Sjonathan		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1111.53Sjonathan		FORKEE_ASSERT(raise(sigval) == 0);
1121.53Sjonathan
1131.53Sjonathan		switch (sigval) {
1141.53Sjonathan		case SIGKILL:
1151.53Sjonathan			/* NOTREACHED */
1161.53Sjonathan			FORKEE_ASSERTX(0 && "This shall not be reached");
1171.71Sjonathan			__unreachable();
1181.33Sjonathan		default:
1191.33Sjonathan			DPRINTF("Before exiting of the child process\n");
1201.33Sjonathan			_exit(exitval);
1211.23Sjonathan		}
1221.57Smhitch	}
1231.57Smhitch	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1241.57Smhitch
1251.1Sderaadt	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1261.85Sjonathan	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1271.85Sjonathan
1281.85Sjonathan	switch (sigval) {
1291.85Sjonathan	case SIGKILL:
1301.85Sjonathan		validate_status_signaled(status, sigval, 0);
1311.85Sjonathan		break;
1321.22Sjonathan	default:
1331.57Smhitch		validate_status_stopped(status, sigval);
1341.22Sjonathan
1351.72Sjonathan		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1361.72Sjonathan			"child\n");
1371.50Sjonathan		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1381.57Smhitch			sizeof(info)) != -1);
1391.57Smhitch
1401.50Sjonathan		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1411.50Sjonathan		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1421.47Sjonathan			"si_errno=%#x\n",
1431.50Sjonathan			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1441.47Sjonathan			info.psi_siginfo.si_errno);
1451.72Sjonathan
1461.35Sjonathan		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1471.57Smhitch		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1481.50Sjonathan
1491.50Sjonathan		DPRINTF("Before resuming the child process where it left off "
1501.57Smhitch		    "and without signal to be sent\n");
1511.50Sjonathan		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1521.50Sjonathan
1531.50Sjonathan		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.50Sjonathan		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1551.57Smhitch		    child);
1561.57Smhitch		break;
1571.57Smhitch	}
1581.48Sjonathan
1591.47Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1601.50Sjonathan	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1611.47Sjonathan}
1621.57Smhitch
1631.47Sjonathan#define TRACEME_RAISE(test, sig)					\
1641.35SjonathanATF_TC(test);								\
1651.72SjonathanATF_TC_HEAD(test, tc)							\
1661.50Sjonathan{									\
1671.35Sjonathan	atf_tc_set_md_var(tc, "descr",					\
1681.35Sjonathan	    "Verify " #sig " followed by _exit(2) in a child");		\
1691.35Sjonathan}									\
1701.50Sjonathan									\
1711.50SjonathanATF_TC_BODY(test, tc)							\
1721.50Sjonathan{									\
1731.50Sjonathan									\
1741.50Sjonathan	traceme_raise(sig);						\
1751.50Sjonathan}
1761.50Sjonathan
1771.50SjonathanTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1781.50SjonathanTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1791.50SjonathanTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1801.50SjonathanTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1811.50SjonathanTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1821.50SjonathanTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */
1831.50SjonathanTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */
1841.50SjonathanTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */
1851.50SjonathanTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */
1861.50SjonathanTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */
1871.50Sjonathan
1881.50Sjonathan/// ----------------------------------------------------------------------------
1891.50Sjonathan
1901.50Sjonathanstatic void
1911.50Sjonathantraceme_raisesignal_ignored(int sigignored)
1921.50Sjonathan{
1931.50Sjonathan	const int exitval = 5;
1941.50Sjonathan	const int sigval = SIGSTOP;
1951.50Sjonathan	pid_t child, wpid;
1961.50Sjonathan	struct sigaction sa;
1971.50Sjonathan#if defined(TWAIT_HAVE_STATUS)
1981.50Sjonathan	int status;
1991.50Sjonathan#endif
2001.50Sjonathan	struct ptrace_siginfo info;
2011.50Sjonathan
2021.35Sjonathan	memset(&info, 0, sizeof(info));
2031.35Sjonathan
2041.35Sjonathan	DPRINTF("Before forking process PID=%d\n", getpid());
2051.50Sjonathan	SYSCALL_REQUIRE((child = fork()) != -1);
2061.50Sjonathan	if (child == 0) {
2071.50Sjonathan		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2081.50Sjonathan		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2091.50Sjonathan
2101.50Sjonathan		memset(&sa, 0, sizeof(sa));
2111.50Sjonathan		sa.sa_handler = SIG_IGN;
2121.50Sjonathan		sigemptyset(&sa.sa_mask);
2131.57Smhitch		FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1);
2141.50Sjonathan
2151.50Sjonathan		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2161.50Sjonathan		FORKEE_ASSERT(raise(sigval) == 0);
2171.50Sjonathan
2181.50Sjonathan		DPRINTF("Before raising %s from child\n",
2191.50Sjonathan		    strsignal(sigignored));
2201.50Sjonathan		FORKEE_ASSERT(raise(sigignored) == 0);
2211.50Sjonathan
2221.50Sjonathan		DPRINTF("Before exiting of the child process\n");
2231.50Sjonathan		_exit(exitval);
2241.50Sjonathan	}
2251.50Sjonathan	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2261.50Sjonathan
2271.50Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2281.50Sjonathan	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2291.50Sjonathan
2301.50Sjonathan	validate_status_stopped(status, sigval);
2311.50Sjonathan
2321.50Sjonathan	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2331.50Sjonathan	SYSCALL_REQUIRE(
2341.50Sjonathan	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2351.50Sjonathan
2361.50Sjonathan	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2371.35Sjonathan	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2381.72Sjonathan	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2391.35Sjonathan	    info.psi_siginfo.si_errno);
2401.50Sjonathan
2411.50Sjonathan	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2421.50Sjonathan	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2431.1Sderaadt
2441.1Sderaadt	DPRINTF("Before resuming the child process where it left off and "
2451.1Sderaadt	    "without signal to be sent\n");
2461.50Sjonathan	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2471.50Sjonathan
2481.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2491.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2501.50Sjonathan
2511.50Sjonathan	validate_status_stopped(status, sigignored);
2521.50Sjonathan
2531.50Sjonathan	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2541.50Sjonathan	SYSCALL_REQUIRE(
2551.50Sjonathan	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2561.50Sjonathan
2571.50Sjonathan	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2581.50Sjonathan	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2591.50Sjonathan	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2601.57Smhitch	    info.psi_siginfo.si_errno);
2611.50Sjonathan
2621.50Sjonathan	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored);
2631.50Sjonathan	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2641.50Sjonathan
2651.50Sjonathan	DPRINTF("Before resuming the child process where it left off and "
2661.50Sjonathan	    "without signal to be sent\n");
2671.50Sjonathan	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2681.50Sjonathan
2691.50Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2701.50Sjonathan	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2711.50Sjonathan
2721.50Sjonathan	validate_status_exited(status, exitval);
2731.50Sjonathan
2741.50Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2751.50Sjonathan	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2761.50Sjonathan}
2771.57Smhitch
2781.1Sderaadt#define TRACEME_RAISESIGNAL_IGNORED(test, sig)				\
2791.1SderaadtATF_TC(test);								\
2801.1SderaadtATF_TC_HEAD(test, tc)							\
2811.50Sjonathan{									\
2821.50Sjonathan	atf_tc_set_md_var(tc, "descr",					\
2831.50Sjonathan	    "Verify that ignoring (with SIG_IGN) " #sig " in tracee "	\
2841.50Sjonathan	    "does not stop tracer from catching this raised signal");	\
2851.50Sjonathan}									\
2861.50Sjonathan									\
2871.50SjonathanATF_TC_BODY(test, tc)							\
2881.50Sjonathan{									\
2891.57Smhitch									\
2901.50Sjonathan	traceme_raisesignal_ignored(sig);				\
2911.50Sjonathan}
2921.50Sjonathan
2931.50Sjonathan// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
2941.50SjonathanTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */
2951.57SmhitchTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP)  /* hangup */
2961.50SjonathanTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */
2971.50SjonathanTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */
2981.50SjonathanTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */
2991.50SjonathanTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */
3001.50SjonathanTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */
3011.50SjonathanTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */
3021.50Sjonathan
3031.50Sjonathan/// ----------------------------------------------------------------------------
3041.50Sjonathan
3051.50Sjonathanstatic void
3061.50Sjonathantraceme_raisesignal_masked(int sigmasked)
3071.50Sjonathan{
3081.50Sjonathan	const int exitval = 5;
3091.50Sjonathan	const int sigval = SIGSTOP;
3101.50Sjonathan	pid_t child, wpid;
3111.50Sjonathan#if defined(TWAIT_HAVE_STATUS)
3121.57Smhitch	int status;
3131.1Sderaadt#endif
3141.50Sjonathan	sigset_t intmask;
3151.50Sjonathan	struct ptrace_siginfo info;
3161.1Sderaadt
3171.1Sderaadt	memset(&info, 0, sizeof(info));
3181.1Sderaadt
3191.1Sderaadt	DPRINTF("Before forking process PID=%d\n", getpid());
3201.1Sderaadt	SYSCALL_REQUIRE((child = fork()) != -1);
3211.1Sderaadt	if (child == 0) {
3221.1Sderaadt		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3231.1Sderaadt		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3241.1Sderaadt
3251.1Sderaadt		sigemptyset(&intmask);
3261.1Sderaadt		sigaddset(&intmask, sigmasked);
3271.1Sderaadt		sigprocmask(SIG_BLOCK, &intmask, NULL);
3281.1Sderaadt
3291.1Sderaadt		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3301.1Sderaadt		FORKEE_ASSERT(raise(sigval) == 0);
3311.32Sjonathan
3321.32Sjonathan		DPRINTF("Before raising %s breakpoint from child\n",
3331.32Sjonathan		    strsignal(sigmasked));
3341.32Sjonathan		FORKEE_ASSERT(raise(sigmasked) == 0);
3351.32Sjonathan
3361.32Sjonathan		DPRINTF("Before exiting of the child process\n");
3371.32Sjonathan		_exit(exitval);
3381.32Sjonathan	}
3391.32Sjonathan	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3401.32Sjonathan
3411.46Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3421.32Sjonathan	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3431.32Sjonathan
3441.32Sjonathan	validate_status_stopped(status, sigval);
3451.32Sjonathan
3461.32Sjonathan	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3471.32Sjonathan	SYSCALL_REQUIRE(
3481.32Sjonathan	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3491.46Sjonathan
3501.1Sderaadt	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3511.57Smhitch	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3521.1Sderaadt	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3531.1Sderaadt	    info.psi_siginfo.si_errno);
3541.1Sderaadt
3551.1Sderaadt	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3561.1Sderaadt	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3571.1Sderaadt
3581.1Sderaadt	DPRINTF("Before resuming the child process where it left off and "
3591.1Sderaadt	    "without signal to be sent\n");
3601.1Sderaadt	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3611.32Sjonathan
3621.1Sderaadt	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3631.1Sderaadt	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3641.16Sjonathan
3651.22Sjonathan	validate_status_exited(status, exitval);
3661.16Sjonathan
3671.16Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3681.57Smhitch	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3691.69Sjonathan}
3701.69Sjonathan
3711.66Smhitch#define TRACEME_RAISESIGNAL_MASKED(test, sig)				\
3721.66SmhitchATF_TC(test);								\
3731.33SjonathanATF_TC_HEAD(test, tc)							\
3741.33Sjonathan{									\
3751.33Sjonathan	atf_tc_set_md_var(tc, "descr",					\
3761.57Smhitch	    "Verify that masking (with SIG_BLOCK) " #sig " in tracee "	\
3771.33Sjonathan	    "stops tracer from catching this raised signal");		\
3781.33Sjonathan}									\
3791.33Sjonathan									\
3801.16SjonathanATF_TC_BODY(test, tc)							\
3811.57Smhitch{									\
3821.74Smhitch									\
3831.57Smhitch	traceme_raisesignal_masked(sig);				\
3841.22Sjonathan}
3851.22Sjonathan
3861.22Sjonathan// A signal handler for SIGKILL and SIGSTOP cannot be masked.
3871.57SmhitchTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */
3881.57SmhitchTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP)  /* hangup */
3891.22SjonathanTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */
3901.22SjonathanTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */
3911.57SmhitchTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */
3921.57SmhitchTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */
3931.57SmhitchTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */
3941.57SmhitchTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */
3951.57Smhitch
3961.57Smhitch/// ----------------------------------------------------------------------------
3971.57Smhitch
3981.57Smhitchstatic void
3991.57Smhitchtraceme_crash(int sig)
4001.22Sjonathan{
4011.68Sjonathan	pid_t child, wpid;
4021.68Sjonathan#if defined(TWAIT_HAVE_STATUS)
4031.68Sjonathan	int status;
4041.73Sjonathan#endif
4051.56Sjonathan	struct ptrace_siginfo info;
4061.56Sjonathan
4071.56Sjonathan#ifndef PTRACE_ILLEGAL_ASM
4081.16Sjonathan	if (sig == SIGILL)
4091.16Sjonathan		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
4101.22Sjonathan#endif
4111.22Sjonathan
4121.22Sjonathan	memset(&info, 0, sizeof(info));
4131.22Sjonathan
4141.23Sjonathan	DPRINTF("Before forking process PID=%d\n", getpid());
4151.36Sjonathan	SYSCALL_REQUIRE((child = fork()) != -1);
4161.73Sjonathan	if (child == 0) {
4171.16Sjonathan		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4181.28Sjonathan		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4191.28Sjonathan
4201.28Sjonathan		DPRINTF("Before executing a trap\n");
4211.28Sjonathan		switch (sig) {
4221.28Sjonathan		case SIGTRAP:
4231.57Smhitch			trigger_trap();
4241.57Smhitch			break;
4251.57Smhitch		case SIGSEGV:
4261.57Smhitch			trigger_segv();
4271.57Smhitch			break;
4281.57Smhitch		case SIGILL:
4291.57Smhitch			trigger_ill();
4301.57Smhitch			break;
4311.57Smhitch		case SIGFPE:
4321.57Smhitch			trigger_fpe();
4331.57Smhitch			break;
4341.57Smhitch		case SIGBUS:
4351.57Smhitch			trigger_bus();
4361.57Smhitch			break;
4371.57Smhitch		default:
4381.57Smhitch			/* NOTREACHED */
4391.57Smhitch			FORKEE_ASSERTX(0 && "This shall not be reached");
4401.28Sjonathan		}
4411.28Sjonathan
4421.57Smhitch		/* NOTREACHED */
4431.57Smhitch		FORKEE_ASSERTX(0 && "This shall not be reached");
4441.57Smhitch	}
4451.57Smhitch	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4461.57Smhitch
4471.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4481.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4491.57Smhitch
4501.57Smhitch	validate_status_stopped(status, sig);
4511.57Smhitch
4521.57Smhitch	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
4531.57Smhitch	SYSCALL_REQUIRE(
4541.57Smhitch	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4551.57Smhitch
4561.57Smhitch	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4571.57Smhitch	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4581.57Smhitch	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4591.57Smhitch	    info.psi_siginfo.si_errno);
4601.57Smhitch
4611.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
4621.57Smhitch	switch (sig) {
4631.57Smhitch	case SIGTRAP:
4641.57Smhitch		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
4651.57Smhitch		break;
4661.57Smhitch	case SIGSEGV:
4671.57Smhitch		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
4681.57Smhitch		break;
4691.57Smhitch	case SIGILL:
4701.57Smhitch		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
4711.57Smhitch		break;
4721.57Smhitch	case SIGFPE:
4731.57Smhitch		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
4741.57Smhitch		break;
4751.57Smhitch	case SIGBUS:
4761.57Smhitch		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
4771.57Smhitch		break;
4781.57Smhitch	}
4791.57Smhitch
4801.57Smhitch	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4811.57Smhitch
4821.1Sderaadt	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4831.63Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4841.1Sderaadt
4851.57Smhitch	validate_status_signaled(status, SIGKILL, 0);
4861.57Smhitch
4871.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4881.57Smhitch	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4891.57Smhitch}
4901.57Smhitch
4911.57Smhitch#define TRACEME_CRASH(test, sig)					\
4921.57SmhitchATF_TC(test);								\
4931.57SmhitchATF_TC_HEAD(test, tc)							\
4941.57Smhitch{									\
4951.57Smhitch	atf_tc_set_md_var(tc, "descr",					\
4961.1Sderaadt	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
4971.57Smhitch}									\
4981.1Sderaadt									\
4991.57SmhitchATF_TC_BODY(test, tc)							\
5001.57Smhitch{									\
5011.57Smhitch									\
5021.57Smhitch	traceme_crash(sig);						\
5031.57Smhitch}
5041.57Smhitch
5051.57SmhitchTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
5061.57SmhitchTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
5071.57SmhitchTRACEME_CRASH(traceme_crash_ill, SIGILL)
5081.57SmhitchTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
5091.57SmhitchTRACEME_CRASH(traceme_crash_bus, SIGBUS)
5101.57Smhitch
5111.57Smhitch/// ----------------------------------------------------------------------------
5121.57Smhitch
5131.57Smhitchstatic void
5141.57Smhitchtraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
5151.82Sthorpej{
5161.82Sthorpej	const int exitval = 5;
5171.82Sthorpej	const int sigval = SIGSTOP;
5181.57Smhitch	pid_t child, wpid;
5191.82Sthorpej	struct sigaction sa;
5201.76Sjonathan#if defined(TWAIT_HAVE_STATUS)
5211.76Sjonathan	int status;
5221.76Sjonathan#endif
5231.57Smhitch	struct ptrace_siginfo info;
5241.57Smhitch
5251.57Smhitch	memset(&info, 0, sizeof(info));
5261.57Smhitch
5271.57Smhitch	DPRINTF("Before forking process PID=%d\n", getpid());
5281.57Smhitch	SYSCALL_REQUIRE((child = fork()) != -1);
5291.57Smhitch	if (child == 0) {
5301.57Smhitch		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5311.57Smhitch		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5321.57Smhitch
5331.57Smhitch		sa.sa_handler = sah;
5341.57Smhitch		sa.sa_flags = SA_SIGINFO;
5351.57Smhitch		sigemptyset(&sa.sa_mask);
5361.57Smhitch
5371.57Smhitch		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
5381.57Smhitch
5391.57Smhitch		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5401.57Smhitch		FORKEE_ASSERT(raise(sigval) == 0);
5411.57Smhitch
5421.57Smhitch		FORKEE_ASSERT_EQ(*traceme_caught, 1);
5431.57Smhitch
5441.57Smhitch		DPRINTF("Before exiting of the child process\n");
5451.57Smhitch		_exit(exitval);
5461.57Smhitch	}
5471.57Smhitch	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5481.57Smhitch
5491.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5501.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5511.57Smhitch
5521.57Smhitch	validate_status_stopped(status, sigval);
5531.57Smhitch
5541.57Smhitch	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5551.57Smhitch	SYSCALL_REQUIRE(
5561.57Smhitch	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5571.57Smhitch
5581.57Smhitch	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5591.57Smhitch	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5601.57Smhitch	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5611.57Smhitch	    info.psi_siginfo.si_errno);
5621.57Smhitch
5631.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5641.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5651.57Smhitch
5661.57Smhitch	DPRINTF("Before resuming the child process where it left off and with "
5671.57Smhitch	    "signal %s to be sent\n", strsignal(sigsent));
5681.57Smhitch	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5691.57Smhitch
5701.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5711.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5721.57Smhitch
5731.57Smhitch	validate_status_exited(status, exitval);
5741.57Smhitch
5751.57Smhitch	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5761.57Smhitch	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5771.57Smhitch}
5781.57Smhitch
5791.57Smhitch#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
5801.57SmhitchATF_TC(test);								\
5811.57SmhitchATF_TC_HEAD(test, tc)							\
5821.57Smhitch{									\
5831.57Smhitch	atf_tc_set_md_var(tc, "descr",					\
5841.57Smhitch	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
5851.57Smhitch	    "handled correctly and caught by a signal handler");	\
5861.57Smhitch}									\
5871.57Smhitch									\
5881.57Smhitchstatic int test##_caught = 0;						\
5891.57Smhitch									\
5901.57Smhitchstatic void								\
5911.57Smhitchtest##_sighandler(int arg)						\
5921.57Smhitch{									\
5931.57Smhitch	FORKEE_ASSERT_EQ(arg, sig);					\
5941.57Smhitch									\
5951.57Smhitch	++ test##_caught;						\
5961.57Smhitch}									\
5971.57Smhitch									\
5981.57SmhitchATF_TC_BODY(test, tc)							\
5991.57Smhitch{									\
6001.57Smhitch									\
6011.57Smhitch	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
6021.57Smhitch}
6031.57Smhitch
6041.57Smhitch// A signal handler for SIGKILL and SIGSTOP cannot be registered.
6051.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
6061.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
6071.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
6081.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */
6091.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */
6101.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */
6111.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */
6121.57SmhitchTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */
6131.57Smhitch
6141.57Smhitch/// ----------------------------------------------------------------------------
6151.57Smhitch
6161.57Smhitchstatic void
6171.57Smhitchtraceme_sendsignal_masked(int sigsent)
6181.57Smhitch{
6191.57Smhitch	const int exitval = 5;
6201.57Smhitch	const int sigval = SIGSTOP;
6211.57Smhitch	pid_t child, wpid;
6221.57Smhitch	sigset_t set;
6231.57Smhitch#if defined(TWAIT_HAVE_STATUS)
6241.57Smhitch	int status;
6251.57Smhitch#endif
6261.57Smhitch	struct ptrace_siginfo info;
6271.57Smhitch
6281.57Smhitch	memset(&info, 0, sizeof(info));
6291.57Smhitch
6301.57Smhitch	DPRINTF("Before forking process PID=%d\n", getpid());
6311.57Smhitch	SYSCALL_REQUIRE((child = fork()) != -1);
6321.57Smhitch	if (child == 0) {
6331.57Smhitch		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
6341.57Smhitch		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
6351.57Smhitch
6361.57Smhitch		sigemptyset(&set);
6371.57Smhitch		sigaddset(&set, sigsent);
6381.57Smhitch		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
6391.57Smhitch
6401.65Sjonathan		DPRINTF("Before raising %s from child\n", strsignal(sigval));
6411.57Smhitch		FORKEE_ASSERT(raise(sigval) == 0);
6421.65Sjonathan
6431.57Smhitch		_exit(exitval);
6441.57Smhitch	}
6451.57Smhitch	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6461.57Smhitch
6471.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6481.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6491.57Smhitch
6501.57Smhitch	validate_status_stopped(status, sigval);
6511.57Smhitch
6521.57Smhitch	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6531.57Smhitch	SYSCALL_REQUIRE(
6541.57Smhitch	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6551.57Smhitch
6561.57Smhitch	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6571.57Smhitch	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6581.57Smhitch	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6591.57Smhitch	    info.psi_siginfo.si_errno);
6601.57Smhitch
6611.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6621.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6631.1Sderaadt
6641.57Smhitch	DPRINTF("Before resuming the child process where it left off and with "
6651.1Sderaadt	    "signal %s to be sent\n", strsignal(sigsent));
6661.1Sderaadt	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6671.57Smhitch
6681.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6691.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6701.57Smhitch
6711.57Smhitch	validate_status_exited(status, exitval);
6721.57Smhitch
6731.1Sderaadt	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6741.1Sderaadt	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6751.1Sderaadt}
6761.1Sderaadt
6771.82Sthorpej#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
6781.82SthorpejATF_TC(test);								\
6791.82SthorpejATF_TC_HEAD(test, tc)							\
6801.1Sderaadt{									\
6811.82Sthorpej	atf_tc_set_md_var(tc, "descr",					\
6821.57Smhitch	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
6831.57Smhitch	    "handled correctly and the signal is masked by SIG_BLOCK");	\
6841.1Sderaadt}									\
6851.1Sderaadt									\
6861.1SderaadtATF_TC_BODY(test, tc)							\
6871.1Sderaadt{									\
6881.60Sjonathan									\
6891.65Sjonathan	traceme_sendsignal_masked(sig);					\
6901.1Sderaadt}
6911.1Sderaadt
6921.57Smhitch// A signal handler for SIGKILL and SIGSTOP cannot be masked.
6931.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
6941.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
6951.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
6961.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */
6971.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */
6981.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */
6991.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */
7001.57SmhitchTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */
7011.57Smhitch
7021.57Smhitch/// ----------------------------------------------------------------------------
7031.57Smhitch
7041.57Smhitchstatic void
7051.57Smhitchtraceme_sendsignal_ignored(int sigsent)
7061.57Smhitch{
7071.57Smhitch	const int exitval = 5;
7081.57Smhitch	const int sigval = SIGSTOP;
7091.57Smhitch	pid_t child, wpid;
7101.67Smhitch	struct sigaction sa;
7111.57Smhitch#if defined(TWAIT_HAVE_STATUS)
7121.57Smhitch	int status;
7131.1Sderaadt#endif
7141.57Smhitch	struct ptrace_siginfo info;
7151.57Smhitch
7161.57Smhitch	memset(&info, 0, sizeof(info));
7171.57Smhitch
7181.1Sderaadt	DPRINTF("Before forking process PID=%d\n", getpid());
7191.57Smhitch	SYSCALL_REQUIRE((child = fork()) != -1);
7201.1Sderaadt	if (child == 0) {
7211.60Sjonathan		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7221.57Smhitch
7231.57Smhitch		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7241.60Sjonathan
7251.1Sderaadt		memset(&sa, 0, sizeof(sa));
7261.1Sderaadt		sa.sa_handler = SIG_IGN;
7271.57Smhitch		sigemptyset(&sa.sa_mask);
7281.1Sderaadt		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
7291.60Sjonathan
7301.1Sderaadt		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7311.57Smhitch		FORKEE_ASSERT(raise(sigval) == 0);
7321.57Smhitch
7331.57Smhitch		_exit(exitval);
7341.1Sderaadt	}
7351.3Sglass	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7361.1Sderaadt
7371.1Sderaadt	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7381.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7391.1Sderaadt
7401.1Sderaadt	validate_status_stopped(status, sigval);
7411.57Smhitch
7421.1Sderaadt	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
7431.57Smhitch	SYSCALL_REQUIRE(
7441.1Sderaadt	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
7451.1Sderaadt
7461.57Smhitch	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
7471.57Smhitch	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
7481.57Smhitch	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
7491.57Smhitch	    info.psi_siginfo.si_errno);
7501.57Smhitch
7511.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
7521.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
7531.57Smhitch
7541.57Smhitch	DPRINTF("Before resuming the child process where it left off and with "
7551.3Sglass	    "signal %s to be sent\n", strsignal(sigsent));
7561.60Sjonathan	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
7571.57Smhitch
7581.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7591.60Sjonathan	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7601.3Sglass
7611.1Sderaadt	validate_status_exited(status, exitval);
7621.57Smhitch
7631.1Sderaadt	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
7641.60Sjonathan	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
7651.3Sglass}
7661.57Smhitch
7671.64Sjonathan#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
7681.57SmhitchATF_TC(test);								\
7691.57SmhitchATF_TC_HEAD(test, tc)							\
7701.1Sderaadt{									\
7711.3Sglass	atf_tc_set_md_var(tc, "descr",					\
7721.1Sderaadt	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
7731.57Smhitch	    "handled correctly and the signal is masked by SIG_IGN");	\
7741.57Smhitch}									\
7751.1Sderaadt									\
7761.1SderaadtATF_TC_BODY(test, tc)							\
7771.57Smhitch{									\
7781.57Smhitch									\
7791.57Smhitch	traceme_sendsignal_ignored(sig);				\
7801.1Sderaadt}
7811.1Sderaadt
7821.1Sderaadt// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
7831.57SmhitchTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
7841.57SmhitchTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
7851.57SmhitchTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
7861.1SderaadtTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */
7871.1SderaadtTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */
7881.1SderaadtTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */
7891.1SderaadtTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */
7901.74SmhitchTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */
7911.57Smhitch
7921.1Sderaadt/// ----------------------------------------------------------------------------
7931.74Smhitch
7941.57Smhitchstatic void
7951.57Smhitchtraceme_sendsignal_simple(int sigsent)
7961.57Smhitch{
7971.57Smhitch	const int sigval = SIGSTOP;
7981.1Sderaadt	int exitval = 0;
7991.1Sderaadt	pid_t child, wpid;
8001.57Smhitch#if defined(TWAIT_HAVE_STATUS)
8011.1Sderaadt	int status;
8021.1Sderaadt	int expect_core;
8031.57Smhitch
8041.1Sderaadt	switch (sigsent) {
8051.57Smhitch	case SIGABRT:
8061.57Smhitch	case SIGTRAP:
8071.57Smhitch	case SIGBUS:
8081.1Sderaadt	case SIGILL:
8091.1Sderaadt	case SIGFPE:
8101.3Sglass	case SIGSEGV:
8111.3Sglass		expect_core = 1;
8121.57Smhitch		break;
8131.82Sthorpej	default:
8141.82Sthorpej		expect_core = 0;
8151.82Sthorpej		break;
8161.82Sthorpej	}
8171.82Sthorpej#endif
8181.82Sthorpej	struct ptrace_siginfo info;
8191.82Sthorpej
8201.82Sthorpej	memset(&info, 0, sizeof(info));
8211.1Sderaadt
8221.5Sglass	DPRINTF("Before forking process PID=%d\n", getpid());
8231.57Smhitch	SYSCALL_REQUIRE((child = fork()) != -1);
8241.75Sjonathan	if (child == 0) {
8251.75Sjonathan		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8261.75Sjonathan		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8271.5Sglass
8281.82Sthorpej		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8291.1Sderaadt		FORKEE_ASSERT(raise(sigval) == 0);
8301.1Sderaadt
8311.1Sderaadt		switch (sigsent) {
8321.1Sderaadt		case SIGCONT:
8331.1Sderaadt		case SIGSTOP:
8341.1Sderaadt			_exit(exitval);
8351.1Sderaadt		default:
8361.1Sderaadt			/* NOTREACHED */
8371.1Sderaadt			FORKEE_ASSERTX(0 && "This shall not be reached");
8381.1Sderaadt		}
8391.1Sderaadt	}
8401.1Sderaadt	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8411.1Sderaadt
8421.1Sderaadt	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8431.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8441.57Smhitch
8451.1Sderaadt	validate_status_stopped(status, sigval);
8461.1Sderaadt
8471.1Sderaadt	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
8481.57Smhitch	SYSCALL_REQUIRE(
8491.57Smhitch	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8501.57Smhitch
8511.57Smhitch	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8521.57Smhitch	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8531.57Smhitch	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8541.57Smhitch	    info.psi_siginfo.si_errno);
8551.57Smhitch
8561.57Smhitch	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8571.1Sderaadt	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8581.57Smhitch
8591.57Smhitch	DPRINTF("Before resuming the child process where it left off and with "
8601.57Smhitch	    "signal %s to be sent\n", strsignal(sigsent));
8611.57Smhitch	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
8621.57Smhitch
8631.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8641.82Sthorpej	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8651.82Sthorpej
8661.82Sthorpej	switch (sigsent) {
8671.57Smhitch	case SIGSTOP:
8681.82Sthorpej		validate_status_stopped(status, sigsent);
8691.57Smhitch		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
8701.57Smhitch		    "child\n");
8711.57Smhitch		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
8721.1Sderaadt		    sizeof(info)) != -1);
8731.57Smhitch
8741.57Smhitch		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8751.57Smhitch		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
8761.57Smhitch		    "si_errno=%#x\n",
8771.74Smhitch		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8781.57Smhitch		    info.psi_siginfo.si_errno);
8791.74Smhitch
8801.57Smhitch		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8811.1Sderaadt		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
8821.1Sderaadt
8831.1Sderaadt		DPRINTF("Before resuming the child process where it left off "
8841.1Sderaadt		    "and with signal %s to be sent\n", strsignal(sigsent));
8851.1Sderaadt		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8861.57Smhitch
8871.57Smhitch		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8881.57Smhitch		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
8891.69Sjonathan		    child);
8901.69Sjonathan		/* FALLTHROUGH */
8911.69Sjonathan	case SIGCONT:
8921.69Sjonathan		validate_status_exited(status, exitval);
8931.69Sjonathan		break;
8941.69Sjonathan	default:
8951.69Sjonathan		validate_status_signaled(status, sigsent, expect_core);
8961.69Sjonathan		break;
8971.1Sderaadt	}
8981.1Sderaadt
8991.57Smhitch	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
9001.57Smhitch	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9011.1Sderaadt}
9021.1Sderaadt
9031.57Smhitch#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
9041.1SderaadtATF_TC(test);								\
9051.1SderaadtATF_TC_HEAD(test, tc)							\
9061.1Sderaadt{									\
9071.69Sjonathan	atf_tc_set_md_var(tc, "descr",					\
9081.69Sjonathan	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
9091.69Sjonathan	    "handled correctly in a child without a signal handler");	\
9101.57Smhitch}									\
9111.65Sjonathan									\
9121.57SmhitchATF_TC_BODY(test, tc)							\
9131.1Sderaadt{									\
9141.1Sderaadt									\
9151.57Smhitch	traceme_sendsignal_simple(sig);					\
9161.57Smhitch}
9171.57Smhitch
9181.57SmhitchTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
9191.57SmhitchTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
9201.57SmhitchTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
9211.1SderaadtTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
9221.1SderaadtTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
9231.57SmhitchTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */
9241.82SthorpejTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */
9251.82SthorpejTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */
9261.82SthorpejTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */
9271.82SthorpejTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */
9281.82Sthorpej
9291.82Sthorpej/// ----------------------------------------------------------------------------
9301.82Sthorpej
9311.82SthorpejATF_TC(traceme_pid1_parent);
9321.82SthorpejATF_TC_HEAD(traceme_pid1_parent, tc)
9331.82Sthorpej{
9341.57Smhitch	atf_tc_set_md_var(tc, "descr",
9351.57Smhitch	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
9361.1Sderaadt}
9371.65Sjonathan
9381.57SmhitchATF_TC_BODY(traceme_pid1_parent, tc)
9391.57Smhitch{
9401.57Smhitch	struct msg_fds parent_child;
9411.1Sderaadt	int exitval_child1 = 1, exitval_child2 = 2;
9421.82Sthorpej	pid_t child1, child2, wpid;
9431.82Sthorpej	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
9441.57Smhitch#if defined(TWAIT_HAVE_STATUS)
9451.57Smhitch	int status;
9461.57Smhitch#endif
9471.57Smhitch
9481.57Smhitch	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
9491.57Smhitch
9501.57Smhitch	DPRINTF("Before forking process PID=%d\n", getpid());
9511.57Smhitch	SYSCALL_REQUIRE((child1 = fork()) != -1);
9521.57Smhitch	if (child1 == 0) {
9531.57Smhitch		DPRINTF("Before forking process PID=%d\n", getpid());
9541.57Smhitch		SYSCALL_REQUIRE((child2 = fork()) != -1);
9551.57Smhitch		if (child2 != 0) {
9561.57Smhitch			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
9571.1Sderaadt			    getpid(), child2);
9581.82Sthorpej			_exit(exitval_child1);
9591.69Sjonathan		}
9601.69Sjonathan		CHILD_FROM_PARENT("exit child1", parent_child, msg);
9611.57Smhitch
9621.57Smhitch		DPRINTF("Assert that our parent is PID1 (initproc)\n");
9631.3Sglass		FORKEE_ASSERT_EQ(getppid(), 1);
9641.1Sderaadt
9651.57Smhitch		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9661.57Smhitch		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
9671.57Smhitch		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
9681.1Sderaadt
9691.57Smhitch		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
9701.57Smhitch
9711.1Sderaadt		_exit(exitval_child2);
9721.65Sjonathan	}
9731.57Smhitch	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
9741.57Smhitch
9751.57Smhitch	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9761.57Smhitch	TWAIT_REQUIRE_SUCCESS(
9771.57Smhitch	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
9781.87Sjonathan
9791.1Sderaadt	validate_status_exited(status, exitval_child1);
9801.57Smhitch
9811.57Smhitch	DPRINTF("Notify that child1 is dead\n");
9821.32Sjonathan	PARENT_TO_CHILD("exit child1", parent_child, msg);
9831.57Smhitch
9841.57Smhitch	DPRINTF("Wait for exiting of child2\n");
9851.57Smhitch	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
9861.1Sderaadt}
9871.57Smhitch
9881.57Smhitch/// ----------------------------------------------------------------------------
9891.1Sderaadt
9901.57Smhitchstatic void
9911.57Smhitchtraceme_vfork_raise(int sigval)
9921.57Smhitch{
9931.57Smhitch	const int exitval = 5, exitval_watcher = 10;
9941.57Smhitch	pid_t child, parent, watcher, wpid;
9951.57Smhitch	int rv;
9961.57Smhitch#if defined(TWAIT_HAVE_STATUS)
9971.57Smhitch	int status;
9981.1Sderaadt
9991.57Smhitch	/* volatile workarounds GCC -Werror=clobbered */
10001.79Sveego	volatile int expect_core;
10011.57Smhitch
10021.1Sderaadt	switch (sigval) {
10031.80Swrstuden	case SIGABRT:
10041.87Sjonathan	case SIGTRAP:
10051.80Swrstuden	case SIGBUS:
10061.87Sjonathan	case SIGILL:
10071.80Swrstuden	case SIGFPE:
10081.87Sjonathan	case SIGSEGV:
10091.87Sjonathan		expect_core = 1;
10101.87Sjonathan		break;
10111.87Sjonathan	default:
10121.87Sjonathan		expect_core = 0;
10131.87Sjonathan		break;
10141.87Sjonathan	}
10151.87Sjonathan#endif
10161.87Sjonathan
10171.87Sjonathan	/*
10181.87Sjonathan	 * Spawn a dedicated thread to watch for a stopped child and emit
10191.87Sjonathan	 * the SIGKILL signal to it.
10201.87Sjonathan	 *
10211.87Sjonathan	 * vfork(2) might clobber watcher, this means that it's safer and
10221.87Sjonathan	 * simpler to reparent this process to initproc and forget about it.
10231.80Swrstuden	 */
10241.80Swrstuden	if (sigval == SIGSTOP) {
10251.57Smhitch		parent = getpid();
10261.57Smhitch
10271.57Smhitch		watcher = fork();
10281.57Smhitch		ATF_REQUIRE(watcher != 1);
10291.57Smhitch		if (watcher == 0) {
10301.22Sjonathan			/* Double fork(2) trick to reparent to initproc */
10311.57Smhitch			watcher = fork();
10321.57Smhitch			FORKEE_ASSERT_NEQ(watcher, -1);
10331.57Smhitch			if (watcher != 0)
10341.1Sderaadt				_exit(exitval_watcher);
10351.57Smhitch
10361.85Sjonathan			child = await_stopped_child(parent);
10371.85Sjonathan
10381.85Sjonathan			errno = 0;
10391.85Sjonathan			rv = kill(child, SIGKILL);
10401.85Sjonathan			FORKEE_ASSERT_EQ(rv, 0);
10411.85Sjonathan			FORKEE_ASSERT_EQ(errno, 0);
10421.85Sjonathan
10431.85Sjonathan			/* This exit value will be collected by initproc */
10441.1Sderaadt			_exit(0);
10451.1Sderaadt		}
10461.57Smhitch		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10471.57Smhitch		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
10481.1Sderaadt		    watcher);
10491.1Sderaadt
10501.1Sderaadt		validate_status_exited(status, exitval_watcher);
10511.33Sjonathan
10521.1Sderaadt		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10531.1Sderaadt		TWAIT_REQUIRE_FAILURE(ECHILD,
10541.1Sderaadt		    wpid = TWAIT_GENERIC(watcher, &status, 0));
10551.1Sderaadt	}
10561.1Sderaadt
10571.82Sthorpej	DPRINTF("Before forking process PID=%d\n", getpid());
10581.82Sthorpej	SYSCALL_REQUIRE((child = vfork()) != -1);
10591.82Sthorpej	if (child == 0) {
10601.1Sderaadt		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10611.82Sthorpej		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10621.57Smhitch
10631.33Sjonathan		DPRINTF("Before raising %s from child\n", strsignal(sigval));
10641.57Smhitch		FORKEE_ASSERT(raise(sigval) == 0);
10651.83Sjonathan
10661.83Sjonathan		switch (sigval) {
10671.83Sjonathan		case SIGSTOP:
10681.28Sjonathan		case SIGKILL:
10691.57Smhitch		case SIGABRT:
10701.57Smhitch		case SIGHUP:
10711.57Smhitch		case SIGTRAP:
10721.45Schristos		case SIGBUS:
10731.57Smhitch		case SIGILL:
10741.57Smhitch		case SIGFPE:
10751.1Sderaadt		case SIGSEGV:
10761.83Sjonathan			/* NOTREACHED */
10771.14Sjonathan			FORKEE_ASSERTX(0 && "This shall not be reached");
10781.57Smhitch			__unreachable();
10791.65Sjonathan		default:
10801.65Sjonathan			DPRINTF("Before exiting of the child process\n");
10811.57Smhitch			_exit(exitval);
10821.57Smhitch		}
10831.1Sderaadt	}
10841.82Sthorpej	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10851.82Sthorpej
10861.82Sthorpej	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10871.1Sderaadt	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10881.82Sthorpej
10891.28Sjonathan	switch (sigval) {
10901.1Sderaadt	case SIGKILL:
10911.79Sveego	case SIGABRT:
10921.57Smhitch	case SIGHUP:
10931.57Smhitch	case SIGTRAP:
10941.57Smhitch	case SIGBUS:
10951.80Swrstuden	case SIGILL:
10961.80Swrstuden	case SIGFPE:
10971.80Swrstuden	case SIGSEGV:
10981.1Sderaadt		validate_status_signaled(status, sigval, expect_core);
10991.1Sderaadt		break;
11001.57Smhitch	case SIGSTOP:
11011.1Sderaadt		validate_status_signaled(status, SIGKILL, 0);
11021.1Sderaadt		break;
11031.57Smhitch	case SIGCONT:
11041.87Sjonathan	case SIGTSTP:
11051.87Sjonathan	case SIGTTIN:
11061.87Sjonathan	case SIGTTOU:
11071.1Sderaadt		validate_status_exited(status, exitval);
11081.20Spaulus		break;
11091.57Smhitch	default:
11101.20Spaulus		/* NOTREACHED */
11111.21Sjonathan		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
11121.20Spaulus		break;
11131.57Smhitch	}
11141.65Sjonathan
11151.14Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11161.82Sthorpej	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11171.82Sthorpej}
11181.82Sthorpej
11191.57Smhitch#define TRACEME_VFORK_RAISE(test, sig)					\
11201.82SthorpejATF_TC(test);								\
11211.28SjonathanATF_TC_HEAD(test, tc)							\
11221.14Sjonathan{									\
11231.43Sjonathan	atf_tc_set_md_var(tc, "descr",					\
11241.1Sderaadt	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
11251.1Sderaadt	    "vfork(2)ed child");					\
11261.1Sderaadt}									\
11271.57Smhitch									\
11281.57SmhitchATF_TC_BODY(test, tc)							\
11291.57Smhitch{									\
11301.1Sderaadt									\
11311.22Sjonathan	traceme_vfork_raise(sig);					\
11321.57Smhitch}
11331.1Sderaadt
11341.1SderaadtTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
11351.57SmhitchTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
11361.1SderaadtTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
11371.82SthorpejTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
11381.82SthorpejTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
11391.82SthorpejTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
11401.1SderaadtTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
11411.82SthorpejTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
11421.1SderaadtTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */
11431.3SglassTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */
11441.3SglassTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */
11451.1SderaadtTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */
11461.1SderaadtTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */
11471.57Smhitch
11481.57Smhitch/// ----------------------------------------------------------------------------
11491.1Sderaadt
11501.1Sderaadtstatic void
11511.1Sderaadttraceme_vfork_crash(int sig)
11521.22Sjonathan{
11531.1Sderaadt	pid_t child, wpid;
11541.1Sderaadt#if defined(TWAIT_HAVE_STATUS)
11551.1Sderaadt	int status;
11561.1Sderaadt#endif
11571.1Sderaadt
11581.62Sjonathan#ifndef PTRACE_ILLEGAL_ASM
11591.1Sderaadt	if (sig == SIGILL)
11601.1Sderaadt		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
11611.45Schristos#endif
11621.1Sderaadt
11631.1Sderaadt	DPRINTF("Before forking process PID=%d\n", getpid());
11641.1Sderaadt	SYSCALL_REQUIRE((child = vfork()) != -1);
11651.1Sderaadt	if (child == 0) {
11661.1Sderaadt		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
11671.1Sderaadt		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
11681.1Sderaadt
11691.62Sjonathan		DPRINTF("Before executing a trap\n");
11701.63Smhitch		switch (sig) {
11711.45Schristos		case SIGTRAP:
11721.65Sjonathan			trigger_trap();
11731.1Sderaadt			break;
11741.45Schristos		case SIGSEGV:
11751.1Sderaadt			trigger_segv();
11761.69Sjonathan			break;
11771.1Sderaadt		case SIGILL:
11781.1Sderaadt			trigger_ill();
11791.69Sjonathan			break;
11801.1Sderaadt		case SIGFPE:
11811.1Sderaadt			trigger_fpe();
11821.1Sderaadt			break;
11831.1Sderaadt		case SIGBUS:
11841.46Sjonathan			trigger_bus();
11851.46Sjonathan			break;
11861.46Sjonathan		default:
11871.41Sjonathan			/* NOTREACHED */
11881.41Sjonathan			FORKEE_ASSERTX(0 && "This shall not be reached");
11891.46Sjonathan		}
11901.1Sderaadt
11911.41Sjonathan		/* NOTREACHED */
11921.41Sjonathan		FORKEE_ASSERTX(0 && "This shall not be reached");
11931.22Sjonathan	}
11941.41Sjonathan	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
11951.41Sjonathan
11961.41Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11971.41Sjonathan	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11981.41Sjonathan
11991.41Sjonathan	validate_status_signaled(status, sig, 1);
12001.22Sjonathan
12011.43Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12021.1Sderaadt	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12031.1Sderaadt}
12041.1Sderaadt
12051.34Sjonathan#define TRACEME_VFORK_CRASH(test, sig)					\
12061.1SderaadtATF_TC(test);								\
12071.1SderaadtATF_TC_HEAD(test, tc)							\
12081.1Sderaadt{									\
12091.1Sderaadt	atf_tc_set_md_var(tc, "descr",					\
12101.1Sderaadt	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
12111.1Sderaadt	    "vfork(2)ed child");					\
12121.1Sderaadt}									\
12131.1Sderaadt									\
12141.1SderaadtATF_TC_BODY(test, tc)							\
12151.24Sjonathan{									\
12161.65Sjonathan									\
12171.24Sjonathan	traceme_vfork_crash(sig);					\
12181.46Sjonathan}
12191.1Sderaadt
12201.45SchristosTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
12211.3SglassTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
12221.1SderaadtTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
12231.1SderaadtTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
12241.1SderaadtTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
12251.1Sderaadt
12261.1Sderaadt/// ----------------------------------------------------------------------------
12271.1Sderaadt
12281.1SderaadtATF_TC(traceme_vfork_exec);
12291.1SderaadtATF_TC_HEAD(traceme_vfork_exec, tc)
12301.1Sderaadt{
12311.1Sderaadt	atf_tc_set_md_var(tc, "descr",
12321.1Sderaadt	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
12331.1Sderaadt}
12341.1Sderaadt
12351.1SderaadtATF_TC_BODY(traceme_vfork_exec, tc)
12361.1Sderaadt{
12371.1Sderaadt	const int sigval = SIGTRAP;
12381.1Sderaadt	pid_t child, wpid;
12391.1Sderaadt#if defined(TWAIT_HAVE_STATUS)
12401.1Sderaadt	int status;
12411.1Sderaadt#endif
12421.1Sderaadt	struct ptrace_siginfo info;
12431.34Sjonathan
12441.34Sjonathan	memset(&info, 0, sizeof(info));
12451.34Sjonathan
12461.1Sderaadt	DPRINTF("Before forking process PID=%d\n", getpid());
12471.1Sderaadt	SYSCALL_REQUIRE((child = vfork()) != -1);
12481.1Sderaadt	if (child == 0) {
12491.1Sderaadt		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12501.1Sderaadt		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12511.1Sderaadt
12521.34Sjonathan		DPRINTF("Before calling execve(2) from child\n");
12531.1Sderaadt		execlp("/bin/echo", "/bin/echo", NULL);
12541.34Sjonathan
12551.34Sjonathan		/* NOTREACHED */
12561.34Sjonathan		FORKEE_ASSERTX(0 && "Not reached");
12571.1Sderaadt	}
12581.1Sderaadt	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12591.1Sderaadt
12601.1Sderaadt	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12611.1Sderaadt	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12621.1Sderaadt
12631.1Sderaadt	validate_status_stopped(status, sigval);
12641.1Sderaadt
12651.1Sderaadt	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
12661.1Sderaadt	SYSCALL_REQUIRE(
12671.1Sderaadt	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
12681.1Sderaadt
12691.1Sderaadt	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
12701.1Sderaadt	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
12711.1Sderaadt	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
12721.1Sderaadt	    info.psi_siginfo.si_errno);
12731.1Sderaadt
12741.1Sderaadt	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
12751.34Sjonathan	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
12761.34Sjonathan
12771.1Sderaadt	DPRINTF("Before resuming the child process where it left off and "
12781.1Sderaadt	    "without signal to be sent\n");
12791.1Sderaadt	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12801.1Sderaadt
12811.1Sderaadt	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12821.1Sderaadt	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12831.1Sderaadt
12841.34Sjonathan	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12851.34Sjonathan	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12861.1Sderaadt}
12871.1Sderaadt
12881.1Sderaadt/// ----------------------------------------------------------------------------
12891.1Sderaadt
12901.1Sderaadt#if defined(TWAIT_HAVE_PID)
12911.1Sderaadtstatic void
12921.1Sderaadtunrelated_tracer_sees_crash(int sig)
12931.34Sjonathan{
12941.34Sjonathan	struct msg_fds parent_tracee, parent_tracer;
12951.1Sderaadt	const int exitval = 10;
12961.1Sderaadt	pid_t tracee, tracer, wpid;
12971.1Sderaadt	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
12981.1Sderaadt#if defined(TWAIT_HAVE_STATUS)
12991.1Sderaadt	int status;
13001.1Sderaadt#endif
13011.1Sderaadt	struct ptrace_siginfo info;
13021.34Sjonathan
13031.34Sjonathan#ifndef PTRACE_ILLEGAL_ASM
13041.1Sderaadt	if (sig == SIGILL)
13051.1Sderaadt		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
13061.1Sderaadt#endif
13071.1Sderaadt
13081.1Sderaadt	memset(&info, 0, sizeof(info));
13091.1Sderaadt
13101.1Sderaadt	DPRINTF("Spawn tracee\n");
13111.1Sderaadt	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
13121.1Sderaadt	tracee = atf_utils_fork();
13131.1Sderaadt	if (tracee == 0) {
13141.1Sderaadt		// Wait for parent to let us crash
13151.65Sjonathan		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
13161.1Sderaadt
13171.65Sjonathan		DPRINTF("Before executing a trap\n");
13181.1Sderaadt		switch (sig) {
13191.1Sderaadt		case SIGTRAP:
13201.1Sderaadt			trigger_trap();
13211.1Sderaadt			break;
13221.1Sderaadt		case SIGSEGV:
13231.1Sderaadt			trigger_segv();
13241.1Sderaadt			break;
13251.1Sderaadt		case SIGILL:
13261.1Sderaadt			trigger_ill();
13271.1Sderaadt			break;
13281.1Sderaadt		case SIGFPE:
13291.1Sderaadt			trigger_fpe();
13301.1Sderaadt			break;
13311.1Sderaadt		case SIGBUS:
13321.1Sderaadt			trigger_bus();
13331.1Sderaadt			break;
13341.1Sderaadt		default:
13351.1Sderaadt			/* NOTREACHED */
13361.1Sderaadt			FORKEE_ASSERTX(0 && "This shall not be reached");
13371.45Schristos		}
13381.1Sderaadt
13391.1Sderaadt		/* NOTREACHED */
13401.1Sderaadt		FORKEE_ASSERTX(0 && "This shall not be reached");
13411.1Sderaadt	}
13421.1Sderaadt
13431.1Sderaadt	DPRINTF("Spawn debugger\n");
13441.1Sderaadt	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
13451.1Sderaadt	tracer = atf_utils_fork();
13461.1Sderaadt	if (tracer == 0) {
13471.1Sderaadt		/* Fork again and drop parent to reattach to PID 1 */
13481.22Sjonathan		tracer = atf_utils_fork();
13491.54Sjonathan		if (tracer != 0)
13501.57Smhitch			_exit(exitval);
13511.1Sderaadt
13521.57Smhitch		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
13531.57Smhitch		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
13541.57Smhitch
13551.57Smhitch		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
13561.1Sderaadt		FORKEE_REQUIRE_SUCCESS(
13571.57Smhitch		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13581.45Schristos
13591.1Sderaadt		forkee_status_stopped(status, SIGSTOP);
13601.57Smhitch
13611.1Sderaadt		/* Resume tracee with PT_CONTINUE */
13621.57Smhitch		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
13631.57Smhitch
13641.57Smhitch		/* Inform parent that tracer has attached to tracee */
13651.57Smhitch		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
13661.57Smhitch
13671.1Sderaadt		/* Wait for parent to tell use that tracee should have exited */
13681.1Sderaadt		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
13691.65Sjonathan
13701.57Smhitch		/* Wait for tracee and assert that it exited */
13711.1Sderaadt		FORKEE_REQUIRE_SUCCESS(
13721.1Sderaadt		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13731.57Smhitch
13741.82Sthorpej		validate_status_stopped(status, sig);
13751.82Sthorpej
13761.82Sthorpej		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
13771.1Sderaadt		    "traced process\n");
13781.82Sthorpej		SYSCALL_REQUIRE(
13791.82Sthorpej		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
13801.82Sthorpej
13811.82Sthorpej		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
13821.82Sthorpej		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
13831.82Sthorpej		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
13841.82Sthorpej		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
13851.82Sthorpej
13861.82Sthorpej		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
13871.82Sthorpej		switch (sig) {
13881.82Sthorpej		case SIGTRAP:
13891.1Sderaadt			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
13901.82Sthorpej			break;
13911.1Sderaadt		case SIGSEGV:
13921.57Smhitch			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
13931.57Smhitch			break;
13941.57Smhitch		case SIGILL:
13951.57Smhitch			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
13961.57Smhitch			break;
13971.65Sjonathan		case SIGFPE:
13981.32Sjonathan			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
13991.32Sjonathan			break;
14001.32Sjonathan		case SIGBUS:
14011.57Smhitch			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
14021.57Smhitch			break;
14031.57Smhitch		}
14041.57Smhitch
14051.57Smhitch		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
14061.57Smhitch		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
14071.57Smhitch		TWAIT_REQUIRE_SUCCESS(
14081.57Smhitch		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14091.57Smhitch
14101.57Smhitch		validate_status_signaled(status, SIGKILL, 0);
14111.57Smhitch
14121.57Smhitch		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
14131.57Smhitch		TWAIT_REQUIRE_FAILURE(ECHILD,
14141.57Smhitch		    wpid = TWAIT_GENERIC(tracee, &status, 0));
14151.57Smhitch
14161.57Smhitch		/* Inform parent that tracer is exiting normally */
14171.57Smhitch		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
14181.57Smhitch
14191.57Smhitch		DPRINTF("Before exiting of the tracer process\n");
14201.57Smhitch		_exit(0 /* collect by initproc */);
14211.57Smhitch	}
14221.57Smhitch
14231.57Smhitch	DPRINTF("Wait for the tracer process (direct child) to exit "
14241.57Smhitch	    "calling %s()\n", TWAIT_FNAME);
14251.57Smhitch	TWAIT_REQUIRE_SUCCESS(
14261.57Smhitch	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
14271.32Sjonathan
14281.32Sjonathan	validate_status_exited(status, exitval);
14291.57Smhitch
14301.57Smhitch	DPRINTF("Wait for the non-exited tracee process with %s()\n",
14311.57Smhitch	    TWAIT_FNAME);
14321.57Smhitch	TWAIT_REQUIRE_SUCCESS(
14331.57Smhitch	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
14341.57Smhitch
14351.32Sjonathan	DPRINTF("Wait for the tracer to attach to the tracee\n");
14361.45Schristos	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
14371.32Sjonathan
14381.32Sjonathan	DPRINTF("Resume the tracee and let it crash\n");
14391.32Sjonathan	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
14401.32Sjonathan
14411.32Sjonathan	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
14421.57Smhitch	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
14431.57Smhitch
14441.32Sjonathan	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
14451.57Smhitch	    TWAIT_FNAME);
14461.57Smhitch	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14471.33Sjonathan
14481.57Smhitch	validate_status_signaled(status, SIGKILL, 0);
14491.57Smhitch
14501.1Sderaadt	DPRINTF("Await normal exit of tracer\n");
14511.3Sglass	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
14521.45Schristos
14531.57Smhitch	msg_close(&parent_tracer);
14541.1Sderaadt	msg_close(&parent_tracee);
14551.57Smhitch}
14561.3Sglass
14571.57Smhitch#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
14581.1SderaadtATF_TC(test);								\
14591.1SderaadtATF_TC_HEAD(test, tc)							\
14601.73Sjonathan{									\
14611.22Sjonathan	atf_tc_set_md_var(tc, "descr",					\
14621.1Sderaadt	    "Assert that an unrelated tracer sees crash signal from the " \
14631.56Sjonathan	    "debuggee");						\
14641.1Sderaadt}									\
14651.1Sderaadt									\
14661.56SjonathanATF_TC_BODY(test, tc)							\
14671.69Sjonathan{									\
14681.69Sjonathan									\
14691.1Sderaadt	unrelated_tracer_sees_crash(sig);				\
14701.1Sderaadt}
14711.1Sderaadt
14721.1SderaadtUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
14731.1SderaadtUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
14741.1SderaadtUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
14751.1SderaadtUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
14761.16SjonathanUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
14771.16Sjonathan#endif
14781.69Sjonathan
14791.69Sjonathan/// ----------------------------------------------------------------------------
14801.69Sjonathan
14811.16Sjonathan#if defined(TWAIT_HAVE_PID)
14821.1Sderaadtstatic void
14831.56Sjonathantracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
14841.56Sjonathan                                             bool stopped)
14851.56Sjonathan{
14861.1Sderaadt	/*
14871.16Sjonathan	 * notimeout - disable timeout in await zombie function
14881.69Sjonathan	 * unrelated - attach from unrelated tracer reparented to initproc
14891.16Sjonathan	 * stopped - attach to a stopped process
14901.69Sjonathan	 */
14911.16Sjonathan
14921.16Sjonathan	struct msg_fds parent_tracee, parent_tracer;
14931.69Sjonathan	const int exitval_tracee = 5;
14941.1Sderaadt	const int exitval_tracer = 10;
14951.1Sderaadt	pid_t tracee, tracer, wpid;
14961.1Sderaadt	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
14971.1Sderaadt#if defined(TWAIT_HAVE_STATUS)
14981.16Sjonathan	int status;
14991.71Sjonathan#endif
15001.1Sderaadt
15011.16Sjonathan	/*
15021.1Sderaadt	 * Only a subset of options are supported.
15031.16Sjonathan	 */
15041.16Sjonathan	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
15051.16Sjonathan	            (!notimeout && unrelated && !stopped) ||
15061.16Sjonathan	            (notimeout && !unrelated && !stopped) ||
15071.16Sjonathan	            (!notimeout && unrelated && stopped));
15081.16Sjonathan
15091.17Sjonathan	DPRINTF("Spawn tracee\n");
15101.17Sjonathan	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15111.16Sjonathan	tracee = atf_utils_fork();
15121.16Sjonathan	if (tracee == 0) {
15131.16Sjonathan		if (stopped) {
15141.16Sjonathan			DPRINTF("Stop self PID %d\n", getpid());
15151.16Sjonathan			raise(SIGSTOP);
15161.16Sjonathan		}
15171.16Sjonathan
15181.16Sjonathan		// Wait for parent to let us exit
15191.16Sjonathan		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
15201.16Sjonathan		_exit(exitval_tracee);
15211.35Sjonathan	}
15221.35Sjonathan
15231.35Sjonathan	DPRINTF("Spawn debugger\n");
15241.35Sjonathan	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
15251.35Sjonathan	tracer = atf_utils_fork();
15261.35Sjonathan	if (tracer == 0) {
15271.35Sjonathan		if(unrelated) {
15281.35Sjonathan			/* Fork again and drop parent to reattach to PID 1 */
15291.35Sjonathan			tracer = atf_utils_fork();
15301.43Sjonathan			if (tracer != 0)
15311.42Sjonathan				_exit(exitval_tracer);
15321.50Sjonathan		}
15331.1Sderaadt
15341.35Sjonathan		if (stopped) {
15351.50Sjonathan			DPRINTF("Await for a stopped parent PID %d\n", tracee);
15361.57Smhitch			await_stopped(tracee);
15371.57Smhitch		}
15381.57Smhitch
15391.57Smhitch		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
15401.16Sjonathan		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
15411.16Sjonathan
15421.77Smhitch		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
15431.57Smhitch		FORKEE_REQUIRE_SUCCESS(
15441.16Sjonathan		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
15451.1Sderaadt
15461.71Sjonathan		forkee_status_stopped(status, SIGSTOP);
15471.71Sjonathan
15481.71Sjonathan		/* Resume tracee with PT_CONTINUE */
15491.71Sjonathan		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
15501.71Sjonathan
15511.71Sjonathan		/* Inform parent that tracer has attached to tracee */
15521.71Sjonathan		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
15531.71Sjonathan
15541.71Sjonathan		/* Wait for parent to tell use that tracee should have exited */
15551.71Sjonathan		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
15561.71Sjonathan
15571.77Smhitch		/* Wait for tracee and assert that it exited */
15581.71Sjonathan		FORKEE_REQUIRE_SUCCESS(
15591.71Sjonathan		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
15601.71Sjonathan
15611.42Sjonathan		forkee_status_exited(status, exitval_tracee);
15621.35Sjonathan		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
15631.42Sjonathan
15641.50Sjonathan		DPRINTF("Before exiting of the tracer process\n");
15651.35Sjonathan		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
15661.71Sjonathan	}
15671.50Sjonathan
15681.57Smhitch	if (unrelated) {
15691.57Smhitch		DPRINTF("Wait for the tracer process (direct child) to exit "
15701.57Smhitch		    "calling %s()\n", TWAIT_FNAME);
15711.57Smhitch		TWAIT_REQUIRE_SUCCESS(
15721.35Sjonathan		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
15731.35Sjonathan
15741.77Smhitch		validate_status_exited(status, exitval_tracer);
15751.57Smhitch
15761.35Sjonathan		DPRINTF("Wait for the non-exited tracee process with %s()\n",
15771.35Sjonathan		    TWAIT_FNAME);
15781.71Sjonathan		TWAIT_REQUIRE_SUCCESS(
15791.71Sjonathan		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
15801.71Sjonathan	}
15811.71Sjonathan
15821.71Sjonathan	DPRINTF("Wait for the tracer to attach to the tracee\n");
15831.71Sjonathan	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
15841.71Sjonathan
15851.71Sjonathan	DPRINTF("Resume the tracee and let it exit\n");
15861.71Sjonathan	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
15871.71Sjonathan
15881.71Sjonathan	DPRINTF("Detect that tracee is zombie\n");
15891.77Smhitch	if (notimeout)
15901.71Sjonathan		await_zombie_raw(tracee, 0);
15911.71Sjonathan	else
15921.71Sjonathan		await_zombie(tracee);
15931.42Sjonathan
15941.1Sderaadt	DPRINTF("Assert that there is no status about tracee %d - "
15951.16Sjonathan	    "Tracer must detect zombie first - calling %s()\n", tracee,
15961.16Sjonathan	    TWAIT_FNAME);
15971.16Sjonathan	TWAIT_REQUIRE_SUCCESS(
15981.16Sjonathan	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
15991.16Sjonathan
16001.16Sjonathan	if (unrelated) {
16011.16Sjonathan		DPRINTF("Resume the tracer and let it detect exited tracee\n");
16021.35Sjonathan		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
16031.35Sjonathan	} else {
16041.35Sjonathan		DPRINTF("Tell the tracer child should have exited\n");
16051.35Sjonathan		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
16061.43Sjonathan		DPRINTF("Wait for tracer to finish its job and exit - calling "
16071.50Sjonathan			"%s()\n", TWAIT_FNAME);
16081.50Sjonathan
16091.57Smhitch		DPRINTF("Wait from tracer child to complete waiting for "
16101.57Smhitch			"tracee\n");
16111.57Smhitch		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
16121.50Sjonathan		    tracer);
16131.50Sjonathan
16141.50Sjonathan		validate_status_exited(status, exitval_tracer);
16151.50Sjonathan	}
16161.50Sjonathan
16171.50Sjonathan	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
16181.47Sjonathan	    TWAIT_FNAME);
16191.47Sjonathan	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
16201.47Sjonathan
16211.43Sjonathan	validate_status_exited(status, exitval_tracee);
16221.43Sjonathan
16231.43Sjonathan	msg_close(&parent_tracer);
16241.35Sjonathan	msg_close(&parent_tracee);
16251.43Sjonathan}
16261.35Sjonathan
16271.50SjonathanATF_TC(tracer_sees_terminaton_before_the_parent);
16281.50SjonathanATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
16291.57Smhitch{
16301.50Sjonathan	atf_tc_set_md_var(tc, "descr",
16311.57Smhitch	    "Assert that tracer sees process termination before the parent");
16321.57Smhitch}
16331.50Sjonathan
16341.50SjonathanATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
16351.35Sjonathan{
16361.57Smhitch
16371.50Sjonathan	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
16381.50Sjonathan}
16391.47Sjonathan
16401.47SjonathanATF_TC(tracer_sysctl_lookup_without_duplicates);
16411.47SjonathanATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
16421.42Sjonathan{
16431.35Sjonathan	atf_tc_set_md_var(tc, "descr",
16441.35Sjonathan	    "Assert that await_zombie() in attach1 always finds a single "
16451.57Smhitch	    "process and no other error is reported");
16461.16Sjonathan}
16471.57Smhitch
16481.16SjonathanATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
16491.16Sjonathan{
16501.16Sjonathan	time_t start, end;
16511.1Sderaadt	double diff;
16521.16Sjonathan	unsigned long N = 0;
16531.16Sjonathan
16541.71Sjonathan	/*
16551.71Sjonathan	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
16561.71Sjonathan	 * This test body isn't specific to this race, however it's just good
16571.71Sjonathan	 * enough for this purposes, no need to invent a dedicated code flow.
16581.1Sderaadt	 */
16591.47Sjonathan
16601.47Sjonathan	start = time(NULL);
16611.1Sderaadt	while (true) {
16621.37Sjonathan		DPRINTF("Step: %lu\n", N);
16631.37Sjonathan		tracer_sees_terminaton_before_the_parent_raw(true, false,
16641.37Sjonathan		                                             false);
16651.37Sjonathan		end = time(NULL);
16661.37Sjonathan		diff = difftime(end, start);
16671.37Sjonathan		if (diff >= 5.0)
16681.1Sderaadt			break;
16691.1Sderaadt		++N;
16701.1Sderaadt	}
16711.1Sderaadt	DPRINTF("Iterations: %lu\n", N);
16721.1Sderaadt}
16731.1Sderaadt
16741.1SderaadtATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
16751.1SderaadtATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
16761.16Sjonathan{
16771.16Sjonathan	atf_tc_set_md_var(tc, "descr",
16781.16Sjonathan	    "Assert that tracer sees process termination before the parent");
16791.1Sderaadt}
16801.16Sjonathan
16811.16SjonathanATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
16821.16Sjonathan{
16831.16Sjonathan
16841.16Sjonathan	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
16851.16Sjonathan}
16861.1Sderaadt
16871.16SjonathanATF_TC(tracer_attach_to_unrelated_stopped_process);
16881.16SjonathanATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
16891.16Sjonathan{
16901.16Sjonathan	atf_tc_set_md_var(tc, "descr",
16911.37Sjonathan	    "Assert that tracer can attach to an unrelated stopped process");
16921.16Sjonathan}
16931.37Sjonathan
16941.1SderaadtATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
16951.1Sderaadt{
16961.1Sderaadt
16971.1Sderaadt	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
16981.71Sjonathan}
16991.16Sjonathan#endif
17001.16Sjonathan
17011.1Sderaadt/// ----------------------------------------------------------------------------
17021.1Sderaadt
17031.1Sderaadtstatic void
17041.1Sderaadtparent_attach_to_its_child(bool stopped)
17051.1Sderaadt{
17061.1Sderaadt	struct msg_fds parent_tracee;
17071.1Sderaadt	const int exitval_tracee = 5;
17081.1Sderaadt	pid_t tracee, wpid;
17091.1Sderaadt	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
17101.1Sderaadt#if defined(TWAIT_HAVE_STATUS)
17111.1Sderaadt	int status;
17121.1Sderaadt#endif
17131.1Sderaadt
17141.1Sderaadt	DPRINTF("Spawn tracee\n");
17151.1Sderaadt	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
17161.1Sderaadt	tracee = atf_utils_fork();
17171.1Sderaadt	if (tracee == 0) {
17181.1Sderaadt		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
17191.1Sderaadt		DPRINTF("Parent should now attach to tracee\n");
17201.1Sderaadt
17211.1Sderaadt		if (stopped) {
17221.1Sderaadt			DPRINTF("Stop self PID %d\n", getpid());
17231.1Sderaadt			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
17241.1Sderaadt		}
17251.1Sderaadt
17261.1Sderaadt		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
17271.1Sderaadt		/* Wait for message from the parent */
17281.1Sderaadt		_exit(exitval_tracee);
17291.1Sderaadt	}
17301.1Sderaadt	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
17311.1Sderaadt
17321.1Sderaadt	if (stopped) {
17331.1Sderaadt		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
17341.1Sderaadt		await_stopped(tracee);
17351.1Sderaadt	}
17361.1Sderaadt
17371.1Sderaadt	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
17381.1Sderaadt	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
17391.1Sderaadt
17401.1Sderaadt	DPRINTF("Wait for the stopped tracee process with %s()\n",
17411.1Sderaadt	    TWAIT_FNAME);
17421.1Sderaadt	TWAIT_REQUIRE_SUCCESS(
17431.1Sderaadt	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17441.1Sderaadt
17451.1Sderaadt	validate_status_stopped(status, SIGSTOP);
17461.1Sderaadt
17471.1Sderaadt	DPRINTF("Resume tracee with PT_CONTINUE\n");
17481.16Sjonathan	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
17491.1Sderaadt
17501.1Sderaadt	DPRINTF("Let the tracee exit now\n");
17511.1Sderaadt	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
17521.1Sderaadt
17531.1Sderaadt	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
17541.1Sderaadt	TWAIT_REQUIRE_SUCCESS(
17551.1Sderaadt	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17561.1Sderaadt
17571.1Sderaadt	validate_status_exited(status, exitval_tracee);
17581.1Sderaadt
17591.1Sderaadt	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
17601.1Sderaadt	TWAIT_REQUIRE_FAILURE(ECHILD,
17611.1Sderaadt	    wpid = TWAIT_GENERIC(tracee, &status, 0));
17621.1Sderaadt
17631.1Sderaadt	msg_close(&parent_tracee);
17641.1Sderaadt}
17651.1Sderaadt
17661.1SderaadtATF_TC(parent_attach_to_its_child);
17671.1SderaadtATF_TC_HEAD(parent_attach_to_its_child, tc)
17681.1Sderaadt{
17691.1Sderaadt	atf_tc_set_md_var(tc, "descr",
17701.1Sderaadt	    "Assert that tracer parent can PT_ATTACH to its child");
17711.1Sderaadt}
17721.1Sderaadt
17731.1SderaadtATF_TC_BODY(parent_attach_to_its_child, tc)
17741.1Sderaadt{
17751.1Sderaadt
17761.1Sderaadt	parent_attach_to_its_child(false);
17771.1Sderaadt}
17781.1Sderaadt
17791.1SderaadtATF_TC(parent_attach_to_its_stopped_child);
17801.71SjonathanATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
17811.71Sjonathan{
17821.71Sjonathan	atf_tc_set_md_var(tc, "descr",
17831.71Sjonathan	    "Assert that tracer parent can PT_ATTACH to its stopped child");
17841.71Sjonathan}
17851.1Sderaadt
17861.1SderaadtATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
17871.1Sderaadt{
17881.1Sderaadt
17891.16Sjonathan	parent_attach_to_its_child(true);
17901.16Sjonathan}
17911.1Sderaadt
17921.1Sderaadt/// ----------------------------------------------------------------------------
17931.1Sderaadt
17941.16Sjonathanstatic void
17951.1Sderaadtchild_attach_to_its_parent(bool stopped)
17961.1Sderaadt{
17971.16Sjonathan	struct msg_fds parent_tracee;
17981.16Sjonathan	const int exitval_tracer = 5;
17991.1Sderaadt	pid_t tracer, wpid;
18001.1Sderaadt	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
18011.16Sjonathan#if defined(TWAIT_HAVE_STATUS)
18021.17Sjonathan	int status;
18031.16Sjonathan#endif
18041.16Sjonathan
18051.16Sjonathan	DPRINTF("Spawn tracer\n");
18061.16Sjonathan	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
18071.1Sderaadt	tracer = atf_utils_fork();
18081.1Sderaadt	if (tracer == 0) {
18091.16Sjonathan		/* Wait for message from the parent */
18101.16Sjonathan		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
18111.16Sjonathan
18121.16Sjonathan		if (stopped) {
18131.16Sjonathan			DPRINTF("Await for a stopped parent PID %d\n",
18141.16Sjonathan			        getppid());
18151.16Sjonathan			await_stopped(getppid());
18161.16Sjonathan		}
18171.16Sjonathan
18181.16Sjonathan		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
18191.23Sjonathan		    getppid());
18201.23Sjonathan		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
18211.23Sjonathan
18221.16Sjonathan		DPRINTF("Wait for the stopped parent process with %s()\n",
18231.16Sjonathan		    TWAIT_FNAME);
18241.35Sjonathan		FORKEE_REQUIRE_SUCCESS(
18251.36Sjonathan		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
18261.35Sjonathan
18271.42Sjonathan		forkee_status_stopped(status, SIGSTOP);
18281.42Sjonathan
18291.50Sjonathan		DPRINTF("Resume parent with PT_DETACH\n");
18301.50Sjonathan		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
18311.57Smhitch		    != -1);
18321.50Sjonathan
18331.50Sjonathan		/* Tell parent we are ready */
18341.42Sjonathan		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
18351.35Sjonathan
18361.42Sjonathan		_exit(exitval_tracer);
18371.50Sjonathan	}
18381.50Sjonathan
18391.57Smhitch	DPRINTF("Wait for the tracer to become ready\n");
18401.50Sjonathan	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
18411.50Sjonathan
18421.42Sjonathan	if (stopped) {
18431.35Sjonathan		DPRINTF("Stop self PID %d\n", getpid());
18441.16Sjonathan		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
18451.16Sjonathan	}
18461.16Sjonathan
18471.16Sjonathan	DPRINTF("Allow the tracer to exit now\n");
18481.16Sjonathan	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
18491.16Sjonathan
18501.16Sjonathan	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
18511.16Sjonathan	TWAIT_REQUIRE_SUCCESS(
18521.16Sjonathan	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
18531.16Sjonathan
18541.16Sjonathan	validate_status_exited(status, exitval_tracer);
18551.16Sjonathan
18561.16Sjonathan	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
18571.16Sjonathan	TWAIT_REQUIRE_FAILURE(ECHILD,
18581.77Smhitch	    wpid = TWAIT_GENERIC(tracer, &status, 0));
18591.77Smhitch
18601.77Smhitch	msg_close(&parent_tracee);
18611.77Smhitch}
18621.77Smhitch
18631.16SjonathanATF_TC(child_attach_to_its_parent);
18641.77SmhitchATF_TC_HEAD(child_attach_to_its_parent, tc)
18651.77Smhitch{
18661.77Smhitch	atf_tc_set_md_var(tc, "descr",
18671.77Smhitch	    "Assert that tracer child can PT_ATTACH to its parent");
18681.77Smhitch}
18691.77Smhitch
18701.77SmhitchATF_TC_BODY(child_attach_to_its_parent, tc)
18711.77Smhitch{
18721.16Sjonathan
18731.16Sjonathan	child_attach_to_its_parent(false);
18741.16Sjonathan}
18751.45Schristos
18761.16SjonathanATF_TC(child_attach_to_its_stopped_parent);
18771.16SjonathanATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
18781.16Sjonathan{
18791.1Sderaadt	atf_tc_set_md_var(tc, "descr",
18801.57Smhitch	    "Assert that tracer child can PT_ATTACH to its stopped parent");
18811.66Smhitch}
18821.66Smhitch
18831.68SjonathanATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
18841.68Sjonathan{
18851.66Smhitch	/*
18861.66Smhitch	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
18871.69Sjonathan	 * this causes a pipe (established from atf-run) to be broken.
18881.66Smhitch	 * atf-run uses this mechanism to monitor whether a test is alive.
18891.66Smhitch	 *
18901.69Sjonathan	 * As a workaround spawn this test as a subprocess.
18911.66Smhitch	 */
18921.66Smhitch
18931.66Smhitch	const int exitval = 15;
18941.66Smhitch	pid_t child, wpid;
18951.66Smhitch#if defined(TWAIT_HAVE_STATUS)
18961.66Smhitch	int status;
18971.66Smhitch#endif
18981.66Smhitch
18991.66Smhitch	SYSCALL_REQUIRE((child = fork()) != -1);
19001.66Smhitch	if (child == 0) {
19011.69Sjonathan		child_attach_to_its_parent(true);
19021.66Smhitch		_exit(exitval);
19031.66Smhitch	} else {
19041.69Sjonathan		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19051.66Smhitch		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19061.69Sjonathan
19071.69Sjonathan		validate_status_exited(status, exitval);
19081.69Sjonathan
19091.69Sjonathan		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
19101.69Sjonathan		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19111.69Sjonathan	}
19121.69Sjonathan}
19131.69Sjonathan
19141.69Sjonathan/// ----------------------------------------------------------------------------
19151.66Smhitch
19161.66Smhitch#if defined(TWAIT_HAVE_PID)
19171.66Smhitch
19181.66Smhitchenum tracee_sees_its_original_parent_type {
19191.66Smhitch	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
19201.66Smhitch	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
19211.72Sjonathan	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
19221.66Smhitch};
19231.68Sjonathan
19241.68Sjonathanstatic void
19251.66Smhitchtracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
19261.66Smhitch{
19271.69Sjonathan	struct msg_fds parent_tracer, parent_tracee;
19281.66Smhitch	const int exitval_tracee = 5;
19291.66Smhitch	const int exitval_tracer = 10;
19301.69Sjonathan	pid_t parent, tracee, tracer, wpid;
19311.66Smhitch	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
19321.66Smhitch#if defined(TWAIT_HAVE_STATUS)
19331.66Smhitch	int status;
19341.66Smhitch#endif
19351.66Smhitch	/* sysctl(3) - kinfo_proc2 */
19361.66Smhitch	int name[CTL_MAXNAME];
19371.66Smhitch	struct kinfo_proc2 kp;
19381.66Smhitch	size_t len = sizeof(kp);
19391.66Smhitch	unsigned int namelen;
19401.66Smhitch
19411.69Sjonathan	/* procfs - status  */
19421.66Smhitch	FILE *fp;
19431.66Smhitch	struct stat st;
19441.69Sjonathan	const char *fname = "/proc/curproc/status";
19451.66Smhitch	char s_executable[MAXPATHLEN];
19461.69Sjonathan	int s_pid, s_ppid;
19471.69Sjonathan	int rv;
19481.69Sjonathan
19491.69Sjonathan	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
19501.66Smhitch		SYSCALL_REQUIRE(
19511.66Smhitch		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
19521.66Smhitch		if (rv != 0)
19531.66Smhitch			atf_tc_skip("/proc/curproc/status not found");
19541.72Sjonathan	}
19551.66Smhitch
19561.69Sjonathan	DPRINTF("Spawn tracee\n");
19571.69Sjonathan	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
19581.69Sjonathan	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
19591.66Smhitch	tracee = atf_utils_fork();
19601.66Smhitch	if (tracee == 0) {
19611.66Smhitch		parent = getppid();
19621.66Smhitch
19631.66Smhitch		/* Emit message to the parent */
19641.66Smhitch		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
19651.66Smhitch		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
19661.69Sjonathan
19671.66Smhitch		switch (type) {
19681.66Smhitch		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
19691.66Smhitch			FORKEE_ASSERT_EQ(parent, getppid());
19701.69Sjonathan			break;
19711.66Smhitch		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
19721.66Smhitch			namelen = 0;
19731.66Smhitch			name[namelen++] = CTL_KERN;
1974			name[namelen++] = KERN_PROC2;
1975			name[namelen++] = KERN_PROC_PID;
1976			name[namelen++] = getpid();
1977			name[namelen++] = len;
1978			name[namelen++] = 1;
1979
1980			FORKEE_ASSERT_EQ(
1981			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
1982			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
1983			break;
1984		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
1985			/*
1986			 * Format:
1987			 *  EXECUTABLE PID PPID ...
1988			 */
1989			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
1990			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
1991			FORKEE_ASSERT_EQ(fclose(fp), 0);
1992			FORKEE_ASSERT_EQ(parent, s_ppid);
1993			break;
1994		}
1995
1996		_exit(exitval_tracee);
1997	}
1998	DPRINTF("Wait for child to record its parent identifier (pid)\n");
1999	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
2000
2001	DPRINTF("Spawn debugger\n");
2002	tracer = atf_utils_fork();
2003	if (tracer == 0) {
2004		/* No IPC to communicate with the child */
2005		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
2006		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
2007
2008		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
2009		FORKEE_REQUIRE_SUCCESS(
2010		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
2011
2012		forkee_status_stopped(status, SIGSTOP);
2013
2014		/* Resume tracee with PT_CONTINUE */
2015		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
2016
2017		/* Inform parent that tracer has attached to tracee */
2018		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
2019
2020		/* Wait for parent to tell use that tracee should have exited */
2021		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
2022
2023		/* Wait for tracee and assert that it exited */
2024		FORKEE_REQUIRE_SUCCESS(
2025		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
2026
2027		forkee_status_exited(status, exitval_tracee);
2028
2029		DPRINTF("Before exiting of the tracer process\n");
2030		_exit(exitval_tracer);
2031	}
2032
2033	DPRINTF("Wait for the tracer to attach to the tracee\n");
2034	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
2035
2036	DPRINTF("Resume the tracee and let it exit\n");
2037	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
2038
2039	DPRINTF("Detect that tracee is zombie\n");
2040	await_zombie(tracee);
2041
2042	DPRINTF("Assert that there is no status about tracee - "
2043	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
2044	TWAIT_REQUIRE_SUCCESS(
2045	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
2046
2047	DPRINTF("Tell the tracer child should have exited\n");
2048	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
2049
2050	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
2051	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
2052	    tracer);
2053
2054	validate_status_exited(status, exitval_tracer);
2055
2056	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
2057	    TWAIT_FNAME);
2058	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
2059	    tracee);
2060
2061	validate_status_exited(status, exitval_tracee);
2062
2063	msg_close(&parent_tracer);
2064	msg_close(&parent_tracee);
2065}
2066
2067#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
2068ATF_TC(test);								\
2069ATF_TC_HEAD(test, tc)							\
2070{									\
2071	atf_tc_set_md_var(tc, "descr",					\
2072	    "Assert that tracee sees its original parent when being traced " \
2073	    "(check " descr ")");					\
2074}									\
2075									\
2076ATF_TC_BODY(test, tc)							\
2077{									\
2078									\
2079	tracee_sees_its_original_parent(type);				\
2080}
2081
2082TRACEE_SEES_ITS_ORIGINAL_PARENT(
2083	tracee_sees_its_original_parent_getppid,
2084	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
2085	"getppid(2)");
2086TRACEE_SEES_ITS_ORIGINAL_PARENT(
2087	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
2088	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
2089	"sysctl(3) and kinfo_proc2");
2090TRACEE_SEES_ITS_ORIGINAL_PARENT(
2091	tracee_sees_its_original_parent_procfs_status,
2092	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
2093	"the status file in procfs");
2094#endif
2095
2096/// ----------------------------------------------------------------------------
2097
2098static void
2099eventmask_preserved(int event)
2100{
2101	const int exitval = 5;
2102	const int sigval = SIGSTOP;
2103	pid_t child, wpid;
2104#if defined(TWAIT_HAVE_STATUS)
2105	int status;
2106#endif
2107	ptrace_event_t set_event, get_event;
2108	const int len = sizeof(ptrace_event_t);
2109
2110	DPRINTF("Before forking process PID=%d\n", getpid());
2111	SYSCALL_REQUIRE((child = fork()) != -1);
2112	if (child == 0) {
2113		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2114		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2115
2116		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2117		FORKEE_ASSERT(raise(sigval) == 0);
2118
2119		DPRINTF("Before exiting of the child process\n");
2120		_exit(exitval);
2121	}
2122	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2123
2124	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2125	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2126
2127	validate_status_stopped(status, sigval);
2128
2129	set_event.pe_set_event = event;
2130	SYSCALL_REQUIRE(
2131	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
2132	SYSCALL_REQUIRE(
2133	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
2134	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
2135
2136	DPRINTF("Before resuming the child process where it left off and "
2137	    "without signal to be sent\n");
2138	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2139
2140	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2141	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2142
2143	validate_status_exited(status, exitval);
2144
2145	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2146	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2147}
2148
2149#define EVENTMASK_PRESERVED(test, event)				\
2150ATF_TC(test);								\
2151ATF_TC_HEAD(test, tc)							\
2152{									\
2153	atf_tc_set_md_var(tc, "descr",					\
2154	    "Verify that eventmask " #event " is preserved");		\
2155}									\
2156									\
2157ATF_TC_BODY(test, tc)							\
2158{									\
2159									\
2160	eventmask_preserved(event);					\
2161}
2162
2163EVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
2164EVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
2165EVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
2166EVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
2167EVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
2168EVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
2169
2170/// ----------------------------------------------------------------------------
2171
2172static void
2173fork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
2174    bool trackvforkdone, bool detachchild, bool detachparent)
2175{
2176	const int exitval = 5;
2177	const int exitval2 = 15;
2178	const int sigval = SIGSTOP;
2179	pid_t child, child2 = 0, wpid;
2180#if defined(TWAIT_HAVE_STATUS)
2181	int status;
2182#endif
2183	ptrace_state_t state;
2184	const int slen = sizeof(state);
2185	ptrace_event_t event;
2186	const int elen = sizeof(event);
2187
2188	DPRINTF("Before forking process PID=%d\n", getpid());
2189	SYSCALL_REQUIRE((child = fork()) != -1);
2190	if (child == 0) {
2191		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2192		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2193
2194		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2195		FORKEE_ASSERT(raise(sigval) == 0);
2196
2197		FORKEE_ASSERT((child2 = (fn)()) != -1);
2198
2199		if (child2 == 0)
2200			_exit(exitval2);
2201
2202		FORKEE_REQUIRE_SUCCESS
2203		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
2204
2205		forkee_status_exited(status, exitval2);
2206
2207		DPRINTF("Before exiting of the child process\n");
2208		_exit(exitval);
2209	}
2210	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2211
2212	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2213	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2214
2215	validate_status_stopped(status, sigval);
2216
2217	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
2218	    trackfork ? "|PTRACE_FORK" : "",
2219	    trackvfork ? "|PTRACE_VFORK" : "",
2220	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
2221	event.pe_set_event = 0;
2222	if (trackfork)
2223		event.pe_set_event |= PTRACE_FORK;
2224	if (trackvfork)
2225		event.pe_set_event |= PTRACE_VFORK;
2226	if (trackvforkdone)
2227		event.pe_set_event |= PTRACE_VFORK_DONE;
2228	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
2229
2230	DPRINTF("Before resuming the child process where it left off and "
2231	    "without signal to be sent\n");
2232	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2233
2234#if defined(TWAIT_HAVE_PID)
2235	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
2236		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
2237		    child);
2238		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
2239		    child);
2240
2241		validate_status_stopped(status, SIGTRAP);
2242
2243		SYSCALL_REQUIRE(
2244		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
2245		if (trackfork && fn == fork) {
2246			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
2247			       PTRACE_FORK);
2248		}
2249		if (trackvfork && fn == vfork) {
2250			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
2251			       PTRACE_VFORK);
2252		}
2253
2254		child2 = state.pe_other_pid;
2255		DPRINTF("Reported ptrace event with forkee %d\n", child2);
2256
2257		DPRINTF("Before calling %s() for the forkee %d of the child "
2258		    "%d\n", TWAIT_FNAME, child2, child);
2259		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
2260		    child2);
2261
2262		validate_status_stopped(status, SIGTRAP);
2263
2264		SYSCALL_REQUIRE(
2265		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
2266		if (trackfork && fn == fork) {
2267			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
2268			       PTRACE_FORK);
2269		}
2270		if (trackvfork && fn == vfork) {
2271			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
2272			       PTRACE_VFORK);
2273		}
2274
2275		ATF_REQUIRE_EQ(state.pe_other_pid, child);
2276
2277		DPRINTF("Before resuming the forkee process where it left off "
2278		    "and without signal to be sent\n");
2279		SYSCALL_REQUIRE(
2280		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
2281
2282		DPRINTF("Before resuming the child process where it left off "
2283		    "and without signal to be sent\n");
2284		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2285	}
2286#endif
2287
2288	if (trackvforkdone && fn == vfork) {
2289		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
2290		    child);
2291		TWAIT_REQUIRE_SUCCESS(
2292		    wpid = TWAIT_GENERIC(child, &status, 0), child);
2293
2294		validate_status_stopped(status, SIGTRAP);
2295
2296		SYSCALL_REQUIRE(
2297		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
2298		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
2299
2300		child2 = state.pe_other_pid;
2301		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
2302		    child2);
2303
2304		DPRINTF("Before resuming the child process where it left off "
2305		    "and without signal to be sent\n");
2306		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2307	}
2308
2309#if defined(TWAIT_HAVE_PID)
2310	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
2311		DPRINTF("Before calling %s() for the forkee - expected exited"
2312		    "\n", TWAIT_FNAME);
2313		TWAIT_REQUIRE_SUCCESS(
2314		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
2315
2316		validate_status_exited(status, exitval2);
2317
2318		DPRINTF("Before calling %s() for the forkee - expected no "
2319		    "process\n", TWAIT_FNAME);
2320		TWAIT_REQUIRE_FAILURE(ECHILD,
2321		    wpid = TWAIT_GENERIC(child2, &status, 0));
2322	}
2323#endif
2324
2325	DPRINTF("Before calling %s() for the child - expected stopped "
2326	    "SIGCHLD\n", TWAIT_FNAME);
2327	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2328
2329	validate_status_stopped(status, SIGCHLD);
2330
2331	DPRINTF("Before resuming the child process where it left off and "
2332	    "without signal to be sent\n");
2333	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2334
2335	DPRINTF("Before calling %s() for the child - expected exited\n",
2336	    TWAIT_FNAME);
2337	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2338
2339	validate_status_exited(status, exitval);
2340
2341	DPRINTF("Before calling %s() for the child - expected no process\n",
2342	    TWAIT_FNAME);
2343	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2344}
2345
2346#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
2347ATF_TC(name);								\
2348ATF_TC_HEAD(name, tc)							\
2349{									\
2350	atf_tc_set_md_var(tc, "descr", descr);				\
2351}									\
2352									\
2353ATF_TC_BODY(name, tc)							\
2354{									\
2355									\
2356	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
2357}
2358
2359#define F false
2360#define T true
2361
2362#define F_IF__0(x)
2363#define F_IF__1(x) x
2364#define F_IF__(x,y) F_IF__ ## x (y)
2365#define F_IF_(x,y) F_IF__(x,y)
2366#define F_IF(x,y) F_IF_(x,y)
2367
2368#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
2369	"Verify " #function "(2) called with 0"				\
2370	F_IF(forkbit,"|PTRACE_FORK")					\
2371	F_IF(vforkbit,"|PTRACE_VFORK")					\
2372	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
2373	" in EVENT_MASK."						\
2374	F_IF(dchildbit," Detach child in this test.")			\
2375	F_IF(dparentbit," Detach parent in this test.")
2376
2377FORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
2378#if defined(TWAIT_HAVE_PID)
2379FORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
2380FORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
2381FORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
2382#endif
2383FORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
2384#if defined(TWAIT_HAVE_PID)
2385FORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
2386FORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
2387FORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
2388#endif
2389
2390FORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
2391#if defined(TWAIT_HAVE_PID)
2392FORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
2393FORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
2394FORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
2395#endif
2396FORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
2397#if defined(TWAIT_HAVE_PID)
2398FORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
2399FORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
2400FORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
2401#endif
2402
2403/// ----------------------------------------------------------------------------
2404
2405enum bytes_transfer_type {
2406	BYTES_TRANSFER_DATA,
2407	BYTES_TRANSFER_DATAIO,
2408	BYTES_TRANSFER_TEXT,
2409	BYTES_TRANSFER_TEXTIO,
2410	BYTES_TRANSFER_AUXV
2411};
2412
2413static int __used
2414bytes_transfer_dummy(int a, int b, int c, int d)
2415{
2416	int e, f, g, h;
2417
2418	a *= 4;
2419	b += 3;
2420	c -= 2;
2421	d /= 1;
2422
2423	e = strtol("10", NULL, 10);
2424	f = strtol("20", NULL, 10);
2425	g = strtol("30", NULL, 10);
2426	h = strtol("40", NULL, 10);
2427
2428	return (a + b * c - d) + (e * f - g / h);
2429}
2430
2431static void
2432bytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
2433{
2434	const int exitval = 5;
2435	const int sigval = SIGSTOP;
2436	pid_t child, wpid;
2437	bool skip = false;
2438
2439	int lookup_me = 0;
2440	uint8_t lookup_me8 = 0;
2441	uint16_t lookup_me16 = 0;
2442	uint32_t lookup_me32 = 0;
2443	uint64_t lookup_me64 = 0;
2444
2445	int magic = 0x13579246;
2446	uint8_t magic8 = 0xab;
2447	uint16_t magic16 = 0x1234;
2448	uint32_t magic32 = 0x98765432;
2449	uint64_t magic64 = 0xabcdef0123456789;
2450
2451	struct ptrace_io_desc io;
2452#if defined(TWAIT_HAVE_STATUS)
2453	int status;
2454#endif
2455	/* 513 is just enough, for the purposes of ATF it's good enough */
2456	AuxInfo ai[513], *aip;
2457
2458	ATF_REQUIRE(size < sizeof(ai));
2459
2460	/* Prepare variables for .TEXT transfers */
2461	switch (type) {
2462	case BYTES_TRANSFER_TEXT:
2463		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
2464		break;
2465	case BYTES_TRANSFER_TEXTIO:
2466		switch (size) {
2467		case 8:
2468			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
2469			break;
2470		case 16:
2471			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
2472			break;
2473		case 32:
2474			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
2475			break;
2476		case 64:
2477			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
2478			break;
2479		}
2480		break;
2481	default:
2482		break;
2483	}
2484
2485	/* Prepare variables for PIOD and AUXV transfers */
2486	switch (type) {
2487	case BYTES_TRANSFER_TEXTIO:
2488	case BYTES_TRANSFER_DATAIO:
2489		io.piod_op = operation;
2490		switch (size) {
2491		case 8:
2492			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
2493			               (void *)bytes_transfer_dummy :
2494			               &lookup_me8;
2495			io.piod_addr = &lookup_me8;
2496			io.piod_len = sizeof(lookup_me8);
2497			break;
2498		case 16:
2499			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
2500			               (void *)bytes_transfer_dummy :
2501			               &lookup_me16;
2502			io.piod_addr = &lookup_me16;
2503			io.piod_len = sizeof(lookup_me16);
2504			break;
2505		case 32:
2506			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
2507			               (void *)bytes_transfer_dummy :
2508			               &lookup_me32;
2509			io.piod_addr = &lookup_me32;
2510			io.piod_len = sizeof(lookup_me32);
2511			break;
2512		case 64:
2513			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
2514			               (void *)bytes_transfer_dummy :
2515			               &lookup_me64;
2516			io.piod_addr = &lookup_me64;
2517			io.piod_len = sizeof(lookup_me64);
2518			break;
2519		default:
2520			break;
2521		}
2522		break;
2523	case BYTES_TRANSFER_AUXV:
2524		io.piod_op = operation;
2525		io.piod_offs = 0;
2526		io.piod_addr = ai;
2527		io.piod_len = size;
2528		break;
2529	default:
2530		break;
2531	}
2532
2533	DPRINTF("Before forking process PID=%d\n", getpid());
2534	SYSCALL_REQUIRE((child = fork()) != -1);
2535	if (child == 0) {
2536		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2537		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2538
2539		switch (type) {
2540		case BYTES_TRANSFER_DATA:
2541			switch (operation) {
2542			case PT_READ_D:
2543			case PT_READ_I:
2544				lookup_me = magic;
2545				break;
2546			default:
2547				break;
2548			}
2549			break;
2550		case BYTES_TRANSFER_DATAIO:
2551			switch (operation) {
2552			case PIOD_READ_D:
2553			case PIOD_READ_I:
2554				switch (size) {
2555				case 8:
2556					lookup_me8 = magic8;
2557					break;
2558				case 16:
2559					lookup_me16 = magic16;
2560					break;
2561				case 32:
2562					lookup_me32 = magic32;
2563					break;
2564				case 64:
2565					lookup_me64 = magic64;
2566					break;
2567				default:
2568					break;
2569				}
2570				break;
2571			default:
2572				break;
2573			}
2574		default:
2575			break;
2576		}
2577
2578		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2579		FORKEE_ASSERT(raise(sigval) == 0);
2580
2581		/* Handle PIOD and PT separately as operation values overlap */
2582		switch (type) {
2583		case BYTES_TRANSFER_DATA:
2584			switch (operation) {
2585			case PT_WRITE_D:
2586			case PT_WRITE_I:
2587				FORKEE_ASSERT_EQ(lookup_me, magic);
2588				break;
2589			default:
2590				break;
2591			}
2592			break;
2593		case BYTES_TRANSFER_DATAIO:
2594			switch (operation) {
2595			case PIOD_WRITE_D:
2596			case PIOD_WRITE_I:
2597				switch (size) {
2598				case 8:
2599					FORKEE_ASSERT_EQ(lookup_me8, magic8);
2600					break;
2601				case 16:
2602					FORKEE_ASSERT_EQ(lookup_me16, magic16);
2603					break;
2604				case 32:
2605					FORKEE_ASSERT_EQ(lookup_me32, magic32);
2606					break;
2607				case 64:
2608					FORKEE_ASSERT_EQ(lookup_me64, magic64);
2609					break;
2610				default:
2611					break;
2612				}
2613				break;
2614			default:
2615				break;
2616			}
2617			break;
2618		case BYTES_TRANSFER_TEXT:
2619			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
2620			                     sizeof(magic)) == 0);
2621			break;
2622		case BYTES_TRANSFER_TEXTIO:
2623			switch (size) {
2624			case 8:
2625				FORKEE_ASSERT(memcmp(&magic8,
2626				                     bytes_transfer_dummy,
2627				                     sizeof(magic8)) == 0);
2628				break;
2629			case 16:
2630				FORKEE_ASSERT(memcmp(&magic16,
2631				                     bytes_transfer_dummy,
2632				                     sizeof(magic16)) == 0);
2633				break;
2634			case 32:
2635				FORKEE_ASSERT(memcmp(&magic32,
2636				                     bytes_transfer_dummy,
2637				                     sizeof(magic32)) == 0);
2638				break;
2639			case 64:
2640				FORKEE_ASSERT(memcmp(&magic64,
2641				                     bytes_transfer_dummy,
2642				                     sizeof(magic64)) == 0);
2643				break;
2644			}
2645			break;
2646		default:
2647			break;
2648		}
2649
2650		DPRINTF("Before exiting of the child process\n");
2651		_exit(exitval);
2652	}
2653	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2654
2655	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2656	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2657
2658	validate_status_stopped(status, sigval);
2659
2660	/* Check PaX MPROTECT */
2661	if (!can_we_write_to_text(child)) {
2662		switch (type) {
2663		case BYTES_TRANSFER_TEXTIO:
2664			switch (operation) {
2665			case PIOD_WRITE_D:
2666			case PIOD_WRITE_I:
2667				skip = true;
2668				break;
2669			default:
2670				break;
2671			}
2672			break;
2673		case BYTES_TRANSFER_TEXT:
2674			switch (operation) {
2675			case PT_WRITE_D:
2676			case PT_WRITE_I:
2677				skip = true;
2678				break;
2679			default:
2680				break;
2681			}
2682			break;
2683		default:
2684			break;
2685		}
2686	}
2687
2688	/* Bailout cleanly killing the child process */
2689	if (skip) {
2690		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
2691		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2692		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
2693		                      child);
2694
2695		validate_status_signaled(status, SIGKILL, 0);
2696
2697		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
2698	}
2699
2700	DPRINTF("Calling operation to transfer bytes between child=%d and "
2701	       "parent=%d\n", child, getpid());
2702
2703	switch (type) {
2704	case BYTES_TRANSFER_TEXTIO:
2705	case BYTES_TRANSFER_DATAIO:
2706	case BYTES_TRANSFER_AUXV:
2707		switch (operation) {
2708		case PIOD_WRITE_D:
2709		case PIOD_WRITE_I:
2710			switch (size) {
2711			case 8:
2712				lookup_me8 = magic8;
2713				break;
2714			case 16:
2715				lookup_me16 = magic16;
2716				break;
2717			case 32:
2718				lookup_me32 = magic32;
2719				break;
2720			case 64:
2721				lookup_me64 = magic64;
2722				break;
2723			default:
2724				break;
2725			}
2726			break;
2727		default:
2728			break;
2729		}
2730		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
2731		switch (operation) {
2732		case PIOD_READ_D:
2733		case PIOD_READ_I:
2734			switch (size) {
2735			case 8:
2736				ATF_REQUIRE_EQ(lookup_me8, magic8);
2737				break;
2738			case 16:
2739				ATF_REQUIRE_EQ(lookup_me16, magic16);
2740				break;
2741			case 32:
2742				ATF_REQUIRE_EQ(lookup_me32, magic32);
2743				break;
2744			case 64:
2745				ATF_REQUIRE_EQ(lookup_me64, magic64);
2746				break;
2747			default:
2748				break;
2749			}
2750			break;
2751		case PIOD_READ_AUXV:
2752			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
2753			        io.piod_len);
2754			ATF_REQUIRE(io.piod_len > 0);
2755			for (aip = ai; aip->a_type != AT_NULL; aip++)
2756				DPRINTF("a_type=%#llx a_v=%#llx\n",
2757				    (long long int)aip->a_type,
2758				    (long long int)aip->a_v);
2759			break;
2760		default:
2761			break;
2762		}
2763		break;
2764	case BYTES_TRANSFER_TEXT:
2765		switch (operation) {
2766		case PT_READ_D:
2767		case PT_READ_I:
2768			errno = 0;
2769			lookup_me = ptrace(operation, child,
2770			                   bytes_transfer_dummy, 0);
2771			ATF_REQUIRE_EQ(lookup_me, magic);
2772			SYSCALL_REQUIRE_ERRNO(errno, 0);
2773			break;
2774		case PT_WRITE_D:
2775		case PT_WRITE_I:
2776			SYSCALL_REQUIRE(ptrace(operation, child,
2777			                       bytes_transfer_dummy, magic)
2778			                != -1);
2779			break;
2780		default:
2781			break;
2782		}
2783		break;
2784	case BYTES_TRANSFER_DATA:
2785		switch (operation) {
2786		case PT_READ_D:
2787		case PT_READ_I:
2788			errno = 0;
2789			lookup_me = ptrace(operation, child, &lookup_me, 0);
2790			ATF_REQUIRE_EQ(lookup_me, magic);
2791			SYSCALL_REQUIRE_ERRNO(errno, 0);
2792			break;
2793		case PT_WRITE_D:
2794		case PT_WRITE_I:
2795			lookup_me = magic;
2796			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
2797			                       magic) != -1);
2798			break;
2799		default:
2800			break;
2801		}
2802		break;
2803	default:
2804		break;
2805	}
2806
2807	DPRINTF("Before resuming the child process where it left off and "
2808	    "without signal to be sent\n");
2809	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2810
2811	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2812	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2813
2814	validate_status_exited(status, exitval);
2815
2816	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2817	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2818}
2819
2820#define BYTES_TRANSFER(test, operation, size, type)			\
2821ATF_TC(test);								\
2822ATF_TC_HEAD(test, tc)							\
2823{									\
2824	atf_tc_set_md_var(tc, "descr",					\
2825	    "Verify bytes transfer operation" #operation " and size " #size \
2826	    " of type " #type);						\
2827}									\
2828									\
2829ATF_TC_BODY(test, tc)							\
2830{									\
2831									\
2832	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
2833}
2834
2835// DATA
2836
2837BYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
2838BYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
2839BYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
2840BYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
2841
2842BYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
2843BYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
2844BYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
2845BYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
2846
2847BYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
2848BYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
2849BYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
2850BYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
2851
2852BYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
2853BYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
2854BYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
2855BYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
2856
2857BYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
2858BYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
2859BYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
2860BYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
2861
2862// TEXT
2863
2864BYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
2865BYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
2866BYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
2867BYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
2868
2869BYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
2870BYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
2871BYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
2872BYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
2873
2874BYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
2875BYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
2876BYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
2877BYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
2878
2879BYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
2880BYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
2881BYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
2882BYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
2883
2884BYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
2885BYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
2886BYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
2887BYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
2888
2889// AUXV
2890
2891BYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
2892
2893/// ----------------------------------------------------------------------------
2894
2895#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS)
2896static void
2897access_regs(const char *regset, const char *aux)
2898{
2899	const int exitval = 5;
2900	const int sigval = SIGSTOP;
2901	pid_t child, wpid;
2902#if defined(TWAIT_HAVE_STATUS)
2903	int status;
2904#endif
2905#if defined(HAVE_GPREGS)
2906	struct reg gpr;
2907	register_t rgstr;
2908#endif
2909#if defined(HAVE_FPREGS)
2910	struct fpreg fpr;
2911#endif
2912
2913#if !defined(HAVE_GPREGS)
2914	if (strcmp(regset, "regs") == 0)
2915		atf_tc_fail("Impossible test scenario!");
2916#endif
2917
2918#if !defined(HAVE_FPREGS)
2919	if (strcmp(regset, "fpregs") == 0)
2920		atf_tc_fail("Impossible test scenario!");
2921#endif
2922
2923	DPRINTF("Before forking process PID=%d\n", getpid());
2924	SYSCALL_REQUIRE((child = fork()) != -1);
2925	if (child == 0) {
2926		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2927		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2928
2929		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2930		FORKEE_ASSERT(raise(sigval) == 0);
2931
2932		DPRINTF("Before exiting of the child process\n");
2933		_exit(exitval);
2934	}
2935	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2936
2937	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2938	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2939
2940	validate_status_stopped(status, sigval);
2941
2942#if defined(HAVE_GPREGS)
2943	if (strcmp(regset, "regs") == 0) {
2944		DPRINTF("Call GETREGS for the child process\n");
2945		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
2946
2947		if (strcmp(aux, "none") == 0) {
2948			DPRINTF("Retrieved registers\n");
2949		} else if (strcmp(aux, "pc") == 0) {
2950			rgstr = PTRACE_REG_PC(&gpr);
2951			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
2952		} else if (strcmp(aux, "set_pc") == 0) {
2953			rgstr = PTRACE_REG_PC(&gpr);
2954			PTRACE_REG_SET_PC(&gpr, rgstr);
2955		} else if (strcmp(aux, "sp") == 0) {
2956			rgstr = PTRACE_REG_SP(&gpr);
2957			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
2958		} else if (strcmp(aux, "intrv") == 0) {
2959			rgstr = PTRACE_REG_INTRV(&gpr);
2960			DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr);
2961		} else if (strcmp(aux, "setregs") == 0) {
2962			DPRINTF("Call SETREGS for the child process\n");
2963			SYSCALL_REQUIRE(
2964			    ptrace(PT_GETREGS, child, &gpr, 0) != -1);
2965		}
2966	}
2967#endif
2968
2969#if defined(HAVE_FPREGS)
2970	if (strcmp(regset, "fpregs") == 0) {
2971		DPRINTF("Call GETFPREGS for the child process\n");
2972		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
2973
2974		if (strcmp(aux, "getfpregs") == 0) {
2975			DPRINTF("Retrieved FP registers\n");
2976		} else if (strcmp(aux, "setfpregs") == 0) {
2977			DPRINTF("Call SETFPREGS for the child\n");
2978			SYSCALL_REQUIRE(
2979			    ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
2980		}
2981	}
2982#endif
2983
2984	DPRINTF("Before resuming the child process where it left off and "
2985	    "without signal to be sent\n");
2986	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2987
2988	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2989	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2990
2991	validate_status_exited(status, exitval);
2992
2993	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2994	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2995}
2996
2997#define ACCESS_REGS(test, regset, aux)					\
2998ATF_TC(test);								\
2999ATF_TC_HEAD(test, tc)							\
3000{									\
3001        atf_tc_set_md_var(tc, "descr",					\
3002            "Verify " regset " with auxiliary operation: " aux);	\
3003}									\
3004									\
3005ATF_TC_BODY(test, tc)							\
3006{									\
3007									\
3008        access_regs(regset, aux);					\
3009}
3010#endif
3011
3012#if defined(HAVE_GPREGS)
3013ACCESS_REGS(access_regs1, "regs", "none")
3014ACCESS_REGS(access_regs2, "regs", "pc")
3015ACCESS_REGS(access_regs3, "regs", "set_pc")
3016ACCESS_REGS(access_regs4, "regs", "sp")
3017ACCESS_REGS(access_regs5, "regs", "intrv")
3018ACCESS_REGS(access_regs6, "regs", "setregs")
3019#endif
3020#if defined(HAVE_FPREGS)
3021ACCESS_REGS(access_fpregs1, "fpregs", "getfpregs")
3022ACCESS_REGS(access_fpregs2, "fpregs", "setfpregs")
3023#endif
3024
3025/// ----------------------------------------------------------------------------
3026
3027#if defined(PT_STEP)
3028static void
3029ptrace_step(int N, int setstep)
3030{
3031	const int exitval = 5;
3032	const int sigval = SIGSTOP;
3033	pid_t child, wpid;
3034#if defined(TWAIT_HAVE_STATUS)
3035	int status;
3036#endif
3037	int happy;
3038	struct ptrace_siginfo info;
3039
3040#if defined(__arm__)
3041	/* PT_STEP not supported on arm 32-bit */
3042	atf_tc_expect_fail("PR kern/52119");
3043#endif
3044
3045	DPRINTF("Before forking process PID=%d\n", getpid());
3046	SYSCALL_REQUIRE((child = fork()) != -1);
3047	if (child == 0) {
3048		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3049		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3050
3051		happy = check_happy(999);
3052
3053		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3054		FORKEE_ASSERT(raise(sigval) == 0);
3055
3056		FORKEE_ASSERT_EQ(happy, check_happy(999));
3057
3058		DPRINTF("Before exiting of the child process\n");
3059		_exit(exitval);
3060	}
3061	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3062
3063	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3064	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3065
3066	validate_status_stopped(status, sigval);
3067
3068	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3069	SYSCALL_REQUIRE(
3070	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3071
3072	DPRINTF("Before checking siginfo_t\n");
3073	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3074	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3075
3076	while (N --> 0) {
3077		if (setstep) {
3078			DPRINTF("Before resuming the child process where it "
3079			    "left off and without signal to be sent (use "
3080			    "PT_SETSTEP and PT_CONTINUE)\n");
3081			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
3082			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
3083			    != -1);
3084		} else {
3085			DPRINTF("Before resuming the child process where it "
3086			    "left off and without signal to be sent (use "
3087			    "PT_STEP)\n");
3088			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
3089			    != -1);
3090		}
3091
3092		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3093		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
3094		    child);
3095
3096		validate_status_stopped(status, SIGTRAP);
3097
3098		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3099		SYSCALL_REQUIRE(
3100		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3101
3102		DPRINTF("Before checking siginfo_t\n");
3103		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
3104		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
3105
3106		if (setstep) {
3107			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
3108		}
3109	}
3110
3111	DPRINTF("Before resuming the child process where it left off and "
3112	    "without signal to be sent\n");
3113	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3114
3115	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3116	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3117
3118	validate_status_exited(status, exitval);
3119
3120	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3121	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3122}
3123
3124#define PTRACE_STEP(test, N, setstep)					\
3125ATF_TC(test);								\
3126ATF_TC_HEAD(test, tc)							\
3127{									\
3128        atf_tc_set_md_var(tc, "descr",					\
3129            "Verify " #N " (PT_SETSTEP set to: " #setstep ")");		\
3130}									\
3131									\
3132ATF_TC_BODY(test, tc)							\
3133{									\
3134									\
3135        ptrace_step(N, setstep);					\
3136}
3137
3138PTRACE_STEP(step1, 1, 0)
3139PTRACE_STEP(step2, 2, 0)
3140PTRACE_STEP(step3, 3, 0)
3141PTRACE_STEP(step4, 4, 0)
3142PTRACE_STEP(setstep1, 1, 1)
3143PTRACE_STEP(setstep2, 2, 1)
3144PTRACE_STEP(setstep3, 3, 1)
3145PTRACE_STEP(setstep4, 4, 1)
3146#endif
3147
3148/// ----------------------------------------------------------------------------
3149
3150static void
3151ptrace_kill(const char *type)
3152{
3153	const int sigval = SIGSTOP;
3154	pid_t child, wpid;
3155#if defined(TWAIT_HAVE_STATUS)
3156	int status;
3157#endif
3158
3159	DPRINTF("Before forking process PID=%d\n", getpid());
3160	SYSCALL_REQUIRE((child = fork()) != -1);
3161	if (child == 0) {
3162		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3163		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3164
3165		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3166		FORKEE_ASSERT(raise(sigval) == 0);
3167
3168		/* NOTREACHED */
3169		FORKEE_ASSERTX(0 &&
3170		    "Child should be terminated by a signal from its parent");
3171	}
3172	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3173
3174	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3175	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3176
3177	validate_status_stopped(status, sigval);
3178
3179	DPRINTF("Before killing the child process with %s\n", type);
3180	if (strcmp(type, "ptrace(PT_KILL)") == 0) {
3181		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
3182	} else if (strcmp(type, "kill(SIGKILL)") == 0) {
3183		kill(child, SIGKILL);
3184	} else if (strcmp(type, "killpg(SIGKILL)") == 0) {
3185		setpgid(child, 0);
3186		killpg(getpgid(child), SIGKILL);
3187	}
3188
3189	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3190	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3191
3192	validate_status_signaled(status, SIGKILL, 0);
3193
3194	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3195	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3196}
3197
3198#define PTRACE_KILL(test, type)						\
3199ATF_TC(test);								\
3200ATF_TC_HEAD(test, tc)							\
3201{									\
3202        atf_tc_set_md_var(tc, "descr",					\
3203            "Verify killing the child with " type);			\
3204}									\
3205									\
3206ATF_TC_BODY(test, tc)							\
3207{									\
3208									\
3209        ptrace_kill(type);						\
3210}
3211
3212// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1
3213PTRACE_KILL(kill1, "ptrace(PT_KILL)")
3214PTRACE_KILL(kill2, "kill(SIGKILL)")
3215PTRACE_KILL(kill3, "killpg(SIGKILL)")
3216
3217/// ----------------------------------------------------------------------------
3218
3219static void
3220traceme_lwpinfo(const int threads)
3221{
3222	const int sigval = SIGSTOP;
3223	const int sigval2 = SIGINT;
3224	pid_t child, wpid;
3225#if defined(TWAIT_HAVE_STATUS)
3226	int status;
3227#endif
3228	struct ptrace_lwpinfo lwp = {0, 0};
3229	struct ptrace_siginfo info;
3230
3231	/* Maximum number of supported threads in this test */
3232	pthread_t t[3];
3233	int n, rv;
3234
3235	ATF_REQUIRE((int)__arraycount(t) >= threads);
3236
3237	DPRINTF("Before forking process PID=%d\n", getpid());
3238	SYSCALL_REQUIRE((child = fork()) != -1);
3239	if (child == 0) {
3240		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3241		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3242
3243		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3244		FORKEE_ASSERT(raise(sigval) == 0);
3245
3246		for (n = 0; n < threads; n++) {
3247			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
3248			FORKEE_ASSERT(rv == 0);
3249		}
3250
3251		DPRINTF("Before raising %s from child\n", strsignal(sigval2));
3252		FORKEE_ASSERT(raise(sigval2) == 0);
3253
3254		/* NOTREACHED */
3255		FORKEE_ASSERTX(0 && "Not reached");
3256	}
3257	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3258
3259	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3260	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3261
3262	validate_status_stopped(status, sigval);
3263
3264	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
3265	SYSCALL_REQUIRE(
3266	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3267
3268	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3269	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3270	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3271	    info.psi_siginfo.si_errno);
3272
3273	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3274	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3275
3276	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
3277	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
3278
3279	DPRINTF("Assert that there exists a single thread only\n");
3280	ATF_REQUIRE(lwp.pl_lwpid > 0);
3281
3282	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
3283	    lwp.pl_lwpid);
3284	FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
3285
3286	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
3287	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
3288
3289	DPRINTF("Assert that there exists a single thread only\n");
3290	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
3291
3292	DPRINTF("Before resuming the child process where it left off and "
3293	    "without signal to be sent\n");
3294	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3295
3296	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3297	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3298
3299	validate_status_stopped(status, sigval2);
3300
3301	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
3302	SYSCALL_REQUIRE(
3303	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3304
3305	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3306	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3307	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3308	    info.psi_siginfo.si_errno);
3309
3310	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2);
3311	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3312
3313	memset(&lwp, 0, sizeof(lwp));
3314
3315	for (n = 0; n <= threads; n++) {
3316		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
3317		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
3318		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
3319
3320		DPRINTF("Assert that the thread exists\n");
3321		ATF_REQUIRE(lwp.pl_lwpid > 0);
3322
3323		DPRINTF("Assert that lwp thread %d received expected event\n",
3324		    lwp.pl_lwpid);
3325		FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ?
3326		    PL_EVENT_SIGNAL : PL_EVENT_NONE);
3327	}
3328	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
3329	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1);
3330	DPRINTF("LWP=%d\n", lwp.pl_lwpid);
3331
3332	DPRINTF("Assert that there are no more threads\n");
3333	ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
3334
3335	DPRINTF("Before resuming the child process where it left off and "
3336	    "without signal to be sent\n");
3337	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1);
3338
3339	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3340	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3341
3342	validate_status_signaled(status, SIGKILL, 0);
3343
3344	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3345	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3346}
3347
3348#define TRACEME_LWPINFO(test, threads)					\
3349ATF_TC(test);								\
3350ATF_TC_HEAD(test, tc)							\
3351{									\
3352	atf_tc_set_md_var(tc, "descr",					\
3353	    "Verify LWPINFO with the child with " #threads		\
3354	    " spawned extra threads");					\
3355}									\
3356									\
3357ATF_TC_BODY(test, tc)							\
3358{									\
3359									\
3360	traceme_lwpinfo(threads);					\
3361}
3362
3363TRACEME_LWPINFO(traceme_lwpinfo0, 0)
3364TRACEME_LWPINFO(traceme_lwpinfo1, 1)
3365TRACEME_LWPINFO(traceme_lwpinfo2, 2)
3366TRACEME_LWPINFO(traceme_lwpinfo3, 3)
3367
3368/// ----------------------------------------------------------------------------
3369
3370#if defined(TWAIT_HAVE_PID)
3371static void
3372attach_lwpinfo(const int threads)
3373{
3374	const int sigval = SIGINT;
3375	struct msg_fds parent_tracee, parent_tracer;
3376	const int exitval_tracer = 10;
3377	pid_t tracee, tracer, wpid;
3378	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
3379#if defined(TWAIT_HAVE_STATUS)
3380	int status;
3381#endif
3382	struct ptrace_lwpinfo lwp = {0, 0};
3383	struct ptrace_siginfo info;
3384
3385	/* Maximum number of supported threads in this test */
3386	pthread_t t[3];
3387	int n, rv;
3388
3389	DPRINTF("Spawn tracee\n");
3390	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
3391	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
3392	tracee = atf_utils_fork();
3393	if (tracee == 0) {
3394		/* Wait for message from the parent */
3395		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
3396
3397		CHILD_FROM_PARENT("spawn threads", parent_tracee, msg);
3398
3399		for (n = 0; n < threads; n++) {
3400			rv = pthread_create(&t[n], NULL, infinite_thread, NULL);
3401			FORKEE_ASSERT(rv == 0);
3402		}
3403
3404		CHILD_TO_PARENT("tracee exit", parent_tracee, msg);
3405
3406		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3407		FORKEE_ASSERT(raise(sigval) == 0);
3408
3409		/* NOTREACHED */
3410		FORKEE_ASSERTX(0 && "Not reached");
3411	}
3412	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
3413
3414	DPRINTF("Spawn debugger\n");
3415	tracer = atf_utils_fork();
3416	if (tracer == 0) {
3417		/* No IPC to communicate with the child */
3418		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
3419		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
3420
3421		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
3422		FORKEE_REQUIRE_SUCCESS(
3423		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
3424
3425		forkee_status_stopped(status, SIGSTOP);
3426
3427		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
3428		    "tracee");
3429		FORKEE_ASSERT(
3430		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
3431
3432		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3433		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
3434		    "si_errno=%#x\n",
3435		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3436		    info.psi_siginfo.si_errno);
3437
3438		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP);
3439		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER);
3440
3441		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
3442		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
3443		    != -1);
3444
3445		DPRINTF("Assert that there exists a thread\n");
3446		FORKEE_ASSERTX(lwp.pl_lwpid > 0);
3447
3448		DPRINTF("Assert that lwp thread %d received event "
3449		    "PL_EVENT_SIGNAL\n", lwp.pl_lwpid);
3450		FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL);
3451
3452		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
3453		    "tracee\n");
3454		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
3455		    != -1);
3456
3457		DPRINTF("Assert that there are no more lwp threads in "
3458		    "tracee\n");
3459		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
3460
3461		/* Resume tracee with PT_CONTINUE */
3462		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
3463
3464		/* Inform parent that tracer has attached to tracee */
3465		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
3466
3467		/* Wait for parent */
3468		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
3469
3470		/* Wait for tracee and assert that it raised a signal */
3471		FORKEE_REQUIRE_SUCCESS(
3472		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
3473
3474		forkee_status_stopped(status, SIGINT);
3475
3476		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
3477		    "child");
3478		FORKEE_ASSERT(
3479		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
3480
3481		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3482		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
3483		    "si_errno=%#x\n",
3484		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3485		    info.psi_siginfo.si_errno);
3486
3487		FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval);
3488		FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP);
3489
3490		memset(&lwp, 0, sizeof(lwp));
3491
3492		for (n = 0; n <= threads; n++) {
3493			DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
3494			    "child\n");
3495			FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp,
3496			    sizeof(lwp)) != -1);
3497			DPRINTF("LWP=%d\n", lwp.pl_lwpid);
3498
3499			DPRINTF("Assert that the thread exists\n");
3500			FORKEE_ASSERT(lwp.pl_lwpid > 0);
3501
3502			DPRINTF("Assert that lwp thread %d received expected "
3503			    "event\n", lwp.pl_lwpid);
3504			FORKEE_ASSERT_EQ(lwp.pl_event,
3505			    info.psi_lwpid == lwp.pl_lwpid ?
3506			    PL_EVENT_SIGNAL : PL_EVENT_NONE);
3507		}
3508		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for "
3509		    "tracee\n");
3510		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp))
3511		    != -1);
3512		DPRINTF("LWP=%d\n", lwp.pl_lwpid);
3513
3514		DPRINTF("Assert that there are no more threads\n");
3515		FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0);
3516
3517		DPRINTF("Before resuming the child process where it left off "
3518		    "and without signal to be sent\n");
3519		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL)
3520		    != -1);
3521
3522		/* Wait for tracee and assert that it exited */
3523		FORKEE_REQUIRE_SUCCESS(
3524		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
3525
3526		forkee_status_signaled(status, SIGKILL, 0);
3527
3528		DPRINTF("Before exiting of the tracer process\n");
3529		_exit(exitval_tracer);
3530	}
3531
3532	DPRINTF("Wait for the tracer to attach to the tracee\n");
3533	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
3534
3535	DPRINTF("Resume the tracee and spawn threads\n");
3536	PARENT_TO_CHILD("spawn threads", parent_tracee, msg);
3537
3538	DPRINTF("Resume the tracee and let it exit\n");
3539	PARENT_FROM_CHILD("tracee exit", parent_tracee, msg);
3540
3541	DPRINTF("Resume the tracer and let it detect multiple threads\n");
3542	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
3543
3544	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
3545	    TWAIT_FNAME);
3546	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
3547	    tracer);
3548
3549	validate_status_exited(status, exitval_tracer);
3550
3551	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
3552	    TWAIT_FNAME);
3553	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
3554	    tracee);
3555
3556	validate_status_signaled(status, SIGKILL, 0);
3557
3558	msg_close(&parent_tracer);
3559	msg_close(&parent_tracee);
3560}
3561
3562#define ATTACH_LWPINFO(test, threads)					\
3563ATF_TC(test);								\
3564ATF_TC_HEAD(test, tc)							\
3565{									\
3566	atf_tc_set_md_var(tc, "descr",					\
3567	    "Verify LWPINFO with the child with " #threads		\
3568	    " spawned extra threads (tracer is not the original "	\
3569	    "parent)");							\
3570}									\
3571									\
3572ATF_TC_BODY(test, tc)							\
3573{									\
3574									\
3575	attach_lwpinfo(threads);					\
3576}
3577
3578ATTACH_LWPINFO(attach_lwpinfo0, 0)
3579ATTACH_LWPINFO(attach_lwpinfo1, 1)
3580ATTACH_LWPINFO(attach_lwpinfo2, 2)
3581ATTACH_LWPINFO(attach_lwpinfo3, 3)
3582#endif
3583
3584/// ----------------------------------------------------------------------------
3585
3586static void
3587ptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
3588{
3589	const int exitval = 5;
3590	const int sigval = SIGINT;
3591	const int sigfaked = SIGTRAP;
3592	const int sicodefaked = TRAP_BRKPT;
3593	pid_t child, wpid;
3594	struct sigaction sa;
3595#if defined(TWAIT_HAVE_STATUS)
3596	int status;
3597#endif
3598	struct ptrace_siginfo info;
3599	memset(&info, 0, sizeof(info));
3600
3601	DPRINTF("Before forking process PID=%d\n", getpid());
3602	SYSCALL_REQUIRE((child = fork()) != -1);
3603	if (child == 0) {
3604		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3605		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3606
3607		sa.sa_sigaction = sah;
3608		sa.sa_flags = SA_SIGINFO;
3609		sigemptyset(&sa.sa_mask);
3610
3611		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
3612		    != -1);
3613
3614		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3615		FORKEE_ASSERT(raise(sigval) == 0);
3616
3617		FORKEE_ASSERT_EQ(*signal_caught, 1);
3618
3619		DPRINTF("Before exiting of the child process\n");
3620		_exit(exitval);
3621	}
3622	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3623
3624	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3625	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3626
3627	validate_status_stopped(status, sigval);
3628
3629	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3630	SYSCALL_REQUIRE(
3631	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3632
3633	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3634	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3635	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3636	    info.psi_siginfo.si_errno);
3637
3638	if (faked) {
3639		DPRINTF("Before setting new faked signal to signo=%d "
3640		    "si_code=%d\n", sigfaked, sicodefaked);
3641		info.psi_siginfo.si_signo = sigfaked;
3642		info.psi_siginfo.si_code = sicodefaked;
3643	}
3644
3645	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
3646	SYSCALL_REQUIRE(
3647	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
3648
3649	if (faked) {
3650		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
3651		    "child\n");
3652		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
3653		    sizeof(info)) != -1);
3654
3655		DPRINTF("Before checking siginfo_t\n");
3656		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
3657		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
3658	}
3659
3660	DPRINTF("Before resuming the child process where it left off and "
3661	    "without signal to be sent\n");
3662	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
3663	    faked ? sigfaked : sigval) != -1);
3664
3665	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3666	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3667
3668	validate_status_exited(status, exitval);
3669
3670	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3671	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3672}
3673
3674#define PTRACE_SIGINFO(test, faked)					\
3675ATF_TC(test);								\
3676ATF_TC_HEAD(test, tc)							\
3677{									\
3678	atf_tc_set_md_var(tc, "descr",					\
3679	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
3680	    "with%s setting signal to new value", faked ? "" : "out");	\
3681}									\
3682									\
3683static int test##_caught = 0;						\
3684									\
3685static void								\
3686test##_sighandler(int sig, siginfo_t *info, void *ctx)			\
3687{									\
3688	if (faked) {							\
3689		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
3690		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
3691		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
3692	} else {							\
3693		FORKEE_ASSERT_EQ(sig, SIGINT);				\
3694		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
3695		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
3696	}								\
3697									\
3698	++ test##_caught;						\
3699}									\
3700									\
3701ATF_TC_BODY(test, tc)							\
3702{									\
3703									\
3704	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
3705}
3706
3707PTRACE_SIGINFO(siginfo_set_unmodified, false)
3708PTRACE_SIGINFO(siginfo_set_faked, true)
3709
3710/// ----------------------------------------------------------------------------
3711
3712ATF_TC(traceme_exec);
3713ATF_TC_HEAD(traceme_exec, tc)
3714{
3715	atf_tc_set_md_var(tc, "descr",
3716	    "Detect SIGTRAP TRAP_EXEC from tracee");
3717}
3718
3719ATF_TC_BODY(traceme_exec, tc)
3720{
3721	const int sigval = SIGTRAP;
3722	pid_t child, wpid;
3723#if defined(TWAIT_HAVE_STATUS)
3724	int status;
3725#endif
3726
3727	struct ptrace_siginfo info;
3728	memset(&info, 0, sizeof(info));
3729
3730	DPRINTF("Before forking process PID=%d\n", getpid());
3731	SYSCALL_REQUIRE((child = fork()) != -1);
3732	if (child == 0) {
3733		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3734		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3735
3736		DPRINTF("Before calling execve(2) from child\n");
3737		execlp("/bin/echo", "/bin/echo", NULL);
3738
3739		FORKEE_ASSERT(0 && "Not reached");
3740	}
3741	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3742
3743	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3744	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3745
3746	validate_status_stopped(status, sigval);
3747
3748	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3749	SYSCALL_REQUIRE(
3750	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3751
3752	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3753	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3754	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3755	    info.psi_siginfo.si_errno);
3756
3757	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3758	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
3759
3760	DPRINTF("Before resuming the child process where it left off and "
3761	    "without signal to be sent\n");
3762	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3763
3764	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3765	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3766
3767	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3768	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3769}
3770
3771/// ----------------------------------------------------------------------------
3772
3773static volatile int done;
3774
3775static void *
3776trace_threads_cb(void *arg __unused)
3777{
3778
3779	done++;
3780
3781	while (done < 3)
3782		continue;
3783
3784	return NULL;
3785}
3786
3787static void
3788trace_threads(bool trace_create, bool trace_exit)
3789{
3790	const int sigval = SIGSTOP;
3791	pid_t child, wpid;
3792#if defined(TWAIT_HAVE_STATUS)
3793	int status;
3794#endif
3795	ptrace_state_t state;
3796	const int slen = sizeof(state);
3797	ptrace_event_t event;
3798	const int elen = sizeof(event);
3799	struct ptrace_siginfo info;
3800
3801	pthread_t t[3];
3802	int rv;
3803	size_t n;
3804	lwpid_t lid;
3805
3806	/* Track created and exited threads */
3807	bool traced_lwps[__arraycount(t)];
3808
3809	atf_tc_skip("PR kern/51995");
3810
3811	DPRINTF("Before forking process PID=%d\n", getpid());
3812	SYSCALL_REQUIRE((child = fork()) != -1);
3813	if (child == 0) {
3814		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3815		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3816
3817		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3818		FORKEE_ASSERT(raise(sigval) == 0);
3819
3820		for (n = 0; n < __arraycount(t); n++) {
3821			rv = pthread_create(&t[n], NULL, trace_threads_cb,
3822			    NULL);
3823			FORKEE_ASSERT(rv == 0);
3824		}
3825
3826		for (n = 0; n < __arraycount(t); n++) {
3827			rv = pthread_join(t[n], NULL);
3828			FORKEE_ASSERT(rv == 0);
3829		}
3830
3831		/*
3832		 * There is race between _exit() and pthread_join() detaching
3833		 * a thread. For simplicity kill the process after detecting
3834		 * LWP events.
3835		 */
3836		while (true)
3837			continue;
3838
3839		FORKEE_ASSERT(0 && "Not reached");
3840	}
3841	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3842
3843	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3844	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3845
3846	validate_status_stopped(status, sigval);
3847
3848	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3849	SYSCALL_REQUIRE(
3850	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3851
3852	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3853	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3854	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3855	    info.psi_siginfo.si_errno);
3856
3857	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3858	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3859
3860	DPRINTF("Set LWP event mask for the child %d\n", child);
3861	memset(&event, 0, sizeof(event));
3862	if (trace_create)
3863		event.pe_set_event |= PTRACE_LWP_CREATE;
3864	if (trace_exit)
3865		event.pe_set_event |= PTRACE_LWP_EXIT;
3866	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
3867
3868	DPRINTF("Before resuming the child process where it left off and "
3869	    "without signal to be sent\n");
3870	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3871
3872	memset(traced_lwps, 0, sizeof(traced_lwps));
3873
3874	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
3875		DPRINTF("Before calling %s() for the child - expected stopped "
3876		    "SIGTRAP\n", TWAIT_FNAME);
3877		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
3878		    child);
3879
3880		validate_status_stopped(status, SIGTRAP);
3881
3882		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
3883		    "child\n");
3884		SYSCALL_REQUIRE(
3885		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3886
3887		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3888		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
3889		    "si_errno=%#x\n",
3890		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3891		    info.psi_siginfo.si_errno);
3892
3893		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
3894		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
3895
3896		SYSCALL_REQUIRE(
3897		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
3898
3899		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
3900		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
3901
3902		lid = state.pe_lwp;
3903		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
3904
3905		traced_lwps[lid - 1] = true;
3906
3907		DPRINTF("Before resuming the child process where it left off "
3908		    "and without signal to be sent\n");
3909		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3910	}
3911
3912	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
3913		DPRINTF("Before calling %s() for the child - expected stopped "
3914		    "SIGTRAP\n", TWAIT_FNAME);
3915		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
3916		    child);
3917
3918		validate_status_stopped(status, SIGTRAP);
3919
3920		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
3921		    "child\n");
3922		SYSCALL_REQUIRE(
3923		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3924
3925		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3926		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
3927		    "si_errno=%#x\n",
3928		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3929		    info.psi_siginfo.si_errno);
3930
3931		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
3932		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
3933
3934		SYSCALL_REQUIRE(
3935		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
3936
3937		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
3938		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
3939
3940		lid = state.pe_lwp;
3941		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
3942
3943		if (trace_create) {
3944			ATF_REQUIRE(traced_lwps[lid - 1] == true);
3945			traced_lwps[lid - 1] = false;
3946		}
3947
3948		DPRINTF("Before resuming the child process where it left off "
3949		    "and without signal to be sent\n");
3950		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3951	}
3952
3953	kill(child, SIGKILL);
3954
3955	DPRINTF("Before calling %s() for the child - expected exited\n",
3956	    TWAIT_FNAME);
3957	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3958
3959	validate_status_signaled(status, SIGKILL, 0);
3960
3961	DPRINTF("Before calling %s() for the child - expected no process\n",
3962	    TWAIT_FNAME);
3963	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3964}
3965
3966#define TRACE_THREADS(test, trace_create, trace_exit)			\
3967ATF_TC(test);								\
3968ATF_TC_HEAD(test, tc)							\
3969{									\
3970        atf_tc_set_md_var(tc, "descr",					\
3971            "Verify spawning threads with%s tracing LWP create and"	\
3972	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
3973	    trace_exit ? "" : "out");					\
3974}									\
3975									\
3976ATF_TC_BODY(test, tc)							\
3977{									\
3978									\
3979        trace_threads(trace_create, trace_exit);			\
3980}
3981
3982TRACE_THREADS(trace_thread1, false, false)
3983TRACE_THREADS(trace_thread2, false, true)
3984TRACE_THREADS(trace_thread3, true, false)
3985TRACE_THREADS(trace_thread4, true, true)
3986
3987/// ----------------------------------------------------------------------------
3988
3989ATF_TC(signal_mask_unrelated);
3990ATF_TC_HEAD(signal_mask_unrelated, tc)
3991{
3992	atf_tc_set_md_var(tc, "descr",
3993	    "Verify that masking single unrelated signal does not stop tracer "
3994	    "from catching other signals");
3995}
3996
3997ATF_TC_BODY(signal_mask_unrelated, tc)
3998{
3999	const int exitval = 5;
4000	const int sigval = SIGSTOP;
4001	const int sigmasked = SIGTRAP;
4002	const int signotmasked = SIGINT;
4003	pid_t child, wpid;
4004#if defined(TWAIT_HAVE_STATUS)
4005	int status;
4006#endif
4007	sigset_t intmask;
4008
4009	DPRINTF("Before forking process PID=%d\n", getpid());
4010	SYSCALL_REQUIRE((child = fork()) != -1);
4011	if (child == 0) {
4012		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4013		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4014
4015		sigemptyset(&intmask);
4016		sigaddset(&intmask, sigmasked);
4017		sigprocmask(SIG_BLOCK, &intmask, NULL);
4018
4019		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4020		FORKEE_ASSERT(raise(sigval) == 0);
4021
4022		DPRINTF("Before raising %s from child\n",
4023		    strsignal(signotmasked));
4024		FORKEE_ASSERT(raise(signotmasked) == 0);
4025
4026		DPRINTF("Before exiting of the child process\n");
4027		_exit(exitval);
4028	}
4029	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4030
4031	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4032	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4033
4034	validate_status_stopped(status, sigval);
4035
4036	DPRINTF("Before resuming the child process where it left off and "
4037	    "without signal to be sent\n");
4038	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4039
4040	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4041	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4042
4043	validate_status_stopped(status, signotmasked);
4044
4045	DPRINTF("Before resuming the child process where it left off and "
4046	    "without signal to be sent\n");
4047	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4048
4049	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4050	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4051
4052	validate_status_exited(status, exitval);
4053
4054	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4055	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4056}
4057
4058/// ----------------------------------------------------------------------------
4059
4060ATF_TC(signal3);
4061ATF_TC_HEAD(signal3, tc)
4062{
4063	atf_tc_set_md_var(tc, "timeout", "5");
4064	atf_tc_set_md_var(tc, "descr",
4065	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4066	    "catching software breakpoints");
4067}
4068
4069ATF_TC_BODY(signal3, tc)
4070{
4071	const int exitval = 5;
4072	const int sigval = SIGSTOP;
4073	const int sigmasked = SIGTRAP;
4074	pid_t child, wpid;
4075#if defined(TWAIT_HAVE_STATUS)
4076	int status;
4077#endif
4078	sigset_t intmask;
4079
4080	DPRINTF("Before forking process PID=%d\n", getpid());
4081	SYSCALL_REQUIRE((child = fork()) != -1);
4082	if (child == 0) {
4083		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4084		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4085
4086		sigemptyset(&intmask);
4087		sigaddset(&intmask, sigmasked);
4088		sigprocmask(SIG_BLOCK, &intmask, NULL);
4089
4090		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4091		FORKEE_ASSERT(raise(sigval) == 0);
4092
4093		DPRINTF("Before raising software breakpoint from child\n");
4094		trigger_trap();
4095
4096		DPRINTF("Before exiting of the child process\n");
4097		_exit(exitval);
4098	}
4099	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4100
4101	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4102	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4103
4104	validate_status_stopped(status, sigval);
4105
4106	DPRINTF("Before resuming the child process where it left off and "
4107	    "without signal to be sent\n");
4108	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4109
4110	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4111	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4112
4113	validate_status_stopped(status, sigmasked);
4114
4115	DPRINTF("Before resuming the child process where it left off and "
4116	    "without signal to be sent\n");
4117	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
4118
4119	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4120	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4121
4122	validate_status_signaled(status, SIGKILL, 0);
4123
4124	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4125	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4126}
4127
4128#if defined(PT_STEP)
4129ATF_TC(signal4);
4130ATF_TC_HEAD(signal4, tc)
4131{
4132	atf_tc_set_md_var(tc, "descr",
4133	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4134	    "catching single step trap");
4135}
4136
4137ATF_TC_BODY(signal4, tc)
4138{
4139	const int exitval = 5;
4140	const int sigval = SIGSTOP;
4141	const int sigmasked = SIGTRAP;
4142	pid_t child, wpid;
4143#if defined(TWAIT_HAVE_STATUS)
4144	int status;
4145#endif
4146	sigset_t intmask;
4147	int happy;
4148
4149#if defined(__arm__)
4150	/* PT_STEP not supported on arm 32-bit */
4151	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
4152#endif
4153
4154	DPRINTF("Before forking process PID=%d\n", getpid());
4155	SYSCALL_REQUIRE((child = fork()) != -1);
4156	if (child == 0) {
4157		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4158		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4159
4160		happy = check_happy(100);
4161
4162		sigemptyset(&intmask);
4163		sigaddset(&intmask, sigmasked);
4164		sigprocmask(SIG_BLOCK, &intmask, NULL);
4165
4166		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4167		FORKEE_ASSERT(raise(sigval) == 0);
4168
4169		FORKEE_ASSERT_EQ(happy, check_happy(100));
4170
4171		DPRINTF("Before exiting of the child process\n");
4172		_exit(exitval);
4173	}
4174	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4175
4176	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4177	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4178
4179	validate_status_stopped(status, sigval);
4180
4181	DPRINTF("Before resuming the child process where it left off and "
4182	    "without signal to be sent\n");
4183	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
4184
4185	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4186	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4187
4188	validate_status_stopped(status, sigmasked);
4189
4190	DPRINTF("Before resuming the child process where it left off and "
4191	    "without signal to be sent\n");
4192	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4193
4194	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4195	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4196
4197	validate_status_exited(status, exitval);
4198
4199	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4200	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4201}
4202#endif
4203
4204ATF_TC(signal5);
4205ATF_TC_HEAD(signal5, tc)
4206{
4207	atf_tc_set_md_var(tc, "descr",
4208	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4209	    "catching exec() breakpoint");
4210}
4211
4212ATF_TC_BODY(signal5, tc)
4213{
4214	const int sigval = SIGSTOP;
4215	const int sigmasked = SIGTRAP;
4216	pid_t child, wpid;
4217#if defined(TWAIT_HAVE_STATUS)
4218	int status;
4219#endif
4220	struct ptrace_siginfo info;
4221	sigset_t intmask;
4222
4223	memset(&info, 0, sizeof(info));
4224
4225	DPRINTF("Before forking process PID=%d\n", getpid());
4226	SYSCALL_REQUIRE((child = fork()) != -1);
4227	if (child == 0) {
4228		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4229		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4230
4231		sigemptyset(&intmask);
4232		sigaddset(&intmask, sigmasked);
4233		sigprocmask(SIG_BLOCK, &intmask, NULL);
4234
4235		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4236		FORKEE_ASSERT(raise(sigval) == 0);
4237
4238		DPRINTF("Before calling execve(2) from child\n");
4239		execlp("/bin/echo", "/bin/echo", NULL);
4240
4241		/* NOTREACHED */
4242		FORKEE_ASSERTX(0 && "Not reached");
4243	}
4244	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4245
4246	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4247	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4248
4249	validate_status_stopped(status, sigval);
4250
4251	DPRINTF("Before resuming the child process where it left off and "
4252	    "without signal to be sent\n");
4253	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4254
4255	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4256	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4257
4258	validate_status_stopped(status, sigmasked);
4259
4260	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4261	SYSCALL_REQUIRE(
4262	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4263
4264	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4265	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4266	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4267	    info.psi_siginfo.si_errno);
4268
4269	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
4270	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
4271
4272	DPRINTF("Before resuming the child process where it left off and "
4273	    "without signal to be sent\n");
4274	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4275
4276	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4277	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4278
4279	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4280	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4281}
4282
4283#if defined(TWAIT_HAVE_PID)
4284ATF_TC(signal6);
4285ATF_TC_HEAD(signal6, tc)
4286{
4287	atf_tc_set_md_var(tc, "timeout", "5");
4288	atf_tc_set_md_var(tc, "descr",
4289	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4290	    "catching PTRACE_FORK breakpoint");
4291}
4292
4293ATF_TC_BODY(signal6, tc)
4294{
4295	const int exitval = 5;
4296	const int exitval2 = 15;
4297	const int sigval = SIGSTOP;
4298	const int sigmasked = SIGTRAP;
4299	pid_t child, child2, wpid;
4300#if defined(TWAIT_HAVE_STATUS)
4301	int status;
4302#endif
4303	sigset_t intmask;
4304	ptrace_state_t state;
4305	const int slen = sizeof(state);
4306	ptrace_event_t event;
4307	const int elen = sizeof(event);
4308
4309	atf_tc_expect_fail("PR kern/51918");
4310
4311	DPRINTF("Before forking process PID=%d\n", getpid());
4312	SYSCALL_REQUIRE((child = fork()) != -1);
4313	if (child == 0) {
4314		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4315		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4316
4317		sigemptyset(&intmask);
4318		sigaddset(&intmask, sigmasked);
4319		sigprocmask(SIG_BLOCK, &intmask, NULL);
4320
4321		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4322		FORKEE_ASSERT(raise(sigval) == 0);
4323
4324		FORKEE_ASSERT((child2 = fork()) != -1);
4325
4326		if (child2 == 0)
4327			_exit(exitval2);
4328
4329		FORKEE_REQUIRE_SUCCESS
4330			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
4331
4332		forkee_status_exited(status, exitval2);
4333
4334		DPRINTF("Before exiting of the child process\n");
4335		_exit(exitval);
4336	}
4337	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4338
4339	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4340	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4341
4342	validate_status_stopped(status, sigval);
4343
4344	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
4345	event.pe_set_event = PTRACE_FORK;
4346	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
4347
4348	DPRINTF("Before resuming the child process where it left off and "
4349	    "without signal to be sent\n");
4350	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4351
4352	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4353	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4354
4355	validate_status_stopped(status, sigmasked);
4356
4357	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
4358	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
4359
4360	child2 = state.pe_other_pid;
4361	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
4362
4363	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
4364	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
4365	    child2);
4366
4367	validate_status_stopped(status, SIGTRAP);
4368
4369	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
4370	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
4371	ATF_REQUIRE_EQ(state.pe_other_pid, child);
4372
4373	DPRINTF("Before resuming the forkee process where it left off and "
4374	    "without signal to be sent\n");
4375	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
4376
4377	DPRINTF("Before resuming the child process where it left off and "
4378	    "without signal to be sent\n");
4379	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4380
4381	DPRINTF("Before calling %s() for the forkee - expected exited\n",
4382	    TWAIT_FNAME);
4383	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
4384	    child2);
4385
4386	validate_status_exited(status, exitval2);
4387
4388	DPRINTF("Before calling %s() for the forkee - expected no process\n",
4389	    TWAIT_FNAME);
4390	TWAIT_REQUIRE_FAILURE(ECHILD,
4391	    wpid = TWAIT_GENERIC(child2, &status, 0));
4392
4393	DPRINTF("Before calling %s() for the child - expected stopped "
4394	    "SIGCHLD\n", TWAIT_FNAME);
4395	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4396
4397	validate_status_stopped(status, SIGCHLD);
4398
4399	DPRINTF("Before resuming the child process where it left off and "
4400	    "without signal to be sent\n");
4401	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4402
4403	DPRINTF("Before calling %s() for the child - expected exited\n",
4404	    TWAIT_FNAME);
4405	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4406
4407	validate_status_exited(status, exitval);
4408
4409	DPRINTF("Before calling %s() for the child - expected no process\n",
4410	    TWAIT_FNAME);
4411	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4412}
4413#endif
4414
4415#if defined(TWAIT_HAVE_PID)
4416ATF_TC(signal7);
4417ATF_TC_HEAD(signal7, tc)
4418{
4419	atf_tc_set_md_var(tc, "descr",
4420	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4421	    "catching PTRACE_VFORK breakpoint");
4422}
4423
4424ATF_TC_BODY(signal7, tc)
4425{
4426	const int exitval = 5;
4427	const int exitval2 = 15;
4428	const int sigval = SIGSTOP;
4429	const int sigmasked = SIGTRAP;
4430	pid_t child, child2, wpid;
4431#if defined(TWAIT_HAVE_STATUS)
4432	int status;
4433#endif
4434	sigset_t intmask;
4435	ptrace_state_t state;
4436	const int slen = sizeof(state);
4437	ptrace_event_t event;
4438	const int elen = sizeof(event);
4439
4440	atf_tc_expect_fail("PR kern/51918");
4441
4442	DPRINTF("Before forking process PID=%d\n", getpid());
4443	SYSCALL_REQUIRE((child = fork()) != -1);
4444	if (child == 0) {
4445		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4446		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4447
4448		sigemptyset(&intmask);
4449		sigaddset(&intmask, sigmasked);
4450		sigprocmask(SIG_BLOCK, &intmask, NULL);
4451
4452		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4453		FORKEE_ASSERT(raise(sigval) == 0);
4454
4455		FORKEE_ASSERT((child2 = fork()) != -1);
4456
4457		if (child2 == 0)
4458			_exit(exitval2);
4459
4460		FORKEE_REQUIRE_SUCCESS
4461			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
4462
4463		forkee_status_exited(status, exitval2);
4464
4465		DPRINTF("Before exiting of the child process\n");
4466		_exit(exitval);
4467	}
4468	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4469
4470	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4471	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4472
4473	validate_status_stopped(status, sigval);
4474
4475	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
4476	event.pe_set_event = PTRACE_VFORK;
4477	SYSCALL_REQUIRE(
4478	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
4479	    errno == ENOTSUP);
4480
4481	DPRINTF("Before resuming the child process where it left off and "
4482	    "without signal to be sent\n");
4483	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4484
4485	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4486	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4487
4488	validate_status_stopped(status, sigmasked);
4489
4490	SYSCALL_REQUIRE(
4491	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
4492	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
4493
4494	child2 = state.pe_other_pid;
4495	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
4496
4497	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
4498	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
4499	    child2);
4500
4501	validate_status_stopped(status, SIGTRAP);
4502
4503	SYSCALL_REQUIRE(
4504	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
4505	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
4506	ATF_REQUIRE_EQ(state.pe_other_pid, child);
4507
4508	DPRINTF("Before resuming the forkee process where it left off and "
4509	    "without signal to be sent\n");
4510	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
4511
4512	DPRINTF("Before resuming the child process where it left off and "
4513	    "without signal to be sent\n");
4514	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4515
4516	DPRINTF("Before calling %s() for the forkee - expected exited\n",
4517	    TWAIT_FNAME);
4518	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
4519	    child2);
4520
4521	validate_status_exited(status, exitval2);
4522
4523	DPRINTF("Before calling %s() for the forkee - expected no process\n",
4524	    TWAIT_FNAME);
4525	TWAIT_REQUIRE_FAILURE(ECHILD,
4526	    wpid = TWAIT_GENERIC(child2, &status, 0));
4527
4528	DPRINTF("Before calling %s() for the child - expected stopped "
4529	    "SIGCHLD\n", TWAIT_FNAME);
4530	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4531
4532	validate_status_stopped(status, SIGCHLD);
4533
4534	DPRINTF("Before resuming the child process where it left off and "
4535	    "without signal to be sent\n");
4536	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4537
4538	DPRINTF("Before calling %s() for the child - expected exited\n",
4539	    TWAIT_FNAME);
4540	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4541
4542	validate_status_exited(status, exitval);
4543
4544	DPRINTF("Before calling %s() for the child - expected no process\n",
4545	    TWAIT_FNAME);
4546	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4547}
4548#endif
4549
4550ATF_TC(signal8);
4551ATF_TC_HEAD(signal8, tc)
4552{
4553	atf_tc_set_md_var(tc, "descr",
4554	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4555	    "catching PTRACE_VFORK_DONE breakpoint");
4556}
4557
4558ATF_TC_BODY(signal8, tc)
4559{
4560	const int exitval = 5;
4561	const int exitval2 = 15;
4562	const int sigval = SIGSTOP;
4563	const int sigmasked = SIGTRAP;
4564	pid_t child, child2, wpid;
4565#if defined(TWAIT_HAVE_STATUS)
4566	int status;
4567#endif
4568	sigset_t intmask;
4569	ptrace_state_t state;
4570	const int slen = sizeof(state);
4571	ptrace_event_t event;
4572	const int elen = sizeof(event);
4573
4574	atf_tc_expect_fail("PR kern/51918");
4575
4576	DPRINTF("Before forking process PID=%d\n", getpid());
4577	SYSCALL_REQUIRE((child = fork()) != -1);
4578	if (child == 0) {
4579		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4580		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4581
4582		sigemptyset(&intmask);
4583		sigaddset(&intmask, sigmasked);
4584		sigprocmask(SIG_BLOCK, &intmask, NULL);
4585
4586		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4587		FORKEE_ASSERT(raise(sigval) == 0);
4588
4589		FORKEE_ASSERT((child2 = vfork()) != -1);
4590
4591		if (child2 == 0)
4592			_exit(exitval2);
4593
4594		FORKEE_REQUIRE_SUCCESS
4595			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
4596
4597		forkee_status_exited(status, exitval2);
4598
4599		DPRINTF("Before exiting of the child process\n");
4600		_exit(exitval);
4601	}
4602	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4603
4604	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4605	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4606
4607	validate_status_stopped(status, sigval);
4608
4609	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
4610	    child);
4611	event.pe_set_event = PTRACE_VFORK_DONE;
4612	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
4613
4614	DPRINTF("Before resuming the child process where it left off and "
4615	    "without signal to be sent\n");
4616	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4617
4618	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4619	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4620
4621	validate_status_stopped(status, sigmasked);
4622
4623	SYSCALL_REQUIRE(
4624	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
4625	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
4626
4627	child2 = state.pe_other_pid;
4628	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
4629
4630	DPRINTF("Before resuming the child process where it left off and "
4631	    "without signal to be sent\n");
4632	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4633
4634	DPRINTF("Before calling %s() for the child - expected stopped "
4635	    "SIGCHLD\n", TWAIT_FNAME);
4636	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4637
4638	validate_status_stopped(status, SIGCHLD);
4639
4640	DPRINTF("Before resuming the child process where it left off and "
4641	    "without signal to be sent\n");
4642	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4643
4644	DPRINTF("Before calling %s() for the child - expected exited\n",
4645	    TWAIT_FNAME);
4646	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4647
4648	validate_status_exited(status, exitval);
4649
4650	DPRINTF("Before calling %s() for the child - expected no process\n",
4651	    TWAIT_FNAME);
4652	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4653}
4654
4655volatile lwpid_t the_lwp_id = 0;
4656
4657static void
4658lwp_main_func(void *arg)
4659{
4660	the_lwp_id = _lwp_self();
4661	_lwp_exit();
4662}
4663
4664ATF_TC(signal9);
4665ATF_TC_HEAD(signal9, tc)
4666{
4667	atf_tc_set_md_var(tc, "descr",
4668	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4669	    "catching PTRACE_LWP_CREATE breakpoint");
4670}
4671
4672ATF_TC_BODY(signal9, tc)
4673{
4674	const int exitval = 5;
4675	const int sigval = SIGSTOP;
4676	const int sigmasked = SIGTRAP;
4677	pid_t child, wpid;
4678#if defined(TWAIT_HAVE_STATUS)
4679	int status;
4680#endif
4681	sigset_t intmask;
4682	ptrace_state_t state;
4683	const int slen = sizeof(state);
4684	ptrace_event_t event;
4685	const int elen = sizeof(event);
4686	ucontext_t uc;
4687	lwpid_t lid;
4688	static const size_t ssize = 16*1024;
4689	void *stack;
4690
4691	atf_tc_expect_fail("PR kern/51918");
4692
4693	DPRINTF("Before forking process PID=%d\n", getpid());
4694	SYSCALL_REQUIRE((child = fork()) != -1);
4695	if (child == 0) {
4696		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4697		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4698
4699		sigemptyset(&intmask);
4700		sigaddset(&intmask, sigmasked);
4701		sigprocmask(SIG_BLOCK, &intmask, NULL);
4702
4703		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4704		FORKEE_ASSERT(raise(sigval) == 0);
4705
4706		DPRINTF("Before allocating memory for stack in child\n");
4707		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
4708
4709		DPRINTF("Before making context for new lwp in child\n");
4710		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
4711
4712		DPRINTF("Before creating new in child\n");
4713		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
4714
4715		DPRINTF("Before waiting for lwp %d to exit\n", lid);
4716		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
4717
4718		DPRINTF("Before verifying that reported %d and running lid %d "
4719		    "are the same\n", lid, the_lwp_id);
4720		FORKEE_ASSERT_EQ(lid, the_lwp_id);
4721
4722		DPRINTF("Before exiting of the child process\n");
4723		_exit(exitval);
4724	}
4725	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4726
4727	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4728	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4729
4730	validate_status_stopped(status, sigval);
4731
4732	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
4733	event.pe_set_event = PTRACE_LWP_CREATE;
4734	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
4735
4736	DPRINTF("Before resuming the child process where it left off and "
4737	    "without signal to be sent\n");
4738	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4739
4740	DPRINTF("Before calling %s() for the child - expected stopped "
4741	    "SIGTRAP\n", TWAIT_FNAME);
4742	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4743
4744	validate_status_stopped(status, sigmasked);
4745
4746	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
4747
4748	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
4749
4750	lid = state.pe_lwp;
4751	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
4752
4753	DPRINTF("Before resuming the child process where it left off and "
4754	    "without signal to be sent\n");
4755	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4756
4757	DPRINTF("Before calling %s() for the child - expected exited\n",
4758	    TWAIT_FNAME);
4759	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4760
4761	validate_status_exited(status, exitval);
4762
4763	DPRINTF("Before calling %s() for the child - expected no process\n",
4764	    TWAIT_FNAME);
4765	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4766}
4767
4768ATF_TC(signal10);
4769ATF_TC_HEAD(signal10, tc)
4770{
4771	atf_tc_set_md_var(tc, "descr",
4772	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
4773	    "catching PTRACE_LWP_EXIT breakpoint");
4774}
4775
4776ATF_TC_BODY(signal10, tc)
4777{
4778	const int exitval = 5;
4779	const int sigval = SIGSTOP;
4780	const int sigmasked = SIGTRAP;
4781	pid_t child, wpid;
4782#if defined(TWAIT_HAVE_STATUS)
4783	int status;
4784#endif
4785	sigset_t intmask;
4786	ptrace_state_t state;
4787	const int slen = sizeof(state);
4788	ptrace_event_t event;
4789	const int elen = sizeof(event);
4790	ucontext_t uc;
4791	lwpid_t lid;
4792	static const size_t ssize = 16*1024;
4793	void *stack;
4794
4795	atf_tc_expect_fail("PR kern/51918");
4796
4797	DPRINTF("Before forking process PID=%d\n", getpid());
4798	SYSCALL_REQUIRE((child = fork()) != -1);
4799	if (child == 0) {
4800		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4801		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4802
4803		sigemptyset(&intmask);
4804		sigaddset(&intmask, sigmasked);
4805		sigprocmask(SIG_BLOCK, &intmask, NULL);
4806
4807		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4808		FORKEE_ASSERT(raise(sigval) == 0);
4809
4810		DPRINTF("Before allocating memory for stack in child\n");
4811		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
4812
4813		DPRINTF("Before making context for new lwp in child\n");
4814		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
4815
4816		DPRINTF("Before creating new in child\n");
4817		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
4818
4819		DPRINTF("Before waiting for lwp %d to exit\n", lid);
4820		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
4821
4822		DPRINTF("Before verifying that reported %d and running lid %d "
4823		    "are the same\n", lid, the_lwp_id);
4824		FORKEE_ASSERT_EQ(lid, the_lwp_id);
4825
4826		DPRINTF("Before exiting of the child process\n");
4827		_exit(exitval);
4828	}
4829	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4830
4831	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4832	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4833
4834	validate_status_stopped(status, sigval);
4835
4836	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
4837	event.pe_set_event = PTRACE_LWP_EXIT;
4838	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
4839
4840	DPRINTF("Before resuming the child process where it left off and "
4841	    "without signal to be sent\n");
4842	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4843
4844	DPRINTF("Before calling %s() for the child - expected stopped "
4845	    "SIGTRAP\n", TWAIT_FNAME);
4846	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4847
4848	validate_status_stopped(status, sigmasked);
4849
4850	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
4851
4852	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
4853
4854	lid = state.pe_lwp;
4855	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
4856
4857	DPRINTF("Before resuming the child process where it left off and "
4858	    "without signal to be sent\n");
4859	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4860
4861	DPRINTF("Before calling %s() for the child - expected exited\n",
4862	    TWAIT_FNAME);
4863	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4864
4865	validate_status_exited(status, exitval);
4866
4867	DPRINTF("Before calling %s() for the child - expected no process\n",
4868	    TWAIT_FNAME);
4869	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4870}
4871
4872static void
4873lwp_main_stop(void *arg)
4874{
4875	the_lwp_id = _lwp_self();
4876
4877	raise(SIGTRAP);
4878
4879	_lwp_exit();
4880}
4881
4882ATF_TC(suspend1);
4883ATF_TC_HEAD(suspend1, tc)
4884{
4885	atf_tc_set_md_var(tc, "descr",
4886	    "Verify that a thread can be suspended by a debugger and later "
4887	    "resumed by a tracee");
4888}
4889
4890ATF_TC_BODY(suspend1, tc)
4891{
4892	const int exitval = 5;
4893	const int sigval = SIGSTOP;
4894	pid_t child, wpid;
4895#if defined(TWAIT_HAVE_STATUS)
4896	int status;
4897#endif
4898	ucontext_t uc;
4899	lwpid_t lid;
4900	static const size_t ssize = 16*1024;
4901	void *stack;
4902	struct ptrace_lwpinfo pl;
4903	struct ptrace_siginfo psi;
4904	volatile int go = 0;
4905
4906	// Feature pending for refactoring
4907	atf_tc_expect_fail("PR kern/51995");
4908
4909	// Hangs with qemu
4910	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
4911
4912	DPRINTF("Before forking process PID=%d\n", getpid());
4913	SYSCALL_REQUIRE((child = fork()) != -1);
4914	if (child == 0) {
4915		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4916		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4917
4918		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4919		FORKEE_ASSERT(raise(sigval) == 0);
4920
4921		DPRINTF("Before allocating memory for stack in child\n");
4922		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
4923
4924		DPRINTF("Before making context for new lwp in child\n");
4925		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
4926
4927		DPRINTF("Before creating new in child\n");
4928		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
4929
4930		while (go == 0)
4931			continue;
4932
4933		raise(SIGINT);
4934
4935		FORKEE_ASSERT(_lwp_continue(lid) == 0);
4936
4937		DPRINTF("Before waiting for lwp %d to exit\n", lid);
4938		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
4939
4940		DPRINTF("Before verifying that reported %d and running lid %d "
4941		    "are the same\n", lid, the_lwp_id);
4942		FORKEE_ASSERT_EQ(lid, the_lwp_id);
4943
4944		DPRINTF("Before exiting of the child process\n");
4945		_exit(exitval);
4946	}
4947	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4948
4949	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4950	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4951
4952	validate_status_stopped(status, sigval);
4953
4954	DPRINTF("Before resuming the child process where it left off and "
4955	    "without signal to be sent\n");
4956	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4957
4958	DPRINTF("Before calling %s() for the child - expected stopped "
4959	    "SIGTRAP\n", TWAIT_FNAME);
4960	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4961
4962	validate_status_stopped(status, SIGTRAP);
4963
4964	DPRINTF("Before reading siginfo and lwpid_t\n");
4965	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
4966
4967	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
4968	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
4969
4970        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
4971	    child, getpid());
4972	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
4973
4974	DPRINTF("Before resuming the child process where it left off and "
4975	    "without signal to be sent\n");
4976	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4977
4978	DPRINTF("Before calling %s() for the child - expected stopped "
4979	    "SIGINT\n", TWAIT_FNAME);
4980	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4981
4982	validate_status_stopped(status, SIGINT);
4983
4984	pl.pl_lwpid = 0;
4985
4986	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
4987	while (pl.pl_lwpid != 0) {
4988
4989		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
4990		switch (pl.pl_lwpid) {
4991		case 1:
4992			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
4993			break;
4994		case 2:
4995			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
4996			break;
4997		}
4998	}
4999
5000	DPRINTF("Before resuming the child process where it left off and "
5001	    "without signal to be sent\n");
5002	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5003
5004	DPRINTF("Before calling %s() for the child - expected exited\n",
5005	    TWAIT_FNAME);
5006	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5007
5008	validate_status_exited(status, exitval);
5009
5010	DPRINTF("Before calling %s() for the child - expected no process\n",
5011	    TWAIT_FNAME);
5012	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5013}
5014
5015ATF_TC(suspend2);
5016ATF_TC_HEAD(suspend2, tc)
5017{
5018	atf_tc_set_md_var(tc, "descr",
5019	    "Verify that the while the only thread within a process is "
5020	    "suspended, the whole process cannot be unstopped");
5021}
5022
5023ATF_TC_BODY(suspend2, tc)
5024{
5025	const int exitval = 5;
5026	const int sigval = SIGSTOP;
5027	pid_t child, wpid;
5028#if defined(TWAIT_HAVE_STATUS)
5029	int status;
5030#endif
5031	struct ptrace_siginfo psi;
5032
5033	// Feature pending for refactoring
5034	atf_tc_expect_fail("PR kern/51995");
5035
5036	// Hangs with qemu
5037	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
5038
5039	DPRINTF("Before forking process PID=%d\n", getpid());
5040	SYSCALL_REQUIRE((child = fork()) != -1);
5041	if (child == 0) {
5042		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5043		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5044
5045		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5046		FORKEE_ASSERT(raise(sigval) == 0);
5047
5048		DPRINTF("Before exiting of the child process\n");
5049		_exit(exitval);
5050	}
5051	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5052
5053	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5054	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5055
5056	validate_status_stopped(status, sigval);
5057
5058	DPRINTF("Before reading siginfo and lwpid_t\n");
5059	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
5060
5061	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
5062	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
5063
5064	DPRINTF("Before resuming the child process where it left off and "
5065	    "without signal to be sent\n");
5066	ATF_REQUIRE_ERRNO(EDEADLK,
5067	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
5068
5069	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
5070	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
5071
5072	DPRINTF("Before resuming the child process where it left off and "
5073	    "without signal to be sent\n");
5074	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5075
5076	DPRINTF("Before calling %s() for the child - expected exited\n",
5077	    TWAIT_FNAME);
5078	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5079
5080	validate_status_exited(status, exitval);
5081
5082	DPRINTF("Before calling %s() for the child - expected no process\n",
5083	    TWAIT_FNAME);
5084	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5085}
5086
5087ATF_TC(resume1);
5088ATF_TC_HEAD(resume1, tc)
5089{
5090	atf_tc_set_md_var(tc, "timeout", "5");
5091	atf_tc_set_md_var(tc, "descr",
5092	    "Verify that a thread can be suspended by a debugger and later "
5093	    "resumed by the debugger");
5094}
5095
5096ATF_TC_BODY(resume1, tc)
5097{
5098	struct msg_fds fds;
5099	const int exitval = 5;
5100	const int sigval = SIGSTOP;
5101	pid_t child, wpid;
5102	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5103#if defined(TWAIT_HAVE_STATUS)
5104	int status;
5105#endif
5106	ucontext_t uc;
5107	lwpid_t lid;
5108	static const size_t ssize = 16*1024;
5109	void *stack;
5110	struct ptrace_lwpinfo pl;
5111	struct ptrace_siginfo psi;
5112
5113	// Feature pending for refactoring
5114	atf_tc_expect_fail("PR kern/51995");
5115
5116	// Hangs with qemu
5117	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
5118
5119	SYSCALL_REQUIRE(msg_open(&fds) == 0);
5120
5121	DPRINTF("Before forking process PID=%d\n", getpid());
5122	SYSCALL_REQUIRE((child = fork()) != -1);
5123	if (child == 0) {
5124		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5125		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5126
5127		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5128		FORKEE_ASSERT(raise(sigval) == 0);
5129
5130		DPRINTF("Before allocating memory for stack in child\n");
5131		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
5132
5133		DPRINTF("Before making context for new lwp in child\n");
5134		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
5135
5136		DPRINTF("Before creating new in child\n");
5137		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
5138
5139		CHILD_TO_PARENT("Message", fds, msg);
5140
5141		raise(SIGINT);
5142
5143		DPRINTF("Before waiting for lwp %d to exit\n", lid);
5144		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
5145
5146		DPRINTF("Before verifying that reported %d and running lid %d "
5147		    "are the same\n", lid, the_lwp_id);
5148		FORKEE_ASSERT_EQ(lid, the_lwp_id);
5149
5150		DPRINTF("Before exiting of the child process\n");
5151		_exit(exitval);
5152	}
5153	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5154
5155	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5156	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5157
5158	validate_status_stopped(status, sigval);
5159
5160	DPRINTF("Before resuming the child process where it left off and "
5161	    "without signal to be sent\n");
5162	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5163
5164	DPRINTF("Before calling %s() for the child - expected stopped "
5165	    "SIGTRAP\n", TWAIT_FNAME);
5166	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5167
5168	validate_status_stopped(status, SIGTRAP);
5169
5170	DPRINTF("Before reading siginfo and lwpid_t\n");
5171	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
5172
5173	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
5174	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
5175
5176	PARENT_FROM_CHILD("Message", fds, msg);
5177
5178	DPRINTF("Before resuming the child process where it left off and "
5179	    "without signal to be sent\n");
5180	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5181
5182	DPRINTF("Before calling %s() for the child - expected stopped "
5183	    "SIGINT\n", TWAIT_FNAME);
5184	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5185
5186	validate_status_stopped(status, SIGINT);
5187
5188	pl.pl_lwpid = 0;
5189
5190	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
5191	while (pl.pl_lwpid != 0) {
5192		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
5193		switch (pl.pl_lwpid) {
5194		case 1:
5195			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
5196			break;
5197		case 2:
5198			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
5199			break;
5200		}
5201	}
5202
5203	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
5204	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
5205
5206	DPRINTF("Before resuming the child process where it left off and "
5207	    "without signal to be sent\n");
5208	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5209
5210	DPRINTF("Before calling %s() for the child - expected exited\n",
5211	    TWAIT_FNAME);
5212	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5213
5214	validate_status_exited(status, exitval);
5215
5216	DPRINTF("Before calling %s() for the child - expected no process\n",
5217	    TWAIT_FNAME);
5218	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5219
5220	msg_close(&fds);
5221
5222	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
5223	sleep(10);
5224}
5225
5226ATF_TC(syscall1);
5227ATF_TC_HEAD(syscall1, tc)
5228{
5229	atf_tc_set_md_var(tc, "descr",
5230	    "Verify that getpid(2) can be traced with PT_SYSCALL");
5231}
5232
5233ATF_TC_BODY(syscall1, tc)
5234{
5235	const int exitval = 5;
5236	const int sigval = SIGSTOP;
5237	pid_t child, wpid;
5238#if defined(TWAIT_HAVE_STATUS)
5239	int status;
5240#endif
5241	struct ptrace_siginfo info;
5242	memset(&info, 0, sizeof(info));
5243
5244	DPRINTF("Before forking process PID=%d\n", getpid());
5245	SYSCALL_REQUIRE((child = fork()) != -1);
5246	if (child == 0) {
5247		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5248		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5249
5250		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5251		FORKEE_ASSERT(raise(sigval) == 0);
5252
5253		syscall(SYS_getpid);
5254
5255		DPRINTF("Before exiting of the child process\n");
5256		_exit(exitval);
5257	}
5258	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5259
5260	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5261	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5262
5263	validate_status_stopped(status, sigval);
5264
5265	DPRINTF("Before resuming the child process where it left off and "
5266	    "without signal to be sent\n");
5267	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
5268
5269	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5270	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5271
5272	validate_status_stopped(status, SIGTRAP);
5273
5274	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5275	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5276
5277	DPRINTF("Before checking siginfo_t and lwpid\n");
5278	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
5279	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
5280	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
5281
5282	DPRINTF("Before resuming the child process where it left off and "
5283	    "without signal to be sent\n");
5284	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
5285
5286	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5287	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5288
5289	validate_status_stopped(status, SIGTRAP);
5290
5291	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5292	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5293
5294	DPRINTF("Before checking siginfo_t and lwpid\n");
5295	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
5296	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
5297	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
5298
5299	DPRINTF("Before resuming the child process where it left off and "
5300	    "without signal to be sent\n");
5301	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5302
5303	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5304	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5305
5306	validate_status_exited(status, exitval);
5307
5308	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5309	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5310}
5311
5312ATF_TC(syscallemu1);
5313ATF_TC_HEAD(syscallemu1, tc)
5314{
5315	atf_tc_set_md_var(tc, "descr",
5316	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
5317}
5318
5319ATF_TC_BODY(syscallemu1, tc)
5320{
5321	const int exitval = 5;
5322	const int sigval = SIGSTOP;
5323	pid_t child, wpid;
5324#if defined(TWAIT_HAVE_STATUS)
5325	int status;
5326#endif
5327
5328#if defined(__sparc__) && !defined(__sparc64__)
5329	/* syscallemu does not work on sparc (32-bit) */
5330	atf_tc_expect_fail("PR kern/52166");
5331#endif
5332
5333	DPRINTF("Before forking process PID=%d\n", getpid());
5334	SYSCALL_REQUIRE((child = fork()) != -1);
5335	if (child == 0) {
5336		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5337		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5338
5339		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5340		FORKEE_ASSERT(raise(sigval) == 0);
5341
5342		syscall(SYS_exit, 100);
5343
5344		DPRINTF("Before exiting of the child process\n");
5345		_exit(exitval);
5346	}
5347	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5348
5349	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5350	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5351
5352	validate_status_stopped(status, sigval);
5353
5354	DPRINTF("Before resuming the child process where it left off and "
5355	    "without signal to be sent\n");
5356	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
5357
5358	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5359	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5360
5361	validate_status_stopped(status, SIGTRAP);
5362
5363	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
5364	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
5365
5366	DPRINTF("Before resuming the child process where it left off and "
5367	    "without signal to be sent\n");
5368	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
5369
5370	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5371	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5372
5373	validate_status_stopped(status, SIGTRAP);
5374
5375	DPRINTF("Before resuming the child process where it left off and "
5376	    "without signal to be sent\n");
5377	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5378
5379	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5380	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5381
5382	validate_status_exited(status, exitval);
5383
5384	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5385	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5386}
5387
5388#include "t_ptrace_amd64_wait.h"
5389#include "t_ptrace_i386_wait.h"
5390#include "t_ptrace_x86_wait.h"
5391
5392ATF_TP_ADD_TCS(tp)
5393{
5394	setvbuf(stdout, NULL, _IONBF, 0);
5395	setvbuf(stderr, NULL, _IONBF, 0);
5396
5397	ATF_TP_ADD_TC(tp, traceme_raise1);
5398	ATF_TP_ADD_TC(tp, traceme_raise2);
5399	ATF_TP_ADD_TC(tp, traceme_raise3);
5400	ATF_TP_ADD_TC(tp, traceme_raise4);
5401	ATF_TP_ADD_TC(tp, traceme_raise5);
5402	ATF_TP_ADD_TC(tp, traceme_raise6);
5403	ATF_TP_ADD_TC(tp, traceme_raise7);
5404	ATF_TP_ADD_TC(tp, traceme_raise8);
5405	ATF_TP_ADD_TC(tp, traceme_raise9);
5406	ATF_TP_ADD_TC(tp, traceme_raise10);
5407
5408	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1);
5409	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2);
5410	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3);
5411	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4);
5412	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5);
5413	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6);
5414	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7);
5415	ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8);
5416
5417	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1);
5418	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2);
5419	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3);
5420	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4);
5421	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5);
5422	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6);
5423	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7);
5424	ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8);
5425
5426	ATF_TP_ADD_TC(tp, traceme_crash_trap);
5427	ATF_TP_ADD_TC(tp, traceme_crash_segv);
5428	ATF_TP_ADD_TC(tp, traceme_crash_ill);
5429	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
5430	ATF_TP_ADD_TC(tp, traceme_crash_bus);
5431
5432	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
5433	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
5434	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
5435	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4);
5436	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5);
5437	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6);
5438	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7);
5439	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8);
5440
5441	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
5442	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
5443	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
5444	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4);
5445	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5);
5446	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6);
5447	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7);
5448	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8);
5449
5450	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
5451	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
5452	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
5453	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4);
5454	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5);
5455	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6);
5456	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7);
5457	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8);
5458
5459	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
5460	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
5461	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
5462	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
5463	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
5464	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6);
5465	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7);
5466	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8);
5467	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9);
5468	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10);
5469
5470	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
5471
5472	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
5473	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
5474	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
5475	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
5476	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
5477	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
5478	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
5479	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
5480	ATF_TP_ADD_TC(tp, traceme_vfork_raise9);
5481	ATF_TP_ADD_TC(tp, traceme_vfork_raise10);
5482	ATF_TP_ADD_TC(tp, traceme_vfork_raise11);
5483	ATF_TP_ADD_TC(tp, traceme_vfork_raise12);
5484	ATF_TP_ADD_TC(tp, traceme_vfork_raise13);
5485
5486	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
5487	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
5488	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
5489	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
5490	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
5491
5492	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
5493
5494	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
5495	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
5496	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
5497	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
5498	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
5499
5500	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
5501	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
5502	ATF_TP_ADD_TC_HAVE_PID(tp,
5503		unrelated_tracer_sees_terminaton_before_the_parent);
5504	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
5505
5506	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
5507	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
5508
5509	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
5510	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
5511
5512	ATF_TP_ADD_TC_HAVE_PID(tp,
5513		tracee_sees_its_original_parent_getppid);
5514	ATF_TP_ADD_TC_HAVE_PID(tp,
5515		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
5516	ATF_TP_ADD_TC_HAVE_PID(tp,
5517		tracee_sees_its_original_parent_procfs_status);
5518
5519	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
5520	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
5521	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
5522	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
5523	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
5524	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
5525
5526	ATF_TP_ADD_TC(tp, fork1);
5527	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
5528	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
5529	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
5530	ATF_TP_ADD_TC(tp, fork5);
5531	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
5532	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
5533	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
5534
5535	ATF_TP_ADD_TC(tp, vfork1);
5536	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
5537	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
5538	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
5539	ATF_TP_ADD_TC(tp, vfork5);
5540	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
5541// thes tests hang on SMP machines, disable them for now
5542//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
5543//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
5544
5545	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
5546	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
5547	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
5548	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
5549
5550	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
5551	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
5552	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
5553	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
5554
5555	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
5556	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
5557	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
5558	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
5559
5560	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
5561	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
5562	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
5563	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
5564
5565	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
5566	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
5567	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
5568	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
5569
5570	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
5571	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
5572	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
5573	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
5574
5575	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
5576	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
5577	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
5578	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
5579
5580	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
5581	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
5582	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
5583	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
5584
5585	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
5586	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
5587	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
5588	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
5589
5590	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
5591	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
5592	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
5593	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
5594
5595	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
5596
5597	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1);
5598	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2);
5599	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3);
5600	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4);
5601	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5);
5602	ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6);
5603
5604	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1);
5605	ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2);
5606
5607	ATF_TP_ADD_TC_PT_STEP(tp, step1);
5608	ATF_TP_ADD_TC_PT_STEP(tp, step2);
5609	ATF_TP_ADD_TC_PT_STEP(tp, step3);
5610	ATF_TP_ADD_TC_PT_STEP(tp, step4);
5611
5612	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
5613	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
5614	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
5615	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
5616
5617	ATF_TP_ADD_TC(tp, kill1);
5618	ATF_TP_ADD_TC(tp, kill2);
5619	ATF_TP_ADD_TC(tp, kill3);
5620
5621	ATF_TP_ADD_TC(tp, traceme_lwpinfo0);
5622	ATF_TP_ADD_TC(tp, traceme_lwpinfo1);
5623	ATF_TP_ADD_TC(tp, traceme_lwpinfo2);
5624	ATF_TP_ADD_TC(tp, traceme_lwpinfo3);
5625
5626	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0);
5627	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1);
5628	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);
5629	ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3);
5630
5631	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
5632	ATF_TP_ADD_TC(tp, siginfo_set_faked);
5633
5634	ATF_TP_ADD_TC(tp, traceme_exec);
5635
5636	ATF_TP_ADD_TC(tp, trace_thread1);
5637	ATF_TP_ADD_TC(tp, trace_thread2);
5638	ATF_TP_ADD_TC(tp, trace_thread3);
5639	ATF_TP_ADD_TC(tp, trace_thread4);
5640
5641	ATF_TP_ADD_TC(tp, signal_mask_unrelated);
5642
5643	ATF_TP_ADD_TC(tp, signal3);
5644	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
5645	ATF_TP_ADD_TC(tp, signal5);
5646	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
5647	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
5648	ATF_TP_ADD_TC(tp, signal8);
5649	ATF_TP_ADD_TC(tp, signal9);
5650	ATF_TP_ADD_TC(tp, signal10);
5651
5652	ATF_TP_ADD_TC(tp, suspend1);
5653	ATF_TP_ADD_TC(tp, suspend2);
5654
5655	ATF_TP_ADD_TC(tp, resume1);
5656
5657	ATF_TP_ADD_TC(tp, syscall1);
5658
5659	ATF_TP_ADD_TC(tp, syscallemu1);
5660
5661	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
5662	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
5663	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
5664
5665	return atf_no_error();
5666}
5667