t_ptrace_wait.c revision 1.60
11.60Skre/*	$NetBSD: t_ptrace_wait.c,v 1.60 2018/05/30 05:09:11 kre Exp $	*/
21.1Skamil
31.1Skamil/*-
41.1Skamil * Copyright (c) 2016 The NetBSD Foundation, Inc.
51.1Skamil * All rights reserved.
61.1Skamil *
71.1Skamil * Redistribution and use in source and binary forms, with or without
81.1Skamil * modification, are permitted provided that the following conditions
91.1Skamil * are met:
101.1Skamil * 1. Redistributions of source code must retain the above copyright
111.1Skamil *    notice, this list of conditions and the following disclaimer.
121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil *    notice, this list of conditions and the following disclaimer in the
141.1Skamil *    documentation and/or other materials provided with the distribution.
151.1Skamil *
161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil * POSSIBILITY OF SUCH DAMAGE.
271.1Skamil */
281.1Skamil
291.1Skamil#include <sys/cdefs.h>
301.60Skre__RCSID("$NetBSD: t_ptrace_wait.c,v 1.60 2018/05/30 05:09:11 kre Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.1Skamil#include <sched.h>
471.1Skamil#include <signal.h>
481.1Skamil#include <stdint.h>
491.1Skamil#include <stdio.h>
501.1Skamil#include <stdlib.h>
511.1Skamil#include <strings.h>
521.26Skamil#include <time.h>
531.1Skamil#include <unistd.h>
541.1Skamil
551.1Skamil#include <atf-c.h>
561.1Skamil
571.1Skamil#include "h_macros.h"
581.1Skamil
591.1Skamil#include "t_ptrace_wait.h"
601.1Skamil#include "msg.h"
611.1Skamil
621.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
631.13Schristos    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, sizeof(msg)) == 0)
641.1Skamil
651.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
661.1Skamil    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
671.1Skamil
681.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
691.1Skamil    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
721.13Schristos    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
731.13Schristos
741.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
751.13Schristos    strerror(errno))
761.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
771.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
781.13Schristos
791.13Schristosstatic int debug = 0;
801.13Schristos
811.13Schristos#define DPRINTF(a, ...)	do  \
821.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
831.13Schristos    while (/*CONSTCOND*/0)
841.1Skamil
851.34Skamil/// ----------------------------------------------------------------------------
861.34Skamil
871.33Skamilstatic void
881.33Skamiltraceme_raise(int sigval)
891.1Skamil{
901.1Skamil	const int exitval = 5;
911.1Skamil	pid_t child, wpid;
921.1Skamil#if defined(TWAIT_HAVE_STATUS)
931.1Skamil	int status;
941.1Skamil#endif
951.1Skamil
961.45Skamil	struct ptrace_siginfo info;
971.45Skamil	memset(&info, 0, sizeof(info));
981.45Skamil
991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1011.1Skamil	if (child == 0) {
1021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1041.1Skamil
1051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1071.1Skamil
1081.36Skamil		switch (sigval) {
1091.36Skamil		case SIGKILL:
1101.36Skamil			/* NOTREACHED */
1111.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1121.36Skamil		default:
1131.36Skamil			DPRINTF("Before exiting of the child process\n");
1141.36Skamil			_exit(exitval);
1151.36Skamil		}
1161.1Skamil	}
1171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1181.1Skamil
1191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1211.1Skamil
1221.36Skamil	switch (sigval) {
1231.36Skamil	case SIGKILL:
1241.36Skamil		validate_status_signaled(status, sigval, 0);
1251.36Skamil		break;
1261.36Skamil	default:
1271.36Skamil		validate_status_stopped(status, sigval);
1281.1Skamil
1291.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1301.45Skamil		        "child\n");
1311.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1321.45Skamil		                       sizeof(info)) != -1);
1331.45Skamil
1341.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1351.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1361.45Skamil		        "si_errno=%#x\n",
1371.45Skamil		        info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1381.45Skamil		        info.psi_siginfo.si_errno);
1391.45Skamil
1401.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1411.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1421.45Skamil
1431.36Skamil		DPRINTF("Before resuming the child process where it left off "
1441.36Skamil		    "and without signal to be sent\n");
1451.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1461.1Skamil
1471.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1481.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1491.36Skamil		                      child);
1501.36Skamil		break;
1511.36Skamil	}
1521.1Skamil
1531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1551.1Skamil}
1561.1Skamil
1571.33Skamil#define TRACEME_RAISE(test, sig)						\
1581.33SkamilATF_TC(test);									\
1591.33SkamilATF_TC_HEAD(test, tc)								\
1601.33Skamil{										\
1611.33Skamil	atf_tc_set_md_var(tc, "descr",						\
1621.33Skamil	    "Verify " #sig " followed by _exit(2) in a child");			\
1631.33Skamil}										\
1641.33Skamil										\
1651.33SkamilATF_TC_BODY(test, tc)								\
1661.33Skamil{										\
1671.33Skamil										\
1681.33Skamil	traceme_raise(sig);							\
1691.33Skamil}
1701.33Skamil
1711.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1721.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1731.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1741.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1751.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1761.33Skamil
1771.34Skamil/// ----------------------------------------------------------------------------
1781.1Skamil
1791.1Skamilstatic void
1801.59Skamiltraceme_crash(int sig)
1811.59Skamil{
1821.59Skamil	pid_t child, wpid;
1831.59Skamil#if defined(TWAIT_HAVE_STATUS)
1841.59Skamil	int status;
1851.59Skamil#endif
1861.59Skamil	struct ptrace_siginfo info;
1871.59Skamil	memset(&info, 0, sizeof(info));
1881.59Skamil
1891.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
1901.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
1911.59Skamil	if (child == 0) {
1921.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1931.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1941.59Skamil
1951.59Skamil		DPRINTF("Before executing a trap\n");
1961.59Skamil		switch (sig) {
1971.59Skamil		case SIGTRAP:
1981.59Skamil			trigger_trap();
1991.59Skamil			break;
2001.59Skamil		case SIGSEGV:
2011.59Skamil			trigger_segv();
2021.59Skamil			break;
2031.59Skamil		case SIGILL:
2041.59Skamil			trigger_ill();
2051.59Skamil			break;
2061.59Skamil		case SIGFPE:
2071.59Skamil			trigger_fpe();
2081.59Skamil			break;
2091.59Skamil		case SIGBUS:
2101.59Skamil			trigger_bus();
2111.59Skamil			break;
2121.59Skamil		default:
2131.59Skamil			/* NOTREACHED */
2141.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2151.59Skamil		}
2161.59Skamil
2171.59Skamil		/* NOTREACHED */
2181.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
2191.59Skamil	}
2201.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2211.59Skamil
2221.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2231.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2241.59Skamil
2251.59Skamil	validate_status_stopped(status, sig);
2261.59Skamil
2271.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
2281.59Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2291.59Skamil
2301.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2311.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2321.59Skamil	        info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2331.59Skamil	        info.psi_siginfo.si_errno);
2341.59Skamil
2351.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
2361.59Skamil	switch (sig) {
2371.59Skamil	case SIGTRAP:
2381.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
2391.59Skamil		break;
2401.59Skamil	case SIGSEGV:
2411.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
2421.59Skamil		break;
2431.59Skamil//	case SIGILL:
2441.59Skamil//		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_ILLOP);
2451.59Skamil//		break;
2461.59Skamil	case SIGFPE:
2471.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
2481.59Skamil		break;
2491.59Skamil	case SIGBUS:
2501.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
2511.59Skamil		break;
2521.59Skamil	}
2531.59Skamil
2541.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
2551.59Skamil
2561.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2571.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2581.59Skamil
2591.59Skamil	validate_status_signaled(status, SIGKILL, 0);
2601.59Skamil
2611.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2621.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2631.59Skamil}
2641.59Skamil
2651.59Skamil#define TRACEME_CRASH(test, sig)						\
2661.59SkamilATF_TC(test);									\
2671.59SkamilATF_TC_HEAD(test, tc)								\
2681.59Skamil{										\
2691.59Skamil	atf_tc_set_md_var(tc, "descr",						\
2701.59Skamil	    "Verify crash signal " #sig " in a child after PT_TRACE_ME");	\
2711.59Skamil}										\
2721.59Skamil										\
2731.59SkamilATF_TC_BODY(test, tc)								\
2741.59Skamil{										\
2751.59Skamil										\
2761.59Skamil	traceme_crash(sig);							\
2771.59Skamil}
2781.59Skamil
2791.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
2801.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
2811.59Skamil//TRACEME_CRASH(traceme_crash_ill, SIGILL)
2821.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
2831.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
2841.59Skamil
2851.59Skamil/// ----------------------------------------------------------------------------
2861.59Skamil
2871.59Skamilstatic void
2881.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
2891.1Skamil{
2901.1Skamil	const int exitval = 5;
2911.34Skamil	const int sigval = SIGSTOP;
2921.1Skamil	pid_t child, wpid;
2931.1Skamil	struct sigaction sa;
2941.1Skamil#if defined(TWAIT_HAVE_STATUS)
2951.1Skamil	int status;
2961.1Skamil#endif
2971.1Skamil
2981.45Skamil	struct ptrace_siginfo info;
2991.45Skamil	memset(&info, 0, sizeof(info));
3001.45Skamil
3011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
3021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
3031.1Skamil	if (child == 0) {
3041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3061.1Skamil
3071.34Skamil		sa.sa_handler = sah;
3081.1Skamil		sa.sa_flags = SA_SIGINFO;
3091.1Skamil		sigemptyset(&sa.sa_mask);
3101.1Skamil
3111.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
3121.1Skamil
3131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3151.1Skamil
3161.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
3171.1Skamil
3181.13Schristos		DPRINTF("Before exiting of the child process\n");
3191.1Skamil		_exit(exitval);
3201.1Skamil	}
3211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3221.1Skamil
3231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3251.1Skamil
3261.1Skamil	validate_status_stopped(status, sigval);
3271.1Skamil
3281.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3291.45Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
3301.45Skamil	                != -1);
3311.45Skamil
3321.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3331.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3341.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3351.45Skamil	    info.psi_siginfo.si_errno);
3361.45Skamil
3371.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3381.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3391.45Skamil
3401.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
3411.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3431.1Skamil
3441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3461.1Skamil
3471.1Skamil	validate_status_exited(status, exitval);
3481.1Skamil
3491.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3511.1Skamil}
3521.1Skamil
3531.50Skamil#define TRACEME_SENDSIGNAL_HANDLE(test, sig)					\
3541.34SkamilATF_TC(test);									\
3551.34SkamilATF_TC_HEAD(test, tc)								\
3561.34Skamil{										\
3571.34Skamil	atf_tc_set_md_var(tc, "descr",						\
3581.34Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
3591.34Skamil	    "handled correctly and caught by a signal handler");		\
3601.34Skamil}										\
3611.34Skamil										\
3621.34Skamilstatic int test##_caught = 0;							\
3631.34Skamil										\
3641.34Skamilstatic void									\
3651.34Skamiltest##_sighandler(int arg)							\
3661.34Skamil{										\
3671.34Skamil	FORKEE_ASSERT_EQ(arg, sig);						\
3681.34Skamil										\
3691.34Skamil	++ test##_caught;							\
3701.34Skamil}										\
3711.34Skamil										\
3721.34SkamilATF_TC_BODY(test, tc)								\
3731.34Skamil{										\
3741.34Skamil										\
3751.50Skamil	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught);	\
3761.34Skamil}
3771.34Skamil
3781.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
3791.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
3801.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
3811.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
3821.34Skamil
3831.34Skamil/// ----------------------------------------------------------------------------
3841.34Skamil
3851.35Skamilstatic void
3861.50Skamiltraceme_sendsignal_masked(int sigsent)
3871.50Skamil{
3881.50Skamil	const int exitval = 5;
3891.50Skamil	const int sigval = SIGSTOP;
3901.50Skamil	pid_t child, wpid;
3911.50Skamil	sigset_t set;
3921.50Skamil#if defined(TWAIT_HAVE_STATUS)
3931.50Skamil	int status;
3941.50Skamil#endif
3951.50Skamil
3961.50Skamil	struct ptrace_siginfo info;
3971.50Skamil	memset(&info, 0, sizeof(info));
3981.50Skamil
3991.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4001.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4011.50Skamil	if (child == 0) {
4021.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4031.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4041.50Skamil
4051.50Skamil		sigemptyset(&set);
4061.50Skamil		sigaddset(&set, sigsent);
4071.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
4081.50Skamil
4091.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4101.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4111.50Skamil
4121.50Skamil		_exit(exitval);
4131.50Skamil	}
4141.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4151.50Skamil
4161.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4171.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4181.50Skamil
4191.50Skamil	validate_status_stopped(status, sigval);
4201.50Skamil
4211.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4221.50Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
4231.50Skamil	                != -1);
4241.50Skamil
4251.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4261.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4271.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4281.50Skamil	    info.psi_siginfo.si_errno);
4291.50Skamil
4301.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4311.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4321.50Skamil
4331.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
4341.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4351.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4361.50Skamil
4371.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4381.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4391.50Skamil
4401.50Skamil	validate_status_exited(status, exitval);
4411.50Skamil
4421.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4431.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4441.50Skamil}
4451.50Skamil
4461.50Skamil#define TRACEME_SENDSIGNAL_MASKED(test, sig)					\
4471.50SkamilATF_TC(test);									\
4481.50SkamilATF_TC_HEAD(test, tc)								\
4491.50Skamil{										\
4501.50Skamil	atf_tc_set_md_var(tc, "descr",						\
4511.50Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
4521.50Skamil	    "handled correctly and the signal is masked by SIG_BLOCK");		\
4531.50Skamil}										\
4541.50Skamil										\
4551.50SkamilATF_TC_BODY(test, tc)								\
4561.50Skamil{										\
4571.50Skamil										\
4581.50Skamil	traceme_sendsignal_masked(sig);						\
4591.50Skamil}
4601.50Skamil
4611.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4621.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
4631.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
4641.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
4651.50Skamil
4661.50Skamil/// ----------------------------------------------------------------------------
4671.50Skamil
4681.50Skamilstatic void
4691.50Skamiltraceme_sendsignal_ignored(int sigsent)
4701.50Skamil{
4711.50Skamil	const int exitval = 5;
4721.50Skamil	const int sigval = SIGSTOP;
4731.50Skamil	pid_t child, wpid;
4741.50Skamil	struct sigaction sa;
4751.50Skamil#if defined(TWAIT_HAVE_STATUS)
4761.50Skamil	int status;
4771.50Skamil#endif
4781.50Skamil
4791.50Skamil	struct ptrace_siginfo info;
4801.50Skamil	memset(&info, 0, sizeof(info));
4811.50Skamil
4821.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4831.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4841.50Skamil	if (child == 0) {
4851.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4861.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4871.50Skamil
4881.50Skamil		memset(&sa, 0, sizeof(sa));
4891.50Skamil		sa.sa_handler = SIG_IGN;
4901.50Skamil		sigemptyset(&sa.sa_mask);
4911.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
4921.50Skamil
4931.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4941.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4951.50Skamil
4961.50Skamil		_exit(exitval);
4971.50Skamil	}
4981.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4991.50Skamil
5001.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5011.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5021.50Skamil
5031.50Skamil	validate_status_stopped(status, sigval);
5041.50Skamil
5051.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5061.50Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
5071.50Skamil	                != -1);
5081.50Skamil
5091.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5101.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5111.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5121.50Skamil	    info.psi_siginfo.si_errno);
5131.50Skamil
5141.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5151.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5161.50Skamil
5171.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
5181.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
5191.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5201.50Skamil
5211.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5221.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5231.50Skamil
5241.50Skamil	validate_status_exited(status, exitval);
5251.50Skamil
5261.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5271.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5281.50Skamil}
5291.50Skamil
5301.50Skamil#define TRACEME_SENDSIGNAL_IGNORED(test, sig)					\
5311.50SkamilATF_TC(test);									\
5321.50SkamilATF_TC_HEAD(test, tc)								\
5331.50Skamil{										\
5341.50Skamil	atf_tc_set_md_var(tc, "descr",						\
5351.50Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
5361.50Skamil	    "handled correctly and the signal is masked by SIG_IGN");		\
5371.50Skamil}										\
5381.50Skamil										\
5391.50SkamilATF_TC_BODY(test, tc)								\
5401.50Skamil{										\
5411.50Skamil										\
5421.50Skamil	traceme_sendsignal_ignored(sig);					\
5431.50Skamil}
5441.50Skamil
5451.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
5461.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort trap */
5471.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
5481.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued? */
5491.50Skamil
5501.50Skamil/// ----------------------------------------------------------------------------
5511.50Skamil
5521.50Skamilstatic void
5531.50Skamiltraceme_sendsignal_simple(int sigsent)
5541.1Skamil{
5551.35Skamil	const int sigval = SIGSTOP;
5561.35Skamil	int exitval = 0;
5571.1Skamil	pid_t child, wpid;
5581.1Skamil#if defined(TWAIT_HAVE_STATUS)
5591.1Skamil	int status;
5601.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
5611.1Skamil#endif
5621.1Skamil
5631.45Skamil	struct ptrace_siginfo info;
5641.45Skamil	memset(&info, 0, sizeof(info));
5651.45Skamil
5661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
5671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
5681.1Skamil	if (child == 0) {
5691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5711.1Skamil
5721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5741.1Skamil
5751.35Skamil		switch (sigsent) {
5761.35Skamil		case SIGCONT:
5771.48Skamil		case SIGSTOP:
5781.35Skamil			_exit(exitval);
5791.35Skamil		default:
5801.35Skamil			/* NOTREACHED */
5811.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5821.35Skamil		}
5831.1Skamil	}
5841.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5851.1Skamil
5861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5881.1Skamil
5891.1Skamil	validate_status_stopped(status, sigval);
5901.1Skamil
5911.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5921.45Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
5931.45Skamil	                != -1);
5941.45Skamil
5951.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5961.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5971.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5981.45Skamil	    info.psi_siginfo.si_errno);
5991.45Skamil
6001.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6011.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6021.45Skamil
6031.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
6041.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
6051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6061.1Skamil
6071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6091.1Skamil
6101.35Skamil	switch (sigsent) {
6111.48Skamil	case SIGSTOP:
6121.48Skamil		validate_status_stopped(status, sigsent);
6131.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
6141.48Skamil		        "child\n");
6151.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
6161.48Skamil		                       sizeof(info)) != -1);
6171.48Skamil
6181.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6191.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
6201.48Skamil		        "si_errno=%#x\n",
6211.48Skamil			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6221.48Skamil		        info.psi_siginfo.si_errno);
6231.48Skamil
6241.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6251.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6261.48Skamil
6271.48Skamil		DPRINTF("Before resuming the child process where it left off "
6281.48Skamil		        "and with signal %s to be sent\n", strsignal(sigsent));
6291.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6301.48Skamil
6311.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6321.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
6331.48Skamil		                      child);
6341.48Skamil		/* FALLTHROUGH */
6351.35Skamil	case SIGCONT:
6361.35Skamil		validate_status_exited(status, exitval);
6371.35Skamil		break;
6381.35Skamil	default:
6391.35Skamil		validate_status_signaled(status, sigsent, expect_core);
6401.35Skamil		break;
6411.35Skamil	}
6421.1Skamil
6431.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6451.1Skamil}
6461.1Skamil
6471.50Skamil#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)					\
6481.35SkamilATF_TC(test);									\
6491.35SkamilATF_TC_HEAD(test, tc)								\
6501.35Skamil{										\
6511.35Skamil	atf_tc_set_md_var(tc, "descr",						\
6521.35Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
6531.35Skamil	    "handled correctly in a child without a signal handler");		\
6541.35Skamil}										\
6551.35Skamil										\
6561.35SkamilATF_TC_BODY(test, tc)								\
6571.35Skamil{										\
6581.35Skamil										\
6591.50Skamil	traceme_sendsignal_simple(sig);						\
6601.35Skamil}
6611.35Skamil
6621.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable */
6631.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable */
6641.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
6651.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
6661.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
6671.35Skamil
6681.35Skamil/// ----------------------------------------------------------------------------
6691.35Skamil
6701.37SkamilATF_TC(traceme_pid1_parent);
6711.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
6721.37Skamil{
6731.37Skamil	atf_tc_set_md_var(tc, "descr",
6741.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
6751.37Skamil}
6761.37Skamil
6771.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
6781.37Skamil{
6791.37Skamil	struct msg_fds parent_child;
6801.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
6811.37Skamil	pid_t child1, child2, wpid;
6821.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6831.37Skamil#if defined(TWAIT_HAVE_STATUS)
6841.37Skamil	int status;
6851.37Skamil#endif
6861.37Skamil
6871.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
6881.37Skamil
6891.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
6901.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
6911.37Skamil	if (child1 == 0) {
6921.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
6931.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
6941.37Skamil		if (child2 != 0) {
6951.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
6961.37Skamil			        getpid(), child2);
6971.37Skamil			_exit(exitval_child1);
6981.37Skamil		}
6991.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
7001.37Skamil
7011.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
7021.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
7031.37Skamil
7041.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7051.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
7061.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
7071.37Skamil
7081.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
7091.37Skamil
7101.37Skamil		_exit(exitval_child2);
7111.37Skamil	}
7121.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
7131.37Skamil
7141.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7151.37Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child1, &status, WEXITED),
7161.37Skamil	                      child1);
7171.37Skamil
7181.37Skamil	validate_status_exited(status, exitval_child1);
7191.37Skamil
7201.37Skamil	DPRINTF("Notify that child1 is dead\n");
7211.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
7221.37Skamil
7231.37Skamil	DPRINTF("Wait for exiting of child2\n");
7241.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
7251.37Skamil}
7261.37Skamil
7271.37Skamil/// ----------------------------------------------------------------------------
7281.37Skamil
7291.40Skamilstatic void
7301.40Skamiltraceme_vfork_raise(int sigval)
7311.40Skamil{
7321.46Skamil	const int exitval = 5, exitval_watcher = 10;
7331.46Skamil	pid_t child, parent, watcher, wpid;
7341.46Skamil	int rv;
7351.40Skamil#if defined(TWAIT_HAVE_STATUS)
7361.40Skamil	int status;
7371.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
7381.40Skamil#endif
7391.40Skamil
7401.46Skamil	/*
7411.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
7421.46Skamil	 * the SIGKILL signal to it.
7431.46Skamil	 *
7441.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
7451.46Skamil	 * simpler to reparent this process to initproc and forget about it.
7461.46Skamil	 */
7471.46Skamil	if (sigval == SIGSTOP) {
7481.46Skamil		parent = getpid();
7491.46Skamil
7501.46Skamil		watcher = fork();
7511.46Skamil		ATF_REQUIRE(watcher != 1);
7521.46Skamil		if (watcher == 0) {
7531.46Skamil			/* Double fork(2) trick to reparent to initproc */
7541.46Skamil			watcher = fork();
7551.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
7561.46Skamil			if (watcher != 0)
7571.46Skamil				_exit(exitval_watcher);
7581.46Skamil
7591.46Skamil			child = await_stopped_child(parent);
7601.46Skamil
7611.46Skamil			errno = 0;
7621.46Skamil			rv = kill(child, SIGKILL);
7631.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
7641.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
7651.46Skamil
7661.46Skamil			/* This exit value will be collected by initproc */
7671.46Skamil			_exit(0);
7681.46Skamil		}
7691.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7701.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
7711.46Skamil		                      watcher);
7721.46Skamil
7731.46Skamil		validate_status_exited(status, exitval_watcher);
7741.46Skamil
7751.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7761.46Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(watcher,
7771.46Skamil		                                                   &status, 0));
7781.46Skamil	}
7791.46Skamil
7801.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7811.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
7821.40Skamil	if (child == 0) {
7831.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7841.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7851.40Skamil
7861.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7871.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7881.40Skamil
7891.40Skamil		switch (sigval) {
7901.46Skamil		case SIGSTOP:
7911.40Skamil		case SIGKILL:
7921.40Skamil		case SIGABRT:
7931.40Skamil		case SIGHUP:
7941.40Skamil			/* NOTREACHED */
7951.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7961.40Skamil		default:
7971.40Skamil			DPRINTF("Before exiting of the child process\n");
7981.40Skamil			_exit(exitval);
7991.40Skamil		}
8001.40Skamil	}
8011.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8021.40Skamil
8031.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8041.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8051.40Skamil
8061.40Skamil	switch (sigval) {
8071.40Skamil	case SIGKILL:
8081.40Skamil	case SIGABRT:
8091.40Skamil	case SIGHUP:
8101.40Skamil		validate_status_signaled(status, sigval, expect_core);
8111.40Skamil		break;
8121.40Skamil	case SIGSTOP:
8131.46Skamil		validate_status_signaled(status, SIGKILL, 0);
8141.46Skamil		break;
8151.40Skamil	case SIGCONT:
8161.47Skamil	case SIGTSTP:
8171.47Skamil	case SIGTTIN:
8181.47Skamil	case SIGTTOU:
8191.40Skamil		validate_status_exited(status, exitval);
8201.40Skamil		break;
8211.40Skamil	default:
8221.40Skamil		/* NOTREACHED */
8231.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
8241.40Skamil		break;
8251.40Skamil	}
8261.40Skamil
8271.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8281.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8291.40Skamil}
8301.40Skamil
8311.40Skamil#define TRACEME_VFORK_RAISE(test, sig)						\
8321.40SkamilATF_TC(test);									\
8331.40SkamilATF_TC_HEAD(test, tc)								\
8341.40Skamil{										\
8351.40Skamil	atf_tc_set_md_var(tc, "descr",						\
8361.42Skamil	    "Verify PT_TRACE_ME followed by raise of " #sig " in a vfork(2)ed "	\
8371.42Skamil	    "child");								\
8381.40Skamil}										\
8391.40Skamil										\
8401.40SkamilATF_TC_BODY(test, tc)								\
8411.40Skamil{										\
8421.40Skamil										\
8431.40Skamil	traceme_vfork_raise(sig);						\
8441.40Skamil}
8451.40Skamil
8461.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
8471.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
8481.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
8491.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
8501.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
8511.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
8521.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
8531.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
8541.40Skamil
8551.40Skamil/// ----------------------------------------------------------------------------
8561.40Skamil
8571.52Skamilstatic void
8581.52Skamiltraceme_vfork_crash(int sig)
8591.41Skamil{
8601.41Skamil	pid_t child, wpid;
8611.41Skamil#if defined(TWAIT_HAVE_STATUS)
8621.41Skamil	int status;
8631.41Skamil#endif
8641.41Skamil
8651.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8661.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
8671.41Skamil	if (child == 0) {
8681.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8691.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8701.41Skamil
8711.52Skamil		DPRINTF("Before executing a trap\n");
8721.52Skamil		switch (sig) {
8731.52Skamil		case SIGTRAP:
8741.52Skamil			trigger_trap();
8751.52Skamil			break;
8761.52Skamil		case SIGSEGV:
8771.52Skamil			trigger_segv();
8781.52Skamil			break;
8791.52Skamil		case SIGILL:
8801.52Skamil			trigger_ill();
8811.52Skamil			break;
8821.52Skamil		case SIGFPE:
8831.52Skamil			trigger_fpe();
8841.52Skamil			break;
8851.52Skamil		case SIGBUS:
8861.52Skamil			trigger_bus();
8871.52Skamil			break;
8881.52Skamil		default:
8891.52Skamil			/* NOTREACHED */
8901.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
8911.52Skamil		}
8921.41Skamil
8931.41Skamil		/* NOTREACHED */
8941.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
8951.41Skamil	}
8961.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8971.41Skamil
8981.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8991.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9001.41Skamil
9011.52Skamil	validate_status_signaled(status, sig, 1);
9021.41Skamil
9031.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9041.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9051.41Skamil}
9061.41Skamil
9071.52Skamil#define TRACEME_VFORK_CRASH(test, sig)						\
9081.52SkamilATF_TC(test);									\
9091.52SkamilATF_TC_HEAD(test, tc)								\
9101.52Skamil{										\
9111.52Skamil	atf_tc_set_md_var(tc, "descr",						\
9121.52Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a "	\
9131.52Skamil	    "vfork(2)ed child");						\
9141.52Skamil}										\
9151.52Skamil										\
9161.52SkamilATF_TC_BODY(test, tc)								\
9171.52Skamil{										\
9181.52Skamil										\
9191.52Skamil	traceme_vfork_crash(sig);						\
9201.52Skamil}
9211.52Skamil
9221.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
9231.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
9241.52Skamil//TRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
9251.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
9261.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
9271.52Skamil
9281.41Skamil/// ----------------------------------------------------------------------------
9291.41Skamil
9301.43SkamilATF_TC(traceme_vfork_exec);
9311.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
9321.43Skamil{
9331.43Skamil	atf_tc_set_md_var(tc, "descr",
9341.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
9351.43Skamil}
9361.43Skamil
9371.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
9381.43Skamil{
9391.43Skamil	const int sigval = SIGTRAP;
9401.43Skamil	pid_t child, wpid;
9411.43Skamil#if defined(TWAIT_HAVE_STATUS)
9421.43Skamil	int status;
9431.43Skamil#endif
9441.43Skamil
9451.43Skamil	struct ptrace_siginfo info;
9461.43Skamil	memset(&info, 0, sizeof(info));
9471.43Skamil
9481.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9491.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
9501.43Skamil	if (child == 0) {
9511.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9521.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9531.43Skamil
9541.43Skamil		DPRINTF("Before calling execve(2) from child\n");
9551.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
9561.43Skamil
9571.43Skamil		/* NOTREACHED */
9581.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
9591.43Skamil	}
9601.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9611.43Skamil
9621.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9631.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9641.43Skamil
9651.43Skamil	validate_status_stopped(status, sigval);
9661.43Skamil
9671.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9681.43Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9691.43Skamil
9701.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9711.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9721.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9731.43Skamil	    info.psi_siginfo.si_errno);
9741.43Skamil
9751.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9761.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
9771.43Skamil
9781.43Skamil	DPRINTF("Before resuming the child process where it left off and "
9791.43Skamil	    "without signal to be sent\n");
9801.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
9811.43Skamil
9821.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9831.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9841.43Skamil
9851.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9861.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9871.43Skamil}
9881.43Skamil
9891.43Skamil/// ----------------------------------------------------------------------------
9901.43Skamil
9911.1Skamil#if defined(TWAIT_HAVE_PID)
9921.51Skamilstatic void
9931.59Skamilunrelated_tracer_sees_crash(int sig)
9941.59Skamil{
9951.59Skamil	struct msg_fds parent_tracee, parent_tracer;
9961.59Skamil	const int exitval = 10;
9971.59Skamil	pid_t tracee, tracer, wpid;
9981.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
9991.59Skamil#if defined(TWAIT_HAVE_STATUS)
10001.59Skamil	int status;
10011.59Skamil#endif
10021.59Skamil	struct ptrace_siginfo info;
10031.59Skamil	memset(&info, 0, sizeof(info));
10041.59Skamil
10051.59Skamil	DPRINTF("Spawn tracee\n");
10061.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10071.59Skamil	tracee = atf_utils_fork();
10081.59Skamil	if (tracee == 0) {
10091.59Skamil		// Wait for parent to let us crash
10101.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
10111.59Skamil
10121.59Skamil		DPRINTF("Before executing a trap\n");
10131.59Skamil		switch (sig) {
10141.59Skamil		case SIGTRAP:
10151.59Skamil			trigger_trap();
10161.59Skamil			break;
10171.59Skamil		case SIGSEGV:
10181.59Skamil			trigger_segv();
10191.59Skamil			break;
10201.59Skamil		case SIGILL:
10211.59Skamil			trigger_ill();
10221.59Skamil			break;
10231.59Skamil		case SIGFPE:
10241.59Skamil			trigger_fpe();
10251.59Skamil			break;
10261.59Skamil		case SIGBUS:
10271.59Skamil			trigger_bus();
10281.59Skamil			break;
10291.59Skamil		default:
10301.59Skamil			/* NOTREACHED */
10311.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
10321.59Skamil		}
10331.59Skamil
10341.59Skamil		/* NOTREACHED */
10351.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
10361.59Skamil	}
10371.59Skamil
10381.59Skamil	DPRINTF("Spawn debugger\n");
10391.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10401.59Skamil	tracer = atf_utils_fork();
10411.59Skamil	if (tracer == 0) {
10421.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
10431.59Skamil		tracer = atf_utils_fork();
10441.59Skamil		if (tracer != 0)
10451.59Skamil				_exit(exitval);
10461.59Skamil
10471.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10481.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10491.59Skamil
10501.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10511.59Skamil		FORKEE_REQUIRE_SUCCESS(
10521.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10531.59Skamil
10541.59Skamil		forkee_status_stopped(status, SIGSTOP);
10551.59Skamil
10561.59Skamil		/* Resume tracee with PT_CONTINUE */
10571.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10581.59Skamil
10591.59Skamil		/* Inform parent that tracer has attached to tracee */
10601.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
10611.59Skamil
10621.59Skamil		/* Wait for parent to tell use that tracee should have exited */
10631.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
10641.59Skamil
10651.59Skamil		/* Wait for tracee and assert that it exited */
10661.59Skamil		FORKEE_REQUIRE_SUCCESS(
10671.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10681.59Skamil
10691.59Skamil		validate_status_stopped(status, sig);
10701.59Skamil
10711.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
10721.59Skamil		        "traced process\n");
10731.59Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, tracee, &info,
10741.59Skamil		                       sizeof(info)) != -1);
10751.59Skamil
10761.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10771.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
10781.59Skamil		        "si_errno=%#x\n", info.psi_siginfo.si_signo,
10791.59Skamil		        info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
10801.59Skamil
10811.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
10821.59Skamil		switch (sig) {
10831.59Skamil		case SIGTRAP:
10841.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
10851.59Skamil			break;
10861.59Skamil		case SIGSEGV:
10871.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
10881.59Skamil			break;
10891.59Skamil//		case SIGILL:
10901.59Skamil//			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_ILLOP);
10911.59Skamil//			break;
10921.59Skamil		case SIGFPE:
10931.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
10941.59Skamil			break;
10951.59Skamil		case SIGBUS:
10961.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
10971.59Skamil			break;
10981.59Skamil		}
10991.59Skamil
11001.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
11011.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
11021.59Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0),
11031.59Skamil		                      tracee);
11041.59Skamil
11051.59Skamil		validate_status_signaled(status, SIGKILL, 0);
11061.59Skamil
11071.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
11081.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
11091.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
11101.59Skamil
11111.59Skamil		DPRINTF("Before exiting of the tracer process\n");
11121.59Skamil		_exit(0 /* collect by initproc */);
11131.59Skamil	}
11141.59Skamil
11151.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
11161.59Skamil	    "calling %s()\n", TWAIT_FNAME);
11171.59Skamil	TWAIT_REQUIRE_SUCCESS(
11181.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
11191.59Skamil
11201.59Skamil	validate_status_exited(status, exitval);
11211.59Skamil
11221.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
11231.59Skamil	    TWAIT_FNAME);
11241.59Skamil	TWAIT_REQUIRE_SUCCESS(
11251.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
11261.59Skamil
11271.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
11281.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
11291.59Skamil
11301.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
11311.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
11321.59Skamil
11331.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
11341.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11351.59Skamil
11361.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11371.59Skamil	    TWAIT_FNAME);
11381.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11391.59Skamil
11401.59Skamil	validate_status_signaled(status, SIGKILL, 0);
11411.59Skamil
11421.59Skamil	msg_close(&parent_tracer);
11431.59Skamil	msg_close(&parent_tracee);
11441.59Skamil}
11451.59Skamil
11461.59Skamil#define UNRELATED_TRACER_SEES_CRASH(test, sig)					\
11471.59SkamilATF_TC(test);									\
11481.59SkamilATF_TC_HEAD(test, tc)								\
11491.59Skamil{										\
11501.59Skamil	atf_tc_set_md_var(tc, "descr",						\
11511.59Skamil	    "Assert that an unrelated tracer sees crash signal from the "	\
11521.59Skamil	    "debuggee");							\
11531.59Skamil}										\
11541.59Skamil										\
11551.59SkamilATF_TC_BODY(test, tc)								\
11561.59Skamil{										\
11571.59Skamil										\
11581.59Skamil	unrelated_tracer_sees_crash(sig);					\
11591.59Skamil}
11601.59Skamil
11611.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
11621.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
11631.59Skamil//UNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
11641.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
11651.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
11661.59Skamil#endif
11671.59Skamil
11681.59Skamil/// ----------------------------------------------------------------------------
11691.59Skamil
11701.59Skamil#if defined(TWAIT_HAVE_PID)
11711.59Skamilstatic void
11721.51Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated)
11731.1Skamil{
11741.51Skamil	/*
11751.51Skamil	 * notimeout - disable timeout in await zombie function
11761.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
11771.51Skamil	 */
11781.1Skamil
11791.1Skamil	struct msg_fds parent_tracee, parent_tracer;
11801.1Skamil	const int exitval_tracee = 5;
11811.1Skamil	const int exitval_tracer = 10;
11821.1Skamil	pid_t tracee, tracer, wpid;
11831.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11841.1Skamil#if defined(TWAIT_HAVE_STATUS)
11851.1Skamil	int status;
11861.1Skamil#endif
11871.1Skamil
11881.13Schristos	DPRINTF("Spawn tracee\n");
11891.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11901.1Skamil	tracee = atf_utils_fork();
11911.1Skamil	if (tracee == 0) {
11921.1Skamil		// Wait for parent to let us exit
11931.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
11941.1Skamil		_exit(exitval_tracee);
11951.1Skamil	}
11961.1Skamil
11971.13Schristos	DPRINTF("Spawn debugger\n");
11981.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
11991.1Skamil	tracer = atf_utils_fork();
12001.1Skamil	if (tracer == 0) {
12011.51Skamil		if(unrelated) {
12021.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
12031.51Skamil			tracer = atf_utils_fork();
12041.51Skamil			if (tracer != 0)
12051.51Skamil				_exit(exitval_tracer);
12061.51Skamil		}
12071.51Skamil
12081.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12091.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12101.1Skamil
12111.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12121.1Skamil		FORKEE_REQUIRE_SUCCESS(
12131.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12141.1Skamil
12151.1Skamil		forkee_status_stopped(status, SIGSTOP);
12161.1Skamil
12171.1Skamil		/* Resume tracee with PT_CONTINUE */
12181.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
12191.1Skamil
12201.1Skamil		/* Inform parent that tracer has attached to tracee */
12211.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12221.1Skamil
12231.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12241.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12251.1Skamil
12261.1Skamil		/* Wait for tracee and assert that it exited */
12271.1Skamil		FORKEE_REQUIRE_SUCCESS(
12281.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12291.1Skamil
12301.1Skamil		forkee_status_exited(status, exitval_tracee);
12311.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
12321.1Skamil
12331.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12341.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
12351.51Skamil	}
12361.51Skamil
12371.51Skamil	if (unrelated) {
12381.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
12391.51Skamil		    "calling %s()\n", TWAIT_FNAME);
12401.51Skamil		TWAIT_REQUIRE_SUCCESS(
12411.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
12421.51Skamil
12431.51Skamil		validate_status_exited(status, exitval_tracer);
12441.51Skamil
12451.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
12461.51Skamil		    TWAIT_FNAME);
12471.51Skamil		TWAIT_REQUIRE_SUCCESS(
12481.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
12491.1Skamil	}
12501.1Skamil
12511.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
12521.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
12531.1Skamil
12541.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
12551.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
12561.1Skamil
12571.13Schristos	DPRINTF("Detect that tracee is zombie\n");
12581.51Skamil	if (notimeout)
12591.26Skamil		await_zombie_raw(tracee, 0);
12601.26Skamil	else
12611.26Skamil		await_zombie(tracee);
12621.1Skamil
12631.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
12641.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
12651.1Skamil	    TWAIT_FNAME);
12661.1Skamil	TWAIT_REQUIRE_SUCCESS(
12671.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
12681.1Skamil
12691.51Skamil	if (unrelated) {
12701.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
12711.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
12721.51Skamil	} else {
12731.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
12741.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
12751.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
12761.59Skamil			"%s()\n", TWAIT_FNAME);
12771.51Skamil
12781.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
12791.59Skamil			"tracee\n");
12801.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
12811.51Skamil		    tracer);
12821.1Skamil
12831.51Skamil		validate_status_exited(status, exitval_tracer);
12841.51Skamil	}
12851.1Skamil
12861.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
12871.1Skamil	    TWAIT_FNAME);
12881.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12891.1Skamil
12901.1Skamil	validate_status_exited(status, exitval_tracee);
12911.1Skamil
12921.1Skamil	msg_close(&parent_tracer);
12931.1Skamil	msg_close(&parent_tracee);
12941.1Skamil}
12951.26Skamil
12961.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
12971.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
12981.51Skamil{
12991.51Skamil	atf_tc_set_md_var(tc, "descr",
13001.51Skamil	    "Assert that tracer sees process termination before the parent");
13011.51Skamil}
13021.51Skamil
13031.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
13041.26Skamil{
13051.26Skamil
13061.51Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false);
13071.26Skamil}
13081.26Skamil
13091.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
13101.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
13111.1Skamil{
13121.1Skamil	atf_tc_set_md_var(tc, "descr",
13131.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
13141.51Skamil	    "process and no other error is reported");
13151.1Skamil}
13161.1Skamil
13171.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
13181.1Skamil{
13191.51Skamil	time_t start, end;
13201.51Skamil	double diff;
13211.51Skamil	unsigned long N = 0;
13221.1Skamil
13231.51Skamil	/*
13241.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
13251.51Skamil	 * This test body isn't specific to this race, however it's just good
13261.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
13271.51Skamil	 */
13281.1Skamil
13291.51Skamil	start = time(NULL);
13301.51Skamil	while (true) {
13311.51Skamil		DPRINTF("Step: %lu\n", N);
13321.51Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false);
13331.51Skamil		end = time(NULL);
13341.51Skamil		diff = difftime(end, start);
13351.51Skamil		if (diff >= 5.0)
13361.51Skamil			break;
13371.51Skamil		++N;
13381.1Skamil	}
13391.51Skamil	DPRINTF("Iterations: %lu\n", N);
13401.51Skamil}
13411.1Skamil
13421.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
13431.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13441.51Skamil{
13451.51Skamil	atf_tc_set_md_var(tc, "descr",
13461.51Skamil	    "Assert that tracer sees process termination before the parent");
13471.51Skamil}
13481.1Skamil
13491.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13501.51Skamil{
13511.1Skamil
13521.51Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true);
13531.1Skamil}
13541.1Skamil#endif
13551.1Skamil
13561.51Skamil/// ----------------------------------------------------------------------------
13571.51Skamil
13581.51SkamilATF_TC(parent_attach_to_its_child);
13591.51SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
13601.1Skamil{
13611.1Skamil	atf_tc_set_md_var(tc, "descr",
13621.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
13631.1Skamil}
13641.1Skamil
13651.51SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
13661.1Skamil{
13671.1Skamil	struct msg_fds parent_tracee;
13681.1Skamil	const int exitval_tracee = 5;
13691.1Skamil	pid_t tracee, wpid;
13701.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
13711.1Skamil#if defined(TWAIT_HAVE_STATUS)
13721.1Skamil	int status;
13731.1Skamil#endif
13741.1Skamil
13751.13Schristos	DPRINTF("Spawn tracee\n");
13761.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
13771.1Skamil	tracee = atf_utils_fork();
13781.1Skamil	if (tracee == 0) {
13791.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
13801.13Schristos		DPRINTF("Parent should now attach to tracee\n");
13811.1Skamil
13821.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
13831.1Skamil		/* Wait for message from the parent */
13841.1Skamil		_exit(exitval_tracee);
13851.1Skamil	}
13861.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
13871.57Skamil
13881.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
13891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
13901.1Skamil
13911.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
13921.1Skamil	    TWAIT_FNAME);
13931.1Skamil	TWAIT_REQUIRE_SUCCESS(
13941.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13951.1Skamil
13961.1Skamil	validate_status_stopped(status, SIGSTOP);
13971.1Skamil
13981.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
13991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
14001.1Skamil
14011.13Schristos	DPRINTF("Let the tracee exit now\n");
14021.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
14031.1Skamil
14041.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
14051.1Skamil	TWAIT_REQUIRE_SUCCESS(
14061.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14071.1Skamil
14081.1Skamil	validate_status_exited(status, exitval_tracee);
14091.1Skamil
14101.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
14111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
14121.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
14131.1Skamil
14141.1Skamil	msg_close(&parent_tracee);
14151.1Skamil}
14161.1Skamil
14171.51Skamil/// ----------------------------------------------------------------------------
14181.51Skamil
14191.51SkamilATF_TC(child_attach_to_its_parent);
14201.51SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
14211.1Skamil{
14221.1Skamil	atf_tc_set_md_var(tc, "descr",
14231.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
14241.1Skamil}
14251.1Skamil
14261.51SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
14271.1Skamil{
14281.1Skamil	struct msg_fds parent_tracee;
14291.1Skamil	const int exitval_tracer = 5;
14301.1Skamil	pid_t tracer, wpid;
14311.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
14321.1Skamil#if defined(TWAIT_HAVE_STATUS)
14331.1Skamil	int status;
14341.1Skamil#endif
14351.1Skamil
14361.13Schristos	DPRINTF("Spawn tracer\n");
14371.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
14381.1Skamil	tracer = atf_utils_fork();
14391.1Skamil	if (tracer == 0) {
14401.1Skamil
14411.1Skamil		/* Wait for message from the parent */
14421.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
14431.1Skamil
14441.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
14451.1Skamil		    getppid());
14461.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
14471.1Skamil
14481.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
14491.1Skamil		    TWAIT_FNAME);
14501.1Skamil		FORKEE_REQUIRE_SUCCESS(
14511.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
14521.1Skamil
14531.1Skamil		forkee_status_stopped(status, SIGSTOP);
14541.1Skamil
14551.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
14561.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
14571.1Skamil		    != -1);
14581.1Skamil
14591.1Skamil		/* Tell parent we are ready */
14601.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
14611.1Skamil
14621.1Skamil		_exit(exitval_tracer);
14631.1Skamil	}
14641.1Skamil
14651.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
14661.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
14671.13Schristos	DPRINTF("Allow the tracer to exit now\n");
14681.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
14691.1Skamil
14701.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
14711.1Skamil	TWAIT_REQUIRE_SUCCESS(
14721.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
14731.1Skamil
14741.1Skamil	validate_status_exited(status, exitval_tracer);
14751.1Skamil
14761.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
14771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
14781.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
14791.1Skamil
14801.1Skamil	msg_close(&parent_tracee);
14811.1Skamil}
14821.1Skamil
14831.51Skamil/// ----------------------------------------------------------------------------
14841.51Skamil
14851.1Skamil#if defined(TWAIT_HAVE_PID)
14861.1Skamil
14871.51Skamilenum tracee_sees_its_original_parent_type {
14881.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
14891.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
14901.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
14911.51Skamil};
14921.51Skamil
14931.51Skamilstatic void
14941.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
14951.1Skamil{
14961.1Skamil	struct msg_fds parent_tracer, parent_tracee;
14971.1Skamil	const int exitval_tracee = 5;
14981.1Skamil	const int exitval_tracer = 10;
14991.1Skamil	pid_t parent, tracee, tracer, wpid;
15001.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15011.1Skamil#if defined(TWAIT_HAVE_STATUS)
15021.1Skamil	int status;
15031.1Skamil#endif
15041.51Skamil	/* sysctl(3) - kinfo_proc2 */
15051.51Skamil	int name[CTL_MAXNAME];
15061.51Skamil	struct kinfo_proc2 kp;
15071.51Skamil	size_t len = sizeof(kp);
15081.51Skamil	unsigned int namelen;
15091.51Skamil
15101.51Skamil	/* procfs - status  */
15111.51Skamil	FILE *fp;
15121.51Skamil	struct stat st;
15131.51Skamil	const char *fname = "/proc/curproc/status";
15141.51Skamil	char s_executable[MAXPATHLEN];
15151.51Skamil	int s_pid, s_ppid;
15161.51Skamil	int rv;
15171.51Skamil
15181.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
15191.51Skamil		SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 ||
15201.51Skamil		                (errno == ENOENT));
15211.51Skamil		if (rv != 0) {
15221.51Skamil			atf_tc_skip("/proc/curproc/status not found");
15231.51Skamil		}
15241.51Skamil	}
15251.1Skamil
15261.13Schristos	DPRINTF("Spawn tracee\n");
15271.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
15281.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15291.1Skamil	tracee = atf_utils_fork();
15301.1Skamil	if (tracee == 0) {
15311.1Skamil		parent = getppid();
15321.1Skamil
15331.1Skamil		/* Emit message to the parent */
15341.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
15351.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
15361.1Skamil
15371.51Skamil		switch (type) {
15381.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
15391.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
15401.51Skamil			break;
15411.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
15421.51Skamil			namelen = 0;
15431.51Skamil			name[namelen++] = CTL_KERN;
15441.51Skamil			name[namelen++] = KERN_PROC2;
15451.51Skamil			name[namelen++] = KERN_PROC_PID;
15461.51Skamil			name[namelen++] = getpid();
15471.51Skamil			name[namelen++] = len;
15481.51Skamil			name[namelen++] = 1;
15491.51Skamil
15501.51Skamil			FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL,
15511.51Skamil			                        0),
15521.51Skamil			                 0);
15531.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
15541.51Skamil			break;
15551.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
15561.51Skamil			/*
15571.51Skamil			 * Format:
15581.51Skamil			 *  EXECUTABLE PID PPID ...
15591.51Skamil			 */
15601.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
15611.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
15621.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
15631.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
15641.51Skamil			break;
15651.51Skamil		}
15661.1Skamil
15671.1Skamil		_exit(exitval_tracee);
15681.1Skamil	}
15691.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
15701.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
15711.1Skamil
15721.13Schristos	DPRINTF("Spawn debugger\n");
15731.1Skamil	tracer = atf_utils_fork();
15741.1Skamil	if (tracer == 0) {
15751.1Skamil		/* No IPC to communicate with the child */
15761.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
15771.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
15781.1Skamil
15791.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
15801.1Skamil		FORKEE_REQUIRE_SUCCESS(
15811.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
15821.1Skamil
15831.1Skamil		forkee_status_stopped(status, SIGSTOP);
15841.1Skamil
15851.1Skamil		/* Resume tracee with PT_CONTINUE */
15861.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
15871.1Skamil
15881.1Skamil		/* Inform parent that tracer has attached to tracee */
15891.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
15901.1Skamil
15911.1Skamil		/* Wait for parent to tell use that tracee should have exited */
15921.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
15931.1Skamil
15941.1Skamil		/* Wait for tracee and assert that it exited */
15951.1Skamil		FORKEE_REQUIRE_SUCCESS(
15961.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
15971.1Skamil
15981.1Skamil		forkee_status_exited(status, exitval_tracee);
15991.1Skamil
16001.13Schristos		DPRINTF("Before exiting of the tracer process\n");
16011.1Skamil		_exit(exitval_tracer);
16021.1Skamil	}
16031.1Skamil
16041.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
16051.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
16061.1Skamil
16071.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
16081.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
16091.1Skamil
16101.13Schristos	DPRINTF("Detect that tracee is zombie\n");
16111.1Skamil	await_zombie(tracee);
16121.1Skamil
16131.13Schristos	DPRINTF("Assert that there is no status about tracee - "
16141.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
16151.1Skamil	TWAIT_REQUIRE_SUCCESS(
16161.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
16171.1Skamil
16181.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
16191.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
16201.1Skamil
16211.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
16221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
16231.1Skamil	    tracer);
16241.1Skamil
16251.1Skamil	validate_status_exited(status, exitval_tracer);
16261.1Skamil
16271.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
16281.1Skamil	    TWAIT_FNAME);
16291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
16301.1Skamil	    tracee);
16311.1Skamil
16321.1Skamil	validate_status_exited(status, exitval_tracee);
16331.1Skamil
16341.1Skamil	msg_close(&parent_tracer);
16351.1Skamil	msg_close(&parent_tracee);
16361.1Skamil}
16371.1Skamil
16381.51Skamil#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)			\
16391.51SkamilATF_TC(test);									\
16401.51SkamilATF_TC_HEAD(test, tc)								\
16411.51Skamil{										\
16421.51Skamil	atf_tc_set_md_var(tc, "descr",						\
16431.51Skamil	    "Assert that tracee sees its original parent when being traced "	\
16441.51Skamil	    "(check " descr ")");						\
16451.51Skamil}										\
16461.51Skamil										\
16471.51SkamilATF_TC_BODY(test, tc)								\
16481.51Skamil{										\
16491.51Skamil										\
16501.51Skamil	tracee_sees_its_original_parent(type);					\
16511.1Skamil}
16521.1Skamil
16531.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
16541.51Skamil	tracee_sees_its_original_parent_getppid,
16551.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
16561.51Skamil	"getppid(2)");
16571.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
16581.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
16591.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
16601.51Skamil	"sysctl(3) and kinfo_proc2");
16611.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
16621.51Skamil	tracee_sees_its_original_parent_procfs_status,
16631.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
16641.51Skamil	"the status file in procfs");
16651.1Skamil#endif
16661.1Skamil
16671.51Skamil/// ----------------------------------------------------------------------------
16681.1Skamil
16691.53Skamilstatic void
16701.53Skamileventmask_preserved(int event)
16711.1Skamil{
16721.1Skamil	const int exitval = 5;
16731.1Skamil	const int sigval = SIGSTOP;
16741.1Skamil	pid_t child, wpid;
16751.1Skamil#if defined(TWAIT_HAVE_STATUS)
16761.1Skamil	int status;
16771.1Skamil#endif
16781.1Skamil	ptrace_event_t set_event, get_event;
16791.1Skamil	const int len = sizeof(ptrace_event_t);
16801.1Skamil
16811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
16821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
16831.1Skamil	if (child == 0) {
16841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
16851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
16861.1Skamil
16871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
16881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
16891.1Skamil
16901.13Schristos		DPRINTF("Before exiting of the child process\n");
16911.1Skamil		_exit(exitval);
16921.1Skamil	}
16931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
16941.1Skamil
16951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16971.1Skamil
16981.1Skamil	validate_status_stopped(status, sigval);
16991.1Skamil
17001.53Skamil	set_event.pe_set_event = event;
17011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
17021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
17031.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
17041.1Skamil
17051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
17061.1Skamil	    "without signal to be sent\n");
17071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
17081.1Skamil
17091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17111.1Skamil
17121.1Skamil	validate_status_exited(status, exitval);
17131.1Skamil
17141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
17161.1Skamil}
17171.1Skamil
17181.53Skamil#define EVENTMASK_PRESERVED(test, event)					\
17191.53SkamilATF_TC(test);									\
17201.53SkamilATF_TC_HEAD(test, tc)								\
17211.53Skamil{										\
17221.53Skamil	atf_tc_set_md_var(tc, "descr",						\
17231.53Skamil	    "Verify that eventmask " #event " is preserved");			\
17241.53Skamil}										\
17251.53Skamil										\
17261.53SkamilATF_TC_BODY(test, tc)								\
17271.53Skamil{										\
17281.53Skamil										\
17291.53Skamil	eventmask_preserved(event);						\
17301.1Skamil}
17311.1Skamil
17321.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
17331.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
17341.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
17351.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
17361.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
17371.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
17381.1Skamil
17391.53Skamil/// ----------------------------------------------------------------------------
17401.1Skamil
17411.28Skamilstatic void
17421.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
17431.32Skamil          bool trackvforkdone, bool detachchild, bool detachparent)
17441.1Skamil{
17451.1Skamil	const int exitval = 5;
17461.1Skamil	const int exitval2 = 15;
17471.1Skamil	const int sigval = SIGSTOP;
17481.31Skamil	pid_t child, child2 = 0, wpid;
17491.1Skamil#if defined(TWAIT_HAVE_STATUS)
17501.1Skamil	int status;
17511.1Skamil#endif
17521.1Skamil	ptrace_state_t state;
17531.1Skamil	const int slen = sizeof(state);
17541.1Skamil	ptrace_event_t event;
17551.1Skamil	const int elen = sizeof(event);
17561.1Skamil
17571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
17581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
17591.1Skamil	if (child == 0) {
17601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17621.1Skamil
17631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
17641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
17651.1Skamil
17661.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
17671.1Skamil
17681.1Skamil		if (child2 == 0)
17691.1Skamil			_exit(exitval2);
17701.1Skamil
17711.1Skamil		FORKEE_REQUIRE_SUCCESS
17721.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
17731.1Skamil
17741.1Skamil		forkee_status_exited(status, exitval2);
17751.1Skamil
17761.13Schristos		DPRINTF("Before exiting of the child process\n");
17771.1Skamil		_exit(exitval);
17781.1Skamil	}
17791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17801.1Skamil
17811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17831.1Skamil
17841.1Skamil	validate_status_stopped(status, sigval);
17851.1Skamil
17861.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
17871.30Skamil	        trackfork ? "|PTRACE_FORK" : "",
17881.30Skamil	        trackvfork ? "|PTRACE_VFORK" : "",
17891.30Skamil	        trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
17901.30Skamil	event.pe_set_event = 0;
17911.30Skamil	if (trackfork)
17921.30Skamil		event.pe_set_event |= PTRACE_FORK;
17931.30Skamil	if (trackvfork)
17941.30Skamil		event.pe_set_event |= PTRACE_VFORK;
17951.30Skamil	if (trackvforkdone)
17961.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
17971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
17981.1Skamil
17991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18001.1Skamil	    "without signal to be sent\n");
18011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18021.1Skamil
18031.29Skamil#if defined(TWAIT_HAVE_PID)
18041.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
18051.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
18061.29Skamil		        child);
18071.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
18081.29Skamil		                      child);
18091.1Skamil
18101.29Skamil		validate_status_stopped(status, SIGTRAP);
18111.1Skamil
18121.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
18131.29Skamil		                       slen) != -1);
18141.31Skamil		if (trackfork && fn == fork) {
18151.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
18161.30Skamil			       PTRACE_FORK);
18171.30Skamil		}
18181.31Skamil		if (trackvfork && fn == vfork) {
18191.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
18201.30Skamil			       PTRACE_VFORK);
18211.30Skamil		}
18221.29Skamil
18231.29Skamil		child2 = state.pe_other_pid;
18241.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
18251.29Skamil
18261.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
18271.29Skamil		        "%d\n", TWAIT_FNAME, child2, child);
18281.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
18291.29Skamil		    child2);
18301.1Skamil
18311.29Skamil		validate_status_stopped(status, SIGTRAP);
18321.1Skamil
18331.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state,
18341.29Skamil		                       slen) != -1);
18351.31Skamil		if (trackfork && fn == fork) {
18361.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
18371.30Skamil			       PTRACE_FORK);
18381.30Skamil		}
18391.31Skamil		if (trackvfork && fn == vfork) {
18401.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
18411.30Skamil			       PTRACE_VFORK);
18421.30Skamil		}
18431.30Skamil
18441.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
18451.29Skamil
18461.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
18471.29Skamil		    "and without signal to be sent\n");
18481.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0)
18491.29Skamil		                != -1);
18501.29Skamil
18511.29Skamil		DPRINTF("Before resuming the child process where it left off "
18521.29Skamil		        "and without signal to be sent\n");
18531.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18541.30Skamil	}
18551.30Skamil#endif
18561.30Skamil
18571.31Skamil	if (trackvforkdone && fn == vfork) {
18581.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
18591.30Skamil		        child);
18601.30Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
18611.30Skamil		                      child);
18621.30Skamil
18631.30Skamil		validate_status_stopped(status, SIGTRAP);
18641.30Skamil
18651.30Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
18661.30Skamil		                       slen) != -1);
18671.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
18681.30Skamil
18691.30Skamil		child2 = state.pe_other_pid;
18701.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
18711.30Skamil		        child2);
18721.30Skamil
18731.30Skamil		DPRINTF("Before resuming the child process where it left off "
18741.30Skamil		        "and without signal to be sent\n");
18751.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18761.30Skamil	}
18771.29Skamil
18781.30Skamil#if defined(TWAIT_HAVE_PID)
18791.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
18801.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
18811.29Skamil		        "\n", TWAIT_FNAME);
18821.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
18831.29Skamil		    child2);
18841.29Skamil
18851.29Skamil		validate_status_exited(status, exitval2);
18861.29Skamil
18871.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
18881.29Skamil		        "process\n", TWAIT_FNAME);
18891.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
18901.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
18911.29Skamil	}
18921.29Skamil#endif
18931.1Skamil
18941.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
18951.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
18961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18971.1Skamil
18981.1Skamil	validate_status_stopped(status, SIGCHLD);
18991.1Skamil
19001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19011.1Skamil	    "without signal to be sent\n");
19021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19031.1Skamil
19041.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
19051.1Skamil	    TWAIT_FNAME);
19061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19071.1Skamil
19081.1Skamil	validate_status_exited(status, exitval);
19091.1Skamil
19101.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
19111.1Skamil	    TWAIT_FNAME);
19121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19131.1Skamil}
19141.28Skamil
19151.32Skamil#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent)	\
19161.32SkamilATF_TC(name);									\
19171.32SkamilATF_TC_HEAD(name, tc)								\
19181.32Skamil{										\
19191.32Skamil	atf_tc_set_md_var(tc, "descr", descr);					\
19201.32Skamil}										\
19211.32Skamil										\
19221.32SkamilATF_TC_BODY(name, tc)								\
19231.32Skamil{										\
19241.32Skamil										\
19251.32Skamil	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);		\
19261.32Skamil}
19271.32Skamil
19281.32Skamil#define F false
19291.32Skamil#define T true
19301.32Skamil
19311.32Skamil#define F_IF__0(x)
19321.32Skamil#define F_IF__1(x) x
19331.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
19341.32Skamil#define F_IF_(x,y) F_IF__(x,y)
19351.32Skamil#define F_IF(x,y) F_IF_(x,y)
19361.32Skamil
19371.32Skamil#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit)	\
19381.32Skamil        "Verify " #function "(2) called with 0"					\
19391.32Skamil        F_IF(forkbit,"|PTRACE_FORK")						\
19401.32Skamil        F_IF(vforkbit,"|PTRACE_VFORK")						\
19411.32Skamil        F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")					\
19421.32Skamil        " in EVENT_MASK."							\
19431.32Skamil        F_IF(dchildbit," Detach child in this test.")				\
19441.32Skamil        F_IF(dparentbit," Detach parent in this test.")
19451.1Skamil
19461.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
19471.31Skamil#if defined(TWAIT_HAVE_PID)
19481.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
19491.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
19501.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
19511.31Skamil#endif
19521.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
19531.31Skamil#if defined(TWAIT_HAVE_PID)
19541.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
19551.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
19561.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
19571.31Skamil#endif
19581.1Skamil
19591.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
19601.31Skamil#if defined(TWAIT_HAVE_PID)
19611.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
19621.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
19631.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
19641.31Skamil#endif
19651.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
19661.31Skamil#if defined(TWAIT_HAVE_PID)
19671.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
19681.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
19691.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
19701.31Skamil#endif
19711.31Skamil
19721.54Skamil/// ----------------------------------------------------------------------------
19731.31Skamil
19741.54Skamilenum bytes_transfer_type {
19751.54Skamil	BYTES_TRANSFER_DATA,
19761.54Skamil	BYTES_TRANSFER_DATAIO,
19771.54Skamil	BYTES_TRANSFER_TEXT,
19781.54Skamil	BYTES_TRANSFER_TEXTIO,
19791.54Skamil	BYTES_TRANSFER_AUXV
19801.54Skamil};
19811.31Skamil
19821.54Skamilstatic int __used
19831.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
19841.54Skamil{
19851.54Skamil	int e, f, g, h;
19861.1Skamil
19871.54Skamil	a *= 4;
19881.54Skamil	b += 3;
19891.54Skamil	c -= 2;
19901.54Skamil	d /= 1;
19911.1Skamil
19921.54Skamil	e = strtol("10", NULL, 10);
19931.54Skamil	f = strtol("20", NULL, 10);
19941.54Skamil	g = strtol("30", NULL, 10);
19951.54Skamil	h = strtol("40", NULL, 10);
19961.1Skamil
19971.54Skamil	return (a + b * c - d) + (e * f - g / h);
19981.1Skamil}
19991.1Skamil
20001.54Skamilstatic void
20011.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
20021.1Skamil{
20031.1Skamil	const int exitval = 5;
20041.1Skamil	const int sigval = SIGSTOP;
20051.1Skamil	pid_t child, wpid;
20061.54Skamil	bool skip = false;
20071.1Skamil
20081.54Skamil	int lookup_me = 0;
20091.54Skamil	uint8_t lookup_me8 = 0;
20101.54Skamil	uint16_t lookup_me16 = 0;
20111.54Skamil	uint32_t lookup_me32 = 0;
20121.54Skamil	uint64_t lookup_me64 = 0;
20131.1Skamil
20141.54Skamil	int magic = 0x13579246;
20151.54Skamil	uint8_t magic8 = 0xab;
20161.54Skamil	uint16_t magic16 = 0x1234;
20171.54Skamil	uint32_t magic32 = 0x98765432;
20181.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
20191.1Skamil
20201.54Skamil	struct ptrace_io_desc io;
20211.1Skamil#if defined(TWAIT_HAVE_STATUS)
20221.1Skamil	int status;
20231.1Skamil#endif
20241.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
20251.60Skre	AuxInfo ai[513], *aip;
20261.55Schristos
20271.55Schristos	ATF_REQUIRE(size < sizeof(ai));
20281.1Skamil
20291.54Skamil	/* Prepare variables for .TEXT transfers */
20301.54Skamil	switch (type) {
20311.54Skamil	case BYTES_TRANSFER_TEXT:
20321.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
20331.54Skamil		break;
20341.54Skamil	case BYTES_TRANSFER_TEXTIO:
20351.54Skamil		switch (size) {
20361.54Skamil		case 8:
20371.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
20381.54Skamil			break;
20391.54Skamil		case 16:
20401.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
20411.54Skamil			break;
20421.54Skamil		case 32:
20431.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
20441.54Skamil			break;
20451.54Skamil		case 64:
20461.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
20471.54Skamil			break;
20481.54Skamil		}
20491.54Skamil		break;
20501.54Skamil	default:
20511.54Skamil		break;
20521.54Skamil	}
20531.1Skamil
20541.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
20551.54Skamil	switch (type) {
20561.54Skamil	case BYTES_TRANSFER_TEXTIO:
20571.54Skamil	case BYTES_TRANSFER_DATAIO:
20581.54Skamil		io.piod_op = operation;
20591.54Skamil		switch (size) {
20601.54Skamil		case 8:
20611.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
20621.54Skamil			               (void *)bytes_transfer_dummy :
20631.54Skamil			               &lookup_me8;
20641.54Skamil			io.piod_addr = &lookup_me8;
20651.54Skamil			io.piod_len = sizeof(lookup_me8);
20661.54Skamil			break;
20671.54Skamil		case 16:
20681.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
20691.54Skamil			               (void *)bytes_transfer_dummy :
20701.54Skamil			               &lookup_me16;
20711.54Skamil			io.piod_addr = &lookup_me16;
20721.54Skamil			io.piod_len = sizeof(lookup_me16);
20731.54Skamil			break;
20741.54Skamil		case 32:
20751.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
20761.54Skamil			               (void *)bytes_transfer_dummy :
20771.54Skamil			               &lookup_me32;
20781.54Skamil			io.piod_addr = &lookup_me32;
20791.54Skamil			io.piod_len = sizeof(lookup_me32);
20801.54Skamil			break;
20811.54Skamil		case 64:
20821.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
20831.54Skamil			               (void *)bytes_transfer_dummy :
20841.54Skamil			               &lookup_me64;
20851.54Skamil			io.piod_addr = &lookup_me64;
20861.54Skamil			io.piod_len = sizeof(lookup_me64);
20871.54Skamil			break;
20881.54Skamil		default:
20891.54Skamil			break;
20901.54Skamil		}
20911.54Skamil		break;
20921.54Skamil	case BYTES_TRANSFER_AUXV:
20931.54Skamil		io.piod_op = operation;
20941.54Skamil		io.piod_offs = 0;
20951.54Skamil		io.piod_addr = ai;
20961.54Skamil		io.piod_len = size;
20971.54Skamil		break;
20981.54Skamil	default:
20991.54Skamil		break;
21001.1Skamil	}
21011.1Skamil
21021.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21031.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21041.1Skamil	if (child == 0) {
21051.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21061.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21071.1Skamil
21081.54Skamil		switch (type) {
21091.54Skamil		case BYTES_TRANSFER_DATA:
21101.54Skamil			switch (operation) {
21111.54Skamil			case PT_READ_D:
21121.54Skamil			case PT_READ_I:
21131.54Skamil				lookup_me = magic;
21141.54Skamil				break;
21151.54Skamil			default:
21161.54Skamil				break;
21171.54Skamil			}
21181.54Skamil			break;
21191.54Skamil		case BYTES_TRANSFER_DATAIO:
21201.54Skamil			switch (operation) {
21211.54Skamil			case PIOD_READ_D:
21221.54Skamil			case PIOD_READ_I:
21231.54Skamil				switch (size) {
21241.54Skamil				case 8:
21251.54Skamil					lookup_me8 = magic8;
21261.54Skamil					break;
21271.54Skamil				case 16:
21281.54Skamil					lookup_me16 = magic16;
21291.54Skamil					break;
21301.54Skamil				case 32:
21311.54Skamil					lookup_me32 = magic32;
21321.54Skamil					break;
21331.54Skamil				case 64:
21341.54Skamil					lookup_me64 = magic64;
21351.54Skamil					break;
21361.54Skamil				default:
21371.54Skamil					break;
21381.54Skamil				}
21391.54Skamil				break;
21401.54Skamil			default:
21411.54Skamil				break;
21421.54Skamil			}
21431.54Skamil		default:
21441.54Skamil			break;
21451.54Skamil		}
21461.54Skamil
21471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21491.1Skamil
21501.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
21511.54Skamil		switch (type) {
21521.54Skamil		case BYTES_TRANSFER_DATA:
21531.54Skamil			switch (operation) {
21541.54Skamil			case PT_WRITE_D:
21551.54Skamil			case PT_WRITE_I:
21561.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
21571.54Skamil				break;
21581.54Skamil			default:
21591.54Skamil				break;
21601.54Skamil			}
21611.54Skamil			break;
21621.54Skamil		case BYTES_TRANSFER_DATAIO:
21631.54Skamil			switch (operation) {
21641.54Skamil			case PIOD_WRITE_D:
21651.54Skamil			case PIOD_WRITE_I:
21661.54Skamil				switch (size) {
21671.54Skamil				case 8:
21681.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
21691.54Skamil					break;
21701.54Skamil				case 16:
21711.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
21721.54Skamil					break;
21731.54Skamil				case 32:
21741.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
21751.54Skamil					break;
21761.54Skamil				case 64:
21771.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
21781.54Skamil					break;
21791.54Skamil				default:
21801.54Skamil					break;
21811.54Skamil				}
21821.54Skamil				break;
21831.54Skamil			default:
21841.54Skamil				break;
21851.54Skamil			}
21861.54Skamil			break;
21871.54Skamil		case BYTES_TRANSFER_TEXT:
21881.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
21891.54Skamil			                     sizeof(magic)) == 0);
21901.54Skamil			break;
21911.54Skamil		case BYTES_TRANSFER_TEXTIO:
21921.54Skamil			switch (size) {
21931.54Skamil			case 8:
21941.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
21951.54Skamil				                     bytes_transfer_dummy,
21961.54Skamil				                     sizeof(magic8)) == 0);
21971.54Skamil				break;
21981.54Skamil			case 16:
21991.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
22001.54Skamil				                     bytes_transfer_dummy,
22011.54Skamil				                     sizeof(magic16)) == 0);
22021.54Skamil				break;
22031.54Skamil			case 32:
22041.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
22051.54Skamil				                     bytes_transfer_dummy,
22061.54Skamil				                     sizeof(magic32)) == 0);
22071.54Skamil				break;
22081.54Skamil			case 64:
22091.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
22101.54Skamil				                     bytes_transfer_dummy,
22111.54Skamil				                     sizeof(magic64)) == 0);
22121.54Skamil				break;
22131.54Skamil			}
22141.54Skamil			break;
22151.54Skamil		default:
22161.54Skamil			break;
22171.54Skamil		}
22181.54Skamil
22191.13Schristos		DPRINTF("Before exiting of the child process\n");
22201.1Skamil		_exit(exitval);
22211.1Skamil	}
22221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22231.1Skamil
22241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22261.1Skamil
22271.1Skamil	validate_status_stopped(status, sigval);
22281.1Skamil
22291.54Skamil	/* Check PaX MPROTECT */
22301.54Skamil	if (!can_we_write_to_text(child)) {
22311.54Skamil		switch (type) {
22321.54Skamil		case BYTES_TRANSFER_TEXTIO:
22331.54Skamil			switch (operation) {
22341.54Skamil			case PIOD_WRITE_D:
22351.54Skamil			case PIOD_WRITE_I:
22361.54Skamil				skip = true;
22371.54Skamil				break;
22381.54Skamil			default:
22391.54Skamil				break;
22401.54Skamil			}
22411.54Skamil			break;
22421.54Skamil		case BYTES_TRANSFER_TEXT:
22431.54Skamil			switch (operation) {
22441.54Skamil			case PT_WRITE_D:
22451.54Skamil			case PT_WRITE_I:
22461.54Skamil				skip = true;
22471.54Skamil				break;
22481.54Skamil			default:
22491.54Skamil				break;
22501.54Skamil			}
22511.54Skamil			break;
22521.54Skamil		default:
22531.54Skamil			break;
22541.54Skamil		}
22551.54Skamil	}
22561.1Skamil
22571.54Skamil	/* Bailout cleanly killing the child process */
22581.54Skamil	if (skip) {
22591.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
22601.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22611.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
22621.54Skamil		                      child);
22631.1Skamil
22641.54Skamil		validate_status_signaled(status, SIGKILL, 0);
22651.1Skamil
22661.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
22671.54Skamil	}
22681.1Skamil
22691.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
22701.54Skamil	       "parent=%d\n", child, getpid());
22711.1Skamil
22721.54Skamil	switch (type) {
22731.54Skamil	case BYTES_TRANSFER_TEXTIO:
22741.54Skamil	case BYTES_TRANSFER_DATAIO:
22751.54Skamil	case BYTES_TRANSFER_AUXV:
22761.54Skamil		switch (operation) {
22771.54Skamil		case PIOD_WRITE_D:
22781.54Skamil		case PIOD_WRITE_I:
22791.54Skamil			switch (size) {
22801.54Skamil			case 8:
22811.54Skamil				lookup_me8 = magic8;
22821.54Skamil				break;
22831.54Skamil			case 16:
22841.54Skamil				lookup_me16 = magic16;
22851.54Skamil				break;
22861.54Skamil			case 32:
22871.54Skamil				lookup_me32 = magic32;
22881.54Skamil				break;
22891.54Skamil			case 64:
22901.54Skamil				lookup_me64 = magic64;
22911.54Skamil				break;
22921.54Skamil			default:
22931.54Skamil				break;
22941.54Skamil			}
22951.54Skamil			break;
22961.54Skamil		default:
22971.54Skamil			break;
22981.54Skamil		}
22991.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23001.54Skamil		switch (operation) {
23011.54Skamil		case PIOD_READ_D:
23021.54Skamil		case PIOD_READ_I:
23031.54Skamil			switch (size) {
23041.54Skamil			case 8:
23051.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
23061.54Skamil				break;
23071.54Skamil			case 16:
23081.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
23091.54Skamil				break;
23101.54Skamil			case 32:
23111.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
23121.54Skamil				break;
23131.54Skamil			case 64:
23141.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
23151.54Skamil				break;
23161.54Skamil			default:
23171.54Skamil				break;
23181.54Skamil			}
23191.54Skamil			break;
23201.54Skamil		case PIOD_READ_AUXV:
23211.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
23221.54Skamil			        io.piod_len);
23231.54Skamil			ATF_REQUIRE(io.piod_len > 0);
23241.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
23251.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
23261.54Skamil				    (long long int)aip->a_type,
23271.54Skamil				    (long long int)aip->a_v);
23281.54Skamil			break;
23291.54Skamil		default:
23301.54Skamil			break;
23311.54Skamil		}
23321.54Skamil		break;
23331.54Skamil	case BYTES_TRANSFER_TEXT:
23341.54Skamil		switch (operation) {
23351.54Skamil		case PT_READ_D:
23361.54Skamil		case PT_READ_I:
23371.54Skamil			errno = 0;
23381.54Skamil			lookup_me = ptrace(operation, child,
23391.54Skamil			                   bytes_transfer_dummy, 0);
23401.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
23411.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
23421.54Skamil			break;
23431.54Skamil		case PT_WRITE_D:
23441.54Skamil		case PT_WRITE_I:
23451.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
23461.54Skamil			                       bytes_transfer_dummy, magic)
23471.54Skamil			                != -1);
23481.54Skamil			break;
23491.54Skamil		default:
23501.54Skamil			break;
23511.54Skamil		}
23521.54Skamil		break;
23531.54Skamil	case BYTES_TRANSFER_DATA:
23541.54Skamil		switch (operation) {
23551.54Skamil		case PT_READ_D:
23561.54Skamil		case PT_READ_I:
23571.54Skamil			errno = 0;
23581.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
23591.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
23601.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
23611.54Skamil			break;
23621.54Skamil		case PT_WRITE_D:
23631.54Skamil		case PT_WRITE_I:
23641.54Skamil			lookup_me = magic;
23651.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
23661.54Skamil			                       magic) != -1);
23671.54Skamil			break;
23681.54Skamil		default:
23691.54Skamil			break;
23701.54Skamil		}
23711.54Skamil		break;
23721.54Skamil	default:
23731.54Skamil		break;
23741.54Skamil	}
23751.1Skamil
23761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23771.1Skamil	    "without signal to be sent\n");
23781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23791.1Skamil
23801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23821.1Skamil
23831.1Skamil	validate_status_exited(status, exitval);
23841.1Skamil
23851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23871.1Skamil}
23881.1Skamil
23891.54Skamil#define BYTES_TRANSFER(test, operation, size, type)				\
23901.54SkamilATF_TC(test);									\
23911.54SkamilATF_TC_HEAD(test, tc)								\
23921.54Skamil{										\
23931.54Skamil	atf_tc_set_md_var(tc, "descr",						\
23941.54Skamil	    "Verify bytes transfer operation" #operation " and size " #size	\
23951.54Skamil	    " of type " #type);							\
23961.54Skamil}										\
23971.54Skamil										\
23981.54SkamilATF_TC_BODY(test, tc)								\
23991.54Skamil{										\
24001.54Skamil										\
24011.54Skamil	bytes_transfer(operation, size, BYTES_TRANSFER_##type);			\
24021.1Skamil}
24031.1Skamil
24041.54Skamil// DATA
24051.1Skamil
24061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
24071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
24081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
24091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
24101.54Skamil
24111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
24121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
24131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
24141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
24151.54Skamil
24161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
24171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
24181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
24191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
24201.54Skamil
24211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
24221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
24231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
24241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
24251.54Skamil
24261.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
24271.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
24281.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
24291.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
24301.54Skamil
24311.54Skamil// TEXT
24321.54Skamil
24331.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
24341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
24351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
24361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
24371.54Skamil
24381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
24391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
24401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
24411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
24421.54Skamil
24431.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
24441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
24451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
24461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
24471.54Skamil
24481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
24491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
24501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
24511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
24521.54Skamil
24531.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
24541.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
24551.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
24561.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
24571.1Skamil
24581.54Skamil// AUXV
24591.1Skamil
24601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
24611.1Skamil
24621.54Skamil/// ----------------------------------------------------------------------------
24631.1Skamil
24641.1Skamil#if defined(HAVE_GPREGS)
24651.1SkamilATF_TC(regs1);
24661.1SkamilATF_TC_HEAD(regs1, tc)
24671.1Skamil{
24681.1Skamil	atf_tc_set_md_var(tc, "descr",
24691.1Skamil	    "Verify plain PT_GETREGS call without further steps");
24701.1Skamil}
24711.1Skamil
24721.1SkamilATF_TC_BODY(regs1, tc)
24731.1Skamil{
24741.1Skamil	const int exitval = 5;
24751.1Skamil	const int sigval = SIGSTOP;
24761.1Skamil	pid_t child, wpid;
24771.1Skamil#if defined(TWAIT_HAVE_STATUS)
24781.1Skamil	int status;
24791.1Skamil#endif
24801.1Skamil	struct reg r;
24811.1Skamil
24821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24841.1Skamil	if (child == 0) {
24851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24871.1Skamil
24881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24901.1Skamil
24911.13Schristos		DPRINTF("Before exiting of the child process\n");
24921.1Skamil		_exit(exitval);
24931.1Skamil	}
24941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24951.1Skamil
24961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24981.1Skamil
24991.1Skamil	validate_status_stopped(status, sigval);
25001.1Skamil
25011.13Schristos	DPRINTF("Call GETREGS for the child process\n");
25021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
25031.1Skamil
25041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25051.1Skamil	    "without signal to be sent\n");
25061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25071.1Skamil
25081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25101.1Skamil
25111.1Skamil	validate_status_exited(status, exitval);
25121.1Skamil
25131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25151.1Skamil}
25161.1Skamil#endif
25171.1Skamil
25181.1Skamil#if defined(HAVE_GPREGS)
25191.1SkamilATF_TC(regs2);
25201.1SkamilATF_TC_HEAD(regs2, tc)
25211.1Skamil{
25221.1Skamil	atf_tc_set_md_var(tc, "descr",
25231.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
25241.1Skamil}
25251.1Skamil
25261.1SkamilATF_TC_BODY(regs2, tc)
25271.1Skamil{
25281.1Skamil	const int exitval = 5;
25291.1Skamil	const int sigval = SIGSTOP;
25301.1Skamil	pid_t child, wpid;
25311.1Skamil#if defined(TWAIT_HAVE_STATUS)
25321.1Skamil	int status;
25331.1Skamil#endif
25341.1Skamil	struct reg r;
25351.1Skamil
25361.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25371.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25381.1Skamil	if (child == 0) {
25391.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25401.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25411.1Skamil
25421.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25431.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25441.1Skamil
25451.13Schristos		DPRINTF("Before exiting of the child process\n");
25461.1Skamil		_exit(exitval);
25471.1Skamil	}
25481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25491.1Skamil
25501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25521.1Skamil
25531.1Skamil	validate_status_stopped(status, sigval);
25541.1Skamil
25551.13Schristos	DPRINTF("Call GETREGS for the child process\n");
25561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
25571.1Skamil
25581.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
25591.1Skamil
25601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25611.1Skamil	    "without signal to be sent\n");
25621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25631.1Skamil
25641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25661.1Skamil
25671.1Skamil	validate_status_exited(status, exitval);
25681.1Skamil
25691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25711.1Skamil}
25721.1Skamil#endif
25731.1Skamil
25741.1Skamil#if defined(HAVE_GPREGS)
25751.1SkamilATF_TC(regs3);
25761.1SkamilATF_TC_HEAD(regs3, tc)
25771.1Skamil{
25781.1Skamil	atf_tc_set_md_var(tc, "descr",
25791.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
25801.1Skamil}
25811.1Skamil
25821.1SkamilATF_TC_BODY(regs3, tc)
25831.1Skamil{
25841.1Skamil	const int exitval = 5;
25851.1Skamil	const int sigval = SIGSTOP;
25861.1Skamil	pid_t child, wpid;
25871.1Skamil#if defined(TWAIT_HAVE_STATUS)
25881.1Skamil	int status;
25891.1Skamil#endif
25901.1Skamil	struct reg r;
25911.1Skamil
25921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25941.1Skamil	if (child == 0) {
25951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25971.1Skamil
25981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26001.1Skamil
26011.13Schristos		DPRINTF("Before exiting of the child process\n");
26021.1Skamil		_exit(exitval);
26031.1Skamil	}
26041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26051.1Skamil
26061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26081.1Skamil
26091.1Skamil	validate_status_stopped(status, sigval);
26101.1Skamil
26111.13Schristos	DPRINTF("Call GETREGS for the child process\n");
26121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
26131.1Skamil
26141.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
26151.1Skamil
26161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26171.1Skamil	    "without signal to be sent\n");
26181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26191.1Skamil
26201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26221.1Skamil
26231.1Skamil	validate_status_exited(status, exitval);
26241.1Skamil
26251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26271.1Skamil}
26281.1Skamil#endif
26291.1Skamil
26301.1Skamil#if defined(HAVE_GPREGS)
26311.1SkamilATF_TC(regs4);
26321.1SkamilATF_TC_HEAD(regs4, tc)
26331.1Skamil{
26341.1Skamil	atf_tc_set_md_var(tc, "descr",
26351.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
26361.1Skamil}
26371.1Skamil
26381.1SkamilATF_TC_BODY(regs4, tc)
26391.1Skamil{
26401.1Skamil	const int exitval = 5;
26411.1Skamil	const int sigval = SIGSTOP;
26421.1Skamil	pid_t child, wpid;
26431.1Skamil#if defined(TWAIT_HAVE_STATUS)
26441.1Skamil	int status;
26451.1Skamil#endif
26461.1Skamil	struct reg r;
26471.1Skamil
26481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26501.1Skamil	if (child == 0) {
26511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26531.1Skamil
26541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26561.1Skamil
26571.13Schristos		DPRINTF("Before exiting of the child process\n");
26581.1Skamil		_exit(exitval);
26591.1Skamil	}
26601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26611.1Skamil
26621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26641.1Skamil
26651.1Skamil	validate_status_stopped(status, sigval);
26661.1Skamil
26671.13Schristos	DPRINTF("Call GETREGS for the child process\n");
26681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
26691.1Skamil
26701.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
26711.1Skamil
26721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26731.1Skamil	    "without signal to be sent\n");
26741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26751.1Skamil
26761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26781.1Skamil
26791.1Skamil	validate_status_exited(status, exitval);
26801.1Skamil
26811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26831.1Skamil}
26841.1Skamil#endif
26851.1Skamil
26861.1Skamil#if defined(HAVE_GPREGS)
26871.1SkamilATF_TC(regs5);
26881.1SkamilATF_TC_HEAD(regs5, tc)
26891.1Skamil{
26901.1Skamil	atf_tc_set_md_var(tc, "descr",
26911.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
26921.1Skamil}
26931.1Skamil
26941.1SkamilATF_TC_BODY(regs5, tc)
26951.1Skamil{
26961.1Skamil	const int exitval = 5;
26971.1Skamil	const int sigval = SIGSTOP;
26981.1Skamil	pid_t child, wpid;
26991.1Skamil#if defined(TWAIT_HAVE_STATUS)
27001.1Skamil	int status;
27011.1Skamil#endif
27021.1Skamil	struct reg r;
27031.1Skamil
27041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27061.1Skamil	if (child == 0) {
27071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27091.1Skamil
27101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27121.1Skamil
27131.13Schristos		DPRINTF("Before exiting of the child process\n");
27141.1Skamil		_exit(exitval);
27151.1Skamil	}
27161.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27171.1Skamil
27181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27201.1Skamil
27211.1Skamil	validate_status_stopped(status, sigval);
27221.1Skamil
27231.13Schristos	DPRINTF("Call GETREGS for the child process\n");
27241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
27251.1Skamil
27261.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
27271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
27281.1Skamil
27291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27301.1Skamil	    "without signal to be sent\n");
27311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27321.1Skamil
27331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27351.1Skamil
27361.1Skamil	validate_status_exited(status, exitval);
27371.1Skamil
27381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27401.1Skamil}
27411.1Skamil#endif
27421.1Skamil
27431.1Skamil#if defined(HAVE_FPREGS)
27441.1SkamilATF_TC(fpregs1);
27451.1SkamilATF_TC_HEAD(fpregs1, tc)
27461.1Skamil{
27471.1Skamil	atf_tc_set_md_var(tc, "descr",
27481.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
27491.1Skamil}
27501.1Skamil
27511.1SkamilATF_TC_BODY(fpregs1, tc)
27521.1Skamil{
27531.1Skamil	const int exitval = 5;
27541.1Skamil	const int sigval = SIGSTOP;
27551.1Skamil	pid_t child, wpid;
27561.1Skamil#if defined(TWAIT_HAVE_STATUS)
27571.1Skamil	int status;
27581.1Skamil#endif
27591.1Skamil	struct fpreg r;
27601.1Skamil
27611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27631.1Skamil	if (child == 0) {
27641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27661.1Skamil
27671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27691.1Skamil
27701.13Schristos		DPRINTF("Before exiting of the child process\n");
27711.1Skamil		_exit(exitval);
27721.1Skamil	}
27731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27741.1Skamil
27751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27771.1Skamil
27781.1Skamil	validate_status_stopped(status, sigval);
27791.1Skamil
27801.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
27811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
27821.1Skamil
27831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27841.1Skamil	    "without signal to be sent\n");
27851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27861.1Skamil
27871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27891.1Skamil
27901.1Skamil	validate_status_exited(status, exitval);
27911.1Skamil
27921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27941.1Skamil}
27951.1Skamil#endif
27961.1Skamil
27971.1Skamil#if defined(HAVE_FPREGS)
27981.1SkamilATF_TC(fpregs2);
27991.1SkamilATF_TC_HEAD(fpregs2, tc)
28001.1Skamil{
28011.1Skamil	atf_tc_set_md_var(tc, "descr",
28021.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
28031.1Skamil	    "regs");
28041.1Skamil}
28051.1Skamil
28061.1SkamilATF_TC_BODY(fpregs2, tc)
28071.1Skamil{
28081.1Skamil	const int exitval = 5;
28091.1Skamil	const int sigval = SIGSTOP;
28101.1Skamil	pid_t child, wpid;
28111.1Skamil#if defined(TWAIT_HAVE_STATUS)
28121.1Skamil	int status;
28131.1Skamil#endif
28141.1Skamil	struct fpreg r;
28151.1Skamil
28161.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28171.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28181.1Skamil	if (child == 0) {
28191.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28201.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28211.1Skamil
28221.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28231.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28241.1Skamil
28251.13Schristos		DPRINTF("Before exiting of the child process\n");
28261.1Skamil		_exit(exitval);
28271.1Skamil	}
28281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28291.1Skamil
28301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28321.1Skamil
28331.1Skamil	validate_status_stopped(status, sigval);
28341.1Skamil
28351.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
28361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
28371.1Skamil
28381.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
28391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
28401.1Skamil
28411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28421.1Skamil	    "without signal to be sent\n");
28431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28441.1Skamil
28451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28471.1Skamil
28481.1Skamil	validate_status_exited(status, exitval);
28491.1Skamil
28501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28521.1Skamil}
28531.1Skamil#endif
28541.1Skamil
28551.1Skamil#if defined(PT_STEP)
28561.1Skamilstatic void
28571.2Skamilptrace_step(int N, int setstep)
28581.1Skamil{
28591.1Skamil	const int exitval = 5;
28601.1Skamil	const int sigval = SIGSTOP;
28611.1Skamil	pid_t child, wpid;
28621.1Skamil#if defined(TWAIT_HAVE_STATUS)
28631.1Skamil	int status;
28641.1Skamil#endif
28651.1Skamil	int happy;
28661.1Skamil
28671.1Skamil#if defined(__arm__)
28681.1Skamil	/* PT_STEP not supported on arm 32-bit */
28691.1Skamil	atf_tc_expect_fail("PR kern/52119");
28701.1Skamil#endif
28711.1Skamil
28721.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28731.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28741.1Skamil	if (child == 0) {
28751.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28761.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28771.1Skamil
28781.1Skamil		happy = check_happy(999);
28791.1Skamil
28801.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28811.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28821.1Skamil
28831.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
28841.1Skamil
28851.13Schristos		DPRINTF("Before exiting of the child process\n");
28861.1Skamil		_exit(exitval);
28871.1Skamil	}
28881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28891.1Skamil
28901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28921.1Skamil
28931.1Skamil	validate_status_stopped(status, sigval);
28941.1Skamil
28951.1Skamil	while (N --> 0) {
28961.2Skamil		if (setstep) {
28971.13Schristos			DPRINTF("Before resuming the child process where it "
28981.2Skamil			    "left off and without signal to be sent (use "
28991.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
29001.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
29011.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
29021.2Skamil			    != -1);
29031.2Skamil		} else {
29041.13Schristos			DPRINTF("Before resuming the child process where it "
29051.2Skamil			    "left off and without signal to be sent (use "
29061.2Skamil			    "PT_STEP)\n");
29071.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
29081.2Skamil			    != -1);
29091.2Skamil		}
29101.1Skamil
29111.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29121.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
29131.1Skamil		    child);
29141.1Skamil
29151.1Skamil		validate_status_stopped(status, SIGTRAP);
29161.2Skamil
29171.2Skamil		if (setstep) {
29181.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
29191.2Skamil		}
29201.1Skamil	}
29211.1Skamil
29221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29231.1Skamil	    "without signal to be sent\n");
29241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29251.1Skamil
29261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29281.1Skamil
29291.1Skamil	validate_status_exited(status, exitval);
29301.1Skamil
29311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29331.1Skamil}
29341.1Skamil#endif
29351.1Skamil
29361.1Skamil#if defined(PT_STEP)
29371.1SkamilATF_TC(step1);
29381.1SkamilATF_TC_HEAD(step1, tc)
29391.1Skamil{
29401.1Skamil	atf_tc_set_md_var(tc, "descr",
29411.1Skamil	    "Verify single PT_STEP call");
29421.1Skamil}
29431.1Skamil
29441.1SkamilATF_TC_BODY(step1, tc)
29451.1Skamil{
29461.2Skamil	ptrace_step(1, 0);
29471.1Skamil}
29481.1Skamil#endif
29491.1Skamil
29501.1Skamil#if defined(PT_STEP)
29511.1SkamilATF_TC(step2);
29521.1SkamilATF_TC_HEAD(step2, tc)
29531.1Skamil{
29541.1Skamil	atf_tc_set_md_var(tc, "descr",
29551.1Skamil	    "Verify PT_STEP called twice");
29561.1Skamil}
29571.1Skamil
29581.1SkamilATF_TC_BODY(step2, tc)
29591.1Skamil{
29601.2Skamil	ptrace_step(2, 0);
29611.1Skamil}
29621.1Skamil#endif
29631.1Skamil
29641.1Skamil#if defined(PT_STEP)
29651.1SkamilATF_TC(step3);
29661.1SkamilATF_TC_HEAD(step3, tc)
29671.1Skamil{
29681.1Skamil	atf_tc_set_md_var(tc, "descr",
29691.1Skamil	    "Verify PT_STEP called three times");
29701.1Skamil}
29711.1Skamil
29721.1SkamilATF_TC_BODY(step3, tc)
29731.1Skamil{
29741.2Skamil	ptrace_step(3, 0);
29751.1Skamil}
29761.1Skamil#endif
29771.1Skamil
29781.1Skamil#if defined(PT_STEP)
29791.1SkamilATF_TC(step4);
29801.1SkamilATF_TC_HEAD(step4, tc)
29811.1Skamil{
29821.1Skamil	atf_tc_set_md_var(tc, "descr",
29831.1Skamil	    "Verify PT_STEP called four times");
29841.1Skamil}
29851.1Skamil
29861.1SkamilATF_TC_BODY(step4, tc)
29871.1Skamil{
29881.2Skamil	ptrace_step(4, 0);
29891.2Skamil}
29901.2Skamil#endif
29911.2Skamil
29921.2Skamil#if defined(PT_STEP)
29931.2SkamilATF_TC(setstep1);
29941.2SkamilATF_TC_HEAD(setstep1, tc)
29951.2Skamil{
29961.2Skamil	atf_tc_set_md_var(tc, "descr",
29971.2Skamil	    "Verify single PT_SETSTEP call");
29981.2Skamil}
29991.2Skamil
30001.2SkamilATF_TC_BODY(setstep1, tc)
30011.2Skamil{
30021.2Skamil	ptrace_step(1, 1);
30031.2Skamil}
30041.2Skamil#endif
30051.2Skamil
30061.2Skamil#if defined(PT_STEP)
30071.2SkamilATF_TC(setstep2);
30081.2SkamilATF_TC_HEAD(setstep2, tc)
30091.2Skamil{
30101.2Skamil	atf_tc_set_md_var(tc, "descr",
30111.2Skamil	    "Verify PT_SETSTEP called twice");
30121.2Skamil}
30131.2Skamil
30141.2SkamilATF_TC_BODY(setstep2, tc)
30151.2Skamil{
30161.2Skamil	ptrace_step(2, 1);
30171.2Skamil}
30181.2Skamil#endif
30191.2Skamil
30201.2Skamil#if defined(PT_STEP)
30211.2SkamilATF_TC(setstep3);
30221.2SkamilATF_TC_HEAD(setstep3, tc)
30231.2Skamil{
30241.2Skamil	atf_tc_set_md_var(tc, "descr",
30251.2Skamil	    "Verify PT_SETSTEP called three times");
30261.2Skamil}
30271.2Skamil
30281.2SkamilATF_TC_BODY(setstep3, tc)
30291.2Skamil{
30301.2Skamil	ptrace_step(3, 1);
30311.2Skamil}
30321.2Skamil#endif
30331.2Skamil
30341.2Skamil#if defined(PT_STEP)
30351.2SkamilATF_TC(setstep4);
30361.2SkamilATF_TC_HEAD(setstep4, tc)
30371.2Skamil{
30381.2Skamil	atf_tc_set_md_var(tc, "descr",
30391.2Skamil	    "Verify PT_SETSTEP called four times");
30401.2Skamil}
30411.2Skamil
30421.2SkamilATF_TC_BODY(setstep4, tc)
30431.2Skamil{
30441.2Skamil	ptrace_step(4, 1);
30451.1Skamil}
30461.1Skamil#endif
30471.1Skamil
30481.1SkamilATF_TC(kill1);
30491.1SkamilATF_TC_HEAD(kill1, tc)
30501.1Skamil{
30511.1Skamil	atf_tc_set_md_var(tc, "descr",
30521.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
30531.1Skamil}
30541.1Skamil
30551.1SkamilATF_TC_BODY(kill1, tc)
30561.1Skamil{
30571.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
30581.1Skamil	pid_t child, wpid;
30591.1Skamil#if defined(TWAIT_HAVE_STATUS)
30601.1Skamil	int status;
30611.1Skamil#endif
30621.1Skamil
30631.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30641.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30651.1Skamil	if (child == 0) {
30661.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30671.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30681.1Skamil
30691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30711.1Skamil
30721.1Skamil		/* NOTREACHED */
30731.1Skamil		FORKEE_ASSERTX(0 &&
30741.1Skamil		    "Child should be terminated by a signal from its parent");
30751.1Skamil	}
30761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30771.1Skamil
30781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30801.1Skamil
30811.1Skamil	validate_status_stopped(status, sigval);
30821.1Skamil
30831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30841.1Skamil	    "without signal to be sent\n");
30851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
30861.1Skamil
30871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30891.1Skamil
30901.1Skamil	validate_status_signaled(status, sigsent, 0);
30911.1Skamil
30921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30941.1Skamil}
30951.1Skamil
30961.1SkamilATF_TC(kill2);
30971.1SkamilATF_TC_HEAD(kill2, tc)
30981.1Skamil{
30991.1Skamil	atf_tc_set_md_var(tc, "descr",
31001.1Skamil	    "Verify that PT_KILL terminates child");
31011.1Skamil}
31021.1Skamil
31031.1SkamilATF_TC_BODY(kill2, tc)
31041.1Skamil{
31051.1Skamil	const int sigval = SIGSTOP;
31061.1Skamil	pid_t child, wpid;
31071.1Skamil#if defined(TWAIT_HAVE_STATUS)
31081.1Skamil	int status;
31091.1Skamil#endif
31101.1Skamil
31111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31131.1Skamil	if (child == 0) {
31141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31161.1Skamil
31171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31191.1Skamil
31201.1Skamil		/* NOTREACHED */
31211.1Skamil		FORKEE_ASSERTX(0 &&
31221.1Skamil		    "Child should be terminated by a signal from its parent");
31231.1Skamil	}
31241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31251.1Skamil
31261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31281.1Skamil
31291.1Skamil	validate_status_stopped(status, sigval);
31301.1Skamil
31311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31321.1Skamil	    "without signal to be sent\n");
31331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
31341.1Skamil
31351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31371.1Skamil
31381.1Skamil	validate_status_signaled(status, SIGKILL, 0);
31391.1Skamil
31401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31421.1Skamil}
31431.1Skamil
31441.1SkamilATF_TC(lwpinfo1);
31451.1SkamilATF_TC_HEAD(lwpinfo1, tc)
31461.1Skamil{
31471.1Skamil	atf_tc_set_md_var(tc, "descr",
31481.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
31491.1Skamil}
31501.1Skamil
31511.1SkamilATF_TC_BODY(lwpinfo1, tc)
31521.1Skamil{
31531.1Skamil	const int exitval = 5;
31541.1Skamil	const int sigval = SIGSTOP;
31551.1Skamil	pid_t child, wpid;
31561.1Skamil#if defined(TWAIT_HAVE_STATUS)
31571.1Skamil	int status;
31581.1Skamil#endif
31591.1Skamil	struct ptrace_lwpinfo info = {0, 0};
31601.1Skamil
31611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31631.1Skamil	if (child == 0) {
31641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31661.1Skamil
31671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31691.1Skamil
31701.13Schristos		DPRINTF("Before exiting of the child process\n");
31711.1Skamil		_exit(exitval);
31721.1Skamil	}
31731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31741.1Skamil
31751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31771.1Skamil
31781.1Skamil	validate_status_stopped(status, sigval);
31791.1Skamil
31801.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
31811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
31821.1Skamil
31831.13Schristos	DPRINTF("Assert that there exists a thread\n");
31841.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
31851.1Skamil
31861.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
31871.1Skamil	    info.pl_lwpid);
31881.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
31891.1Skamil	    "Received event %d != expected event %d",
31901.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
31911.1Skamil
31921.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
31931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
31941.1Skamil
31951.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
31961.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
31971.1Skamil
31981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31991.1Skamil	    "without signal to be sent\n");
32001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32011.1Skamil
32021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32041.1Skamil
32051.1Skamil	validate_status_exited(status, exitval);
32061.1Skamil
32071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32081.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32091.1Skamil}
32101.1Skamil
32111.1Skamil#if defined(TWAIT_HAVE_PID)
32121.1SkamilATF_TC(lwpinfo2);
32131.1SkamilATF_TC_HEAD(lwpinfo2, tc)
32141.1Skamil{
32151.1Skamil	atf_tc_set_md_var(tc, "descr",
32161.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
32171.1Skamil	    "tracer)");
32181.1Skamil}
32191.1Skamil
32201.1SkamilATF_TC_BODY(lwpinfo2, tc)
32211.1Skamil{
32221.1Skamil	struct msg_fds parent_tracee, parent_tracer;
32231.1Skamil	const int exitval_tracee = 5;
32241.1Skamil	const int exitval_tracer = 10;
32251.1Skamil	pid_t tracee, tracer, wpid;
32261.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
32271.1Skamil#if defined(TWAIT_HAVE_STATUS)
32281.1Skamil	int status;
32291.1Skamil#endif
32301.1Skamil	struct ptrace_lwpinfo info = {0, 0};
32311.1Skamil
32321.13Schristos	DPRINTF("Spawn tracee\n");
32331.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
32341.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
32351.1Skamil	tracee = atf_utils_fork();
32361.1Skamil	if (tracee == 0) {
32371.1Skamil
32381.1Skamil		/* Wait for message from the parent */
32391.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
32401.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
32411.1Skamil
32421.1Skamil		_exit(exitval_tracee);
32431.1Skamil	}
32441.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
32451.1Skamil
32461.13Schristos	DPRINTF("Spawn debugger\n");
32471.1Skamil	tracer = atf_utils_fork();
32481.1Skamil	if (tracer == 0) {
32491.1Skamil		/* No IPC to communicate with the child */
32501.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
32511.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
32521.1Skamil
32531.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
32541.1Skamil		FORKEE_REQUIRE_SUCCESS(
32551.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
32561.1Skamil
32571.1Skamil		forkee_status_stopped(status, SIGSTOP);
32581.1Skamil
32591.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
32601.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
32611.1Skamil		    != -1);
32621.1Skamil
32631.13Schristos		DPRINTF("Assert that there exists a thread\n");
32641.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
32651.1Skamil
32661.13Schristos		DPRINTF("Assert that lwp thread %d received event "
32671.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
32681.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
32691.1Skamil
32701.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
32711.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
32721.1Skamil		    != -1);
32731.1Skamil
32741.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
32751.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
32761.1Skamil
32771.1Skamil		/* Resume tracee with PT_CONTINUE */
32781.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
32791.1Skamil
32801.1Skamil		/* Inform parent that tracer has attached to tracee */
32811.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
32821.1Skamil		/* Wait for parent */
32831.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
32841.1Skamil
32851.1Skamil		/* Wait for tracee and assert that it exited */
32861.1Skamil		FORKEE_REQUIRE_SUCCESS(
32871.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
32881.1Skamil
32891.1Skamil		forkee_status_exited(status, exitval_tracee);
32901.1Skamil
32911.13Schristos		DPRINTF("Before exiting of the tracer process\n");
32921.1Skamil		_exit(exitval_tracer);
32931.1Skamil	}
32941.1Skamil
32951.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
32961.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
32971.1Skamil
32981.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
32991.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
33001.1Skamil
33011.13Schristos	DPRINTF("Detect that tracee is zombie\n");
33021.1Skamil	await_zombie(tracee);
33031.1Skamil
33041.13Schristos	DPRINTF("Assert that there is no status about tracee - "
33051.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
33061.1Skamil	TWAIT_REQUIRE_SUCCESS(
33071.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
33081.1Skamil
33091.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
33101.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
33111.1Skamil
33121.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
33131.1Skamil	    TWAIT_FNAME);
33141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
33151.1Skamil	    tracer);
33161.1Skamil
33171.1Skamil	validate_status_exited(status, exitval_tracer);
33181.1Skamil
33191.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
33201.1Skamil	    TWAIT_FNAME);
33211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
33221.1Skamil	    tracee);
33231.1Skamil
33241.1Skamil	validate_status_exited(status, exitval_tracee);
33251.1Skamil
33261.1Skamil	msg_close(&parent_tracer);
33271.1Skamil	msg_close(&parent_tracee);
33281.1Skamil}
33291.1Skamil#endif
33301.1Skamil
33311.1SkamilATF_TC(siginfo1);
33321.1SkamilATF_TC_HEAD(siginfo1, tc)
33331.1Skamil{
33341.1Skamil	atf_tc_set_md_var(tc, "descr",
33351.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
33361.1Skamil}
33371.1Skamil
33381.1SkamilATF_TC_BODY(siginfo1, tc)
33391.1Skamil{
33401.1Skamil	const int exitval = 5;
33411.1Skamil	const int sigval = SIGTRAP;
33421.1Skamil	pid_t child, wpid;
33431.1Skamil#if defined(TWAIT_HAVE_STATUS)
33441.1Skamil	int status;
33451.1Skamil#endif
33461.1Skamil	struct ptrace_siginfo info;
33471.1Skamil	memset(&info, 0, sizeof(info));
33481.1Skamil
33491.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33501.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33511.1Skamil	if (child == 0) {
33521.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33531.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33541.1Skamil
33551.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33561.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33571.1Skamil
33581.13Schristos		DPRINTF("Before exiting of the child process\n");
33591.1Skamil		_exit(exitval);
33601.1Skamil	}
33611.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33621.1Skamil
33631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33651.1Skamil
33661.1Skamil	validate_status_stopped(status, sigval);
33671.1Skamil
33681.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
33691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
33701.1Skamil
33711.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
33721.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
33731.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
33741.1Skamil	    info.psi_siginfo.si_errno);
33751.1Skamil
33761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33771.1Skamil	    "without signal to be sent\n");
33781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33791.1Skamil
33801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33821.1Skamil
33831.1Skamil	validate_status_exited(status, exitval);
33841.1Skamil
33851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33871.1Skamil}
33881.1Skamil
33891.1SkamilATF_TC(siginfo2);
33901.1SkamilATF_TC_HEAD(siginfo2, tc)
33911.1Skamil{
33921.1Skamil	atf_tc_set_md_var(tc, "descr",
33931.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
33941.1Skamil	    "modification of SIGINT from tracee");
33951.1Skamil}
33961.1Skamil
33971.1Skamilstatic int siginfo2_caught = 0;
33981.1Skamil
33991.1Skamilstatic void
34001.1Skamilsiginfo2_sighandler(int sig)
34011.1Skamil{
34021.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
34031.1Skamil
34041.1Skamil	++siginfo2_caught;
34051.1Skamil}
34061.1Skamil
34071.1SkamilATF_TC_BODY(siginfo2, tc)
34081.1Skamil{
34091.1Skamil	const int exitval = 5;
34101.1Skamil	const int sigval = SIGINT;
34111.1Skamil	pid_t child, wpid;
34121.1Skamil	struct sigaction sa;
34131.1Skamil#if defined(TWAIT_HAVE_STATUS)
34141.1Skamil	int status;
34151.1Skamil#endif
34161.1Skamil	struct ptrace_siginfo info;
34171.1Skamil	memset(&info, 0, sizeof(info));
34181.1Skamil
34191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34211.1Skamil	if (child == 0) {
34221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34241.1Skamil
34251.1Skamil		sa.sa_handler = siginfo2_sighandler;
34261.1Skamil		sa.sa_flags = SA_SIGINFO;
34271.1Skamil		sigemptyset(&sa.sa_mask);
34281.1Skamil
34291.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
34301.1Skamil
34311.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34321.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34331.1Skamil
34341.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
34351.1Skamil
34361.13Schristos		DPRINTF("Before exiting of the child process\n");
34371.1Skamil		_exit(exitval);
34381.1Skamil	}
34391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34401.1Skamil
34411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34431.1Skamil
34441.1Skamil	validate_status_stopped(status, sigval);
34451.1Skamil
34461.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
34471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
34481.1Skamil
34491.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
34501.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
34511.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
34521.1Skamil	    info.psi_siginfo.si_errno);
34531.1Skamil
34541.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
34551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
34561.1Skamil
34571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34581.1Skamil	    "without signal to be sent\n");
34591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
34601.1Skamil
34611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34631.1Skamil
34641.1Skamil	validate_status_exited(status, exitval);
34651.1Skamil
34661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34681.1Skamil}
34691.1Skamil
34701.1SkamilATF_TC(siginfo3);
34711.1SkamilATF_TC_HEAD(siginfo3, tc)
34721.1Skamil{
34731.1Skamil	atf_tc_set_md_var(tc, "descr",
34741.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
34751.1Skamil	    "setting signal to new value");
34761.1Skamil}
34771.1Skamil
34781.1Skamilstatic int siginfo3_caught = 0;
34791.1Skamil
34801.1Skamilstatic void
34811.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
34821.1Skamil{
34831.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
34841.1Skamil
34851.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
34861.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
34871.1Skamil
34881.1Skamil	++siginfo3_caught;
34891.1Skamil}
34901.1Skamil
34911.1SkamilATF_TC_BODY(siginfo3, tc)
34921.1Skamil{
34931.1Skamil	const int exitval = 5;
34941.1Skamil	const int sigval = SIGINT;
34951.1Skamil	const int sigfaked = SIGTRAP;
34961.1Skamil	const int sicodefaked = TRAP_BRKPT;
34971.1Skamil	pid_t child, wpid;
34981.1Skamil	struct sigaction sa;
34991.1Skamil#if defined(TWAIT_HAVE_STATUS)
35001.1Skamil	int status;
35011.1Skamil#endif
35021.1Skamil	struct ptrace_siginfo info;
35031.1Skamil	memset(&info, 0, sizeof(info));
35041.1Skamil
35051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35071.1Skamil	if (child == 0) {
35081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35101.1Skamil
35111.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
35121.1Skamil		sa.sa_flags = SA_SIGINFO;
35131.1Skamil		sigemptyset(&sa.sa_mask);
35141.1Skamil
35151.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
35161.1Skamil
35171.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35181.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35191.1Skamil
35201.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
35211.1Skamil
35221.13Schristos		DPRINTF("Before exiting of the child process\n");
35231.1Skamil		_exit(exitval);
35241.1Skamil	}
35251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35261.1Skamil
35271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35291.1Skamil
35301.1Skamil	validate_status_stopped(status, sigval);
35311.1Skamil
35321.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35341.1Skamil
35351.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35361.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35371.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35381.1Skamil	    info.psi_siginfo.si_errno);
35391.1Skamil
35401.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
35411.1Skamil	    sigfaked, sicodefaked);
35421.1Skamil	info.psi_siginfo.si_signo = sigfaked;
35431.1Skamil	info.psi_siginfo.si_code = sicodefaked;
35441.1Skamil
35451.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
35461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
35471.1Skamil
35481.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35501.1Skamil
35511.13Schristos	DPRINTF("Before checking siginfo_t\n");
35521.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
35531.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
35541.1Skamil
35551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35561.1Skamil	    "without signal to be sent\n");
35571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
35581.1Skamil
35591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35611.1Skamil
35621.1Skamil	validate_status_exited(status, exitval);
35631.1Skamil
35641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35661.1Skamil}
35671.1Skamil
35681.1SkamilATF_TC(siginfo4);
35691.1SkamilATF_TC_HEAD(siginfo4, tc)
35701.1Skamil{
35711.1Skamil	atf_tc_set_md_var(tc, "descr",
35721.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
35731.1Skamil}
35741.1Skamil
35751.1SkamilATF_TC_BODY(siginfo4, tc)
35761.1Skamil{
35771.1Skamil	const int sigval = SIGTRAP;
35781.1Skamil	pid_t child, wpid;
35791.1Skamil#if defined(TWAIT_HAVE_STATUS)
35801.1Skamil	int status;
35811.1Skamil#endif
35821.1Skamil
35831.1Skamil	struct ptrace_siginfo info;
35841.1Skamil	memset(&info, 0, sizeof(info));
35851.1Skamil
35861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35881.1Skamil	if (child == 0) {
35891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35911.1Skamil
35921.13Schristos		DPRINTF("Before calling execve(2) from child\n");
35931.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
35941.1Skamil
35951.1Skamil		FORKEE_ASSERT(0 && "Not reached");
35961.1Skamil	}
35971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35981.1Skamil
35991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36011.1Skamil
36021.1Skamil	validate_status_stopped(status, sigval);
36031.1Skamil
36041.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36061.1Skamil
36071.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36081.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
36091.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36101.1Skamil	    info.psi_siginfo.si_errno);
36111.1Skamil
36121.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
36131.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
36141.1Skamil
36151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36161.1Skamil	    "without signal to be sent\n");
36171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36181.1Skamil
36191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36211.1Skamil
36221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36241.1Skamil}
36251.1Skamil
36261.1Skamil#if defined(TWAIT_HAVE_PID)
36271.1SkamilATF_TC(siginfo5);
36281.1SkamilATF_TC_HEAD(siginfo5, tc)
36291.1Skamil{
36301.1Skamil	atf_tc_set_md_var(tc, "descr",
36311.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
36321.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
36331.1Skamil}
36341.1Skamil
36351.1SkamilATF_TC_BODY(siginfo5, tc)
36361.1Skamil{
36371.1Skamil	const int exitval = 5;
36381.1Skamil	const int exitval2 = 15;
36391.1Skamil	const int sigval = SIGSTOP;
36401.1Skamil	pid_t child, child2, wpid;
36411.1Skamil#if defined(TWAIT_HAVE_STATUS)
36421.1Skamil	int status;
36431.1Skamil#endif
36441.1Skamil	ptrace_state_t state;
36451.1Skamil	const int slen = sizeof(state);
36461.1Skamil	ptrace_event_t event;
36471.1Skamil	const int elen = sizeof(event);
36481.1Skamil	struct ptrace_siginfo info;
36491.1Skamil
36501.1Skamil	memset(&info, 0, sizeof(info));
36511.1Skamil
36521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36541.1Skamil	if (child == 0) {
36551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36571.1Skamil
36581.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36591.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36601.1Skamil
36611.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
36621.1Skamil
36631.1Skamil		if (child2 == 0)
36641.1Skamil			_exit(exitval2);
36651.1Skamil
36661.1Skamil		FORKEE_REQUIRE_SUCCESS
36671.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
36681.1Skamil
36691.1Skamil		forkee_status_exited(status, exitval2);
36701.1Skamil
36711.13Schristos		DPRINTF("Before exiting of the child process\n");
36721.1Skamil		_exit(exitval);
36731.1Skamil	}
36741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36751.1Skamil
36761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36781.1Skamil
36791.1Skamil	validate_status_stopped(status, sigval);
36801.1Skamil
36811.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36831.1Skamil
36841.13Schristos	DPRINTF("Before checking siginfo_t\n");
36851.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
36861.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
36871.1Skamil
36881.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
36891.1Skamil	event.pe_set_event = PTRACE_FORK;
36901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
36911.1Skamil
36921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36931.1Skamil	    "without signal to be sent\n");
36941.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
36951.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
36961.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
36971.1Skamil                "state.pe_other_pid=child)\n", child);
36981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36991.1Skamil
37001.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
37011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37021.1Skamil
37031.1Skamil	validate_status_stopped(status, SIGTRAP);
37041.1Skamil
37051.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37071.1Skamil
37081.13Schristos	DPRINTF("Before checking siginfo_t\n");
37091.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
37101.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
37111.1Skamil
37121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
37131.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
37141.1Skamil
37151.1Skamil	child2 = state.pe_other_pid;
37161.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
37171.1Skamil
37181.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
37191.1Skamil	    TWAIT_FNAME, child2, child);
37201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
37211.1Skamil	    child2);
37221.1Skamil
37231.1Skamil	validate_status_stopped(status, SIGTRAP);
37241.1Skamil
37251.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37271.1Skamil
37281.13Schristos	DPRINTF("Before checking siginfo_t\n");
37291.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
37301.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
37311.1Skamil
37321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
37331.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
37341.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
37351.1Skamil
37361.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
37371.1Skamil	    "without signal to be sent\n");
37381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
37391.1Skamil
37401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37411.1Skamil	    "without signal to be sent\n");
37421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37431.1Skamil
37441.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
37451.1Skamil	    TWAIT_FNAME);
37461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
37471.1Skamil	    child2);
37481.1Skamil
37491.1Skamil	validate_status_exited(status, exitval2);
37501.1Skamil
37511.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
37521.1Skamil	    TWAIT_FNAME);
37531.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
37541.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
37551.1Skamil
37561.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
37571.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
37581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37591.1Skamil
37601.1Skamil	validate_status_stopped(status, SIGCHLD);
37611.1Skamil
37621.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37641.1Skamil
37651.13Schristos	DPRINTF("Before checking siginfo_t\n");
37661.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
37671.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
37681.1Skamil
37691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37701.1Skamil	    "without signal to be sent\n");
37711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37721.1Skamil
37731.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
37741.1Skamil	    TWAIT_FNAME);
37751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37761.1Skamil
37771.1Skamil	validate_status_exited(status, exitval);
37781.1Skamil
37791.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
37801.1Skamil	    TWAIT_FNAME);
37811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37821.1Skamil}
37831.1Skamil#endif
37841.1Skamil
37851.1Skamil#if defined(PT_STEP)
37861.1SkamilATF_TC(siginfo6);
37871.1SkamilATF_TC_HEAD(siginfo6, tc)
37881.1Skamil{
37891.1Skamil	atf_tc_set_md_var(tc, "descr",
37901.1Skamil	    "Verify single PT_STEP call with signal information check");
37911.1Skamil}
37921.1Skamil
37931.1SkamilATF_TC_BODY(siginfo6, tc)
37941.1Skamil{
37951.1Skamil	const int exitval = 5;
37961.1Skamil	const int sigval = SIGSTOP;
37971.1Skamil	pid_t child, wpid;
37981.1Skamil#if defined(TWAIT_HAVE_STATUS)
37991.1Skamil	int status;
38001.1Skamil#endif
38011.1Skamil	int happy;
38021.1Skamil	struct ptrace_siginfo info;
38031.1Skamil
38041.1Skamil#if defined(__arm__)
38051.1Skamil	/* PT_STEP not supported on arm 32-bit */
38061.1Skamil	atf_tc_expect_fail("PR kern/52119");
38071.1Skamil#endif
38081.1Skamil
38091.1Skamil	memset(&info, 0, sizeof(info));
38101.1Skamil
38111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38131.1Skamil	if (child == 0) {
38141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38161.1Skamil
38171.1Skamil		happy = check_happy(100);
38181.1Skamil
38191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38211.1Skamil
38221.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
38231.1Skamil
38241.13Schristos		DPRINTF("Before exiting of the child process\n");
38251.1Skamil		_exit(exitval);
38261.1Skamil	}
38271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38281.1Skamil
38291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38311.1Skamil
38321.1Skamil	validate_status_stopped(status, sigval);
38331.1Skamil
38341.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38361.1Skamil
38371.13Schristos	DPRINTF("Before checking siginfo_t\n");
38381.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
38391.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38401.1Skamil
38411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38421.1Skamil	    "without signal to be sent (use PT_STEP)\n");
38431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
38441.1Skamil
38451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38471.1Skamil
38481.1Skamil	validate_status_stopped(status, SIGTRAP);
38491.1Skamil
38501.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38521.1Skamil
38531.13Schristos	DPRINTF("Before checking siginfo_t\n");
38541.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38551.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
38561.1Skamil
38571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38581.1Skamil	    "without signal to be sent\n");
38591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38601.1Skamil
38611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38631.1Skamil
38641.1Skamil	validate_status_exited(status, exitval);
38651.1Skamil
38661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38681.1Skamil}
38691.1Skamil#endif
38701.1Skamil
38711.1Skamilvolatile lwpid_t the_lwp_id = 0;
38721.1Skamil
38731.1Skamilstatic void
38741.1Skamillwp_main_func(void *arg)
38751.1Skamil{
38761.1Skamil	the_lwp_id = _lwp_self();
38771.1Skamil	_lwp_exit();
38781.1Skamil}
38791.1Skamil
38801.1SkamilATF_TC(lwp_create1);
38811.1SkamilATF_TC_HEAD(lwp_create1, tc)
38821.1Skamil{
38831.1Skamil	atf_tc_set_md_var(tc, "descr",
38841.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
38851.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
38861.1Skamil}
38871.1Skamil
38881.1SkamilATF_TC_BODY(lwp_create1, tc)
38891.1Skamil{
38901.1Skamil	const int exitval = 5;
38911.1Skamil	const int sigval = SIGSTOP;
38921.1Skamil	pid_t child, wpid;
38931.1Skamil#if defined(TWAIT_HAVE_STATUS)
38941.1Skamil	int status;
38951.1Skamil#endif
38961.1Skamil	ptrace_state_t state;
38971.1Skamil	const int slen = sizeof(state);
38981.1Skamil	ptrace_event_t event;
38991.1Skamil	const int elen = sizeof(event);
39001.1Skamil	ucontext_t uc;
39011.1Skamil	lwpid_t lid;
39021.1Skamil	static const size_t ssize = 16*1024;
39031.1Skamil	void *stack;
39041.1Skamil
39051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39071.1Skamil	if (child == 0) {
39081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39101.1Skamil
39111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39131.1Skamil
39141.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
39151.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
39161.1Skamil
39171.13Schristos		DPRINTF("Before making context for new lwp in child\n");
39181.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
39191.1Skamil
39201.13Schristos		DPRINTF("Before creating new in child\n");
39211.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
39221.1Skamil
39231.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
39241.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
39251.1Skamil
39261.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
39271.1Skamil		    "are the same\n", lid, the_lwp_id);
39281.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
39291.1Skamil
39301.13Schristos		DPRINTF("Before exiting of the child process\n");
39311.1Skamil		_exit(exitval);
39321.1Skamil	}
39331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39341.1Skamil
39351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39371.1Skamil
39381.1Skamil	validate_status_stopped(status, sigval);
39391.1Skamil
39401.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
39411.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
39421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
39431.1Skamil
39441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39451.1Skamil	    "without signal to be sent\n");
39461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39471.1Skamil
39481.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
39491.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
39501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39511.1Skamil
39521.1Skamil	validate_status_stopped(status, SIGTRAP);
39531.1Skamil
39541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
39551.1Skamil
39561.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
39571.1Skamil
39581.1Skamil	lid = state.pe_lwp;
39591.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
39601.1Skamil
39611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39621.1Skamil	    "without signal to be sent\n");
39631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39641.1Skamil
39651.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
39661.1Skamil	    TWAIT_FNAME);
39671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39681.1Skamil
39691.1Skamil	validate_status_exited(status, exitval);
39701.1Skamil
39711.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
39721.1Skamil	    TWAIT_FNAME);
39731.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39741.1Skamil}
39751.1Skamil
39761.1SkamilATF_TC(lwp_exit1);
39771.1SkamilATF_TC_HEAD(lwp_exit1, tc)
39781.1Skamil{
39791.1Skamil	atf_tc_set_md_var(tc, "descr",
39801.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
39811.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
39821.1Skamil}
39831.1Skamil
39841.1SkamilATF_TC_BODY(lwp_exit1, tc)
39851.1Skamil{
39861.1Skamil	const int exitval = 5;
39871.1Skamil	const int sigval = SIGSTOP;
39881.1Skamil	pid_t child, wpid;
39891.1Skamil#if defined(TWAIT_HAVE_STATUS)
39901.1Skamil	int status;
39911.1Skamil#endif
39921.1Skamil	ptrace_state_t state;
39931.1Skamil	const int slen = sizeof(state);
39941.1Skamil	ptrace_event_t event;
39951.1Skamil	const int elen = sizeof(event);
39961.1Skamil	ucontext_t uc;
39971.1Skamil	lwpid_t lid;
39981.1Skamil	static const size_t ssize = 16*1024;
39991.1Skamil	void *stack;
40001.1Skamil
40011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40031.1Skamil	if (child == 0) {
40041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40061.1Skamil
40071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40091.1Skamil
40101.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
40111.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
40121.1Skamil
40131.13Schristos		DPRINTF("Before making context for new lwp in child\n");
40141.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
40151.1Skamil
40161.13Schristos		DPRINTF("Before creating new in child\n");
40171.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
40181.1Skamil
40191.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
40201.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
40211.1Skamil
40221.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
40231.1Skamil		    "are the same\n", lid, the_lwp_id);
40241.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
40251.1Skamil
40261.13Schristos		DPRINTF("Before exiting of the child process\n");
40271.1Skamil		_exit(exitval);
40281.1Skamil	}
40291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40301.1Skamil
40311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40331.1Skamil
40341.1Skamil	validate_status_stopped(status, sigval);
40351.1Skamil
40361.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
40371.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
40381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
40391.1Skamil
40401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40411.1Skamil	    "without signal to be sent\n");
40421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40431.1Skamil
40441.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
40451.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
40461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40471.1Skamil
40481.1Skamil	validate_status_stopped(status, SIGTRAP);
40491.1Skamil
40501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
40511.1Skamil
40521.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
40531.1Skamil
40541.1Skamil	lid = state.pe_lwp;
40551.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
40561.1Skamil
40571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40581.1Skamil	    "without signal to be sent\n");
40591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40601.1Skamil
40611.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
40621.1Skamil	    TWAIT_FNAME);
40631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40641.1Skamil
40651.1Skamil	validate_status_exited(status, exitval);
40661.1Skamil
40671.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
40681.1Skamil	    TWAIT_FNAME);
40691.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40701.1Skamil}
40711.1Skamil
40721.1SkamilATF_TC(signal1);
40731.1SkamilATF_TC_HEAD(signal1, tc)
40741.1Skamil{
40751.1Skamil	atf_tc_set_md_var(tc, "descr",
40761.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
40771.1Skamil	    "from catching other signals");
40781.1Skamil}
40791.1Skamil
40801.1SkamilATF_TC_BODY(signal1, tc)
40811.1Skamil{
40821.1Skamil	const int exitval = 5;
40831.1Skamil	const int sigval = SIGSTOP;
40841.1Skamil	const int sigmasked = SIGTRAP;
40851.1Skamil	const int signotmasked = SIGINT;
40861.1Skamil	pid_t child, wpid;
40871.1Skamil#if defined(TWAIT_HAVE_STATUS)
40881.1Skamil	int status;
40891.1Skamil#endif
40901.1Skamil	sigset_t intmask;
40911.1Skamil
40921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40941.1Skamil	if (child == 0) {
40951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40971.1Skamil
40981.1Skamil		sigemptyset(&intmask);
40991.1Skamil		sigaddset(&intmask, sigmasked);
41001.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
41011.1Skamil
41021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41041.1Skamil
41051.13Schristos		DPRINTF("Before raising %s from child\n",
41061.1Skamil		    strsignal(signotmasked));
41071.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
41081.1Skamil
41091.13Schristos		DPRINTF("Before exiting of the child process\n");
41101.1Skamil		_exit(exitval);
41111.1Skamil	}
41121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41131.1Skamil
41141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41161.1Skamil
41171.1Skamil	validate_status_stopped(status, sigval);
41181.1Skamil
41191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41201.1Skamil	    "without signal to be sent\n");
41211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41221.1Skamil
41231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41251.1Skamil
41261.1Skamil	validate_status_stopped(status, signotmasked);
41271.1Skamil
41281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41291.1Skamil	    "without signal to be sent\n");
41301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41311.1Skamil
41321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41341.1Skamil
41351.1Skamil	validate_status_exited(status, exitval);
41361.1Skamil
41371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41391.1Skamil}
41401.1Skamil
41411.1SkamilATF_TC(signal2);
41421.1SkamilATF_TC_HEAD(signal2, tc)
41431.1Skamil{
41441.1Skamil	atf_tc_set_md_var(tc, "descr",
41451.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
41461.1Skamil	    "catching this raised signal");
41471.1Skamil}
41481.1Skamil
41491.1SkamilATF_TC_BODY(signal2, tc)
41501.1Skamil{
41511.1Skamil	const int exitval = 5;
41521.1Skamil	const int sigval = SIGSTOP;
41531.1Skamil	const int sigmasked = SIGTRAP;
41541.1Skamil	pid_t child, wpid;
41551.1Skamil#if defined(TWAIT_HAVE_STATUS)
41561.1Skamil	int status;
41571.1Skamil#endif
41581.1Skamil	sigset_t intmask;
41591.1Skamil
41601.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41611.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41621.1Skamil	if (child == 0) {
41631.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41641.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41651.1Skamil
41661.1Skamil		sigemptyset(&intmask);
41671.1Skamil		sigaddset(&intmask, sigmasked);
41681.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
41691.1Skamil
41701.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41711.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41721.1Skamil
41731.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
41741.1Skamil		    strsignal(sigmasked));
41751.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
41761.1Skamil
41771.13Schristos		DPRINTF("Before exiting of the child process\n");
41781.1Skamil		_exit(exitval);
41791.1Skamil	}
41801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41811.1Skamil
41821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41841.1Skamil
41851.1Skamil	validate_status_stopped(status, sigval);
41861.1Skamil
41871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41881.1Skamil	    "without signal to be sent\n");
41891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41901.1Skamil
41911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41931.1Skamil
41941.1Skamil	validate_status_exited(status, exitval);
41951.1Skamil
41961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41981.1Skamil}
41991.1Skamil
42001.1SkamilATF_TC(signal3);
42011.1SkamilATF_TC_HEAD(signal3, tc)
42021.1Skamil{
42031.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
42041.1Skamil	atf_tc_set_md_var(tc, "descr",
42051.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
42061.1Skamil	    "catching software breakpoints");
42071.1Skamil}
42081.1Skamil
42091.1SkamilATF_TC_BODY(signal3, tc)
42101.1Skamil{
42111.1Skamil	const int exitval = 5;
42121.1Skamil	const int sigval = SIGSTOP;
42131.1Skamil	const int sigmasked = SIGTRAP;
42141.1Skamil	pid_t child, wpid;
42151.1Skamil#if defined(TWAIT_HAVE_STATUS)
42161.1Skamil	int status;
42171.1Skamil#endif
42181.1Skamil	sigset_t intmask;
42191.1Skamil
42201.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42211.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42221.1Skamil	if (child == 0) {
42231.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42241.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42251.1Skamil
42261.1Skamil		sigemptyset(&intmask);
42271.1Skamil		sigaddset(&intmask, sigmasked);
42281.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42291.1Skamil
42301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42321.1Skamil
42331.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
42341.52Skamil		trigger_trap();
42351.1Skamil
42361.13Schristos		DPRINTF("Before exiting of the child process\n");
42371.1Skamil		_exit(exitval);
42381.1Skamil	}
42391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42401.1Skamil
42411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42431.1Skamil
42441.1Skamil	validate_status_stopped(status, sigval);
42451.1Skamil
42461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42471.1Skamil	    "without signal to be sent\n");
42481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42491.1Skamil
42501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42521.1Skamil
42531.1Skamil	validate_status_stopped(status, sigmasked);
42541.1Skamil
42551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42561.1Skamil	    "without signal to be sent\n");
42571.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
42581.1Skamil
42591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42611.1Skamil
42621.49Skamil	validate_status_signaled(status, SIGKILL, 0);
42631.1Skamil
42641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42661.1Skamil}
42671.1Skamil
42681.1Skamil#if defined(PT_STEP)
42691.1SkamilATF_TC(signal4);
42701.1SkamilATF_TC_HEAD(signal4, tc)
42711.1Skamil{
42721.1Skamil	atf_tc_set_md_var(tc, "descr",
42731.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
42741.1Skamil	    "catching single step trap");
42751.1Skamil}
42761.1Skamil
42771.1SkamilATF_TC_BODY(signal4, tc)
42781.1Skamil{
42791.1Skamil	const int exitval = 5;
42801.1Skamil	const int sigval = SIGSTOP;
42811.1Skamil	const int sigmasked = SIGTRAP;
42821.1Skamil	pid_t child, wpid;
42831.1Skamil#if defined(TWAIT_HAVE_STATUS)
42841.1Skamil	int status;
42851.1Skamil#endif
42861.1Skamil	sigset_t intmask;
42871.1Skamil	int happy;
42881.1Skamil
42891.1Skamil#if defined(__arm__)
42901.5Skamil	/* PT_STEP not supported on arm 32-bit */
42911.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
42921.1Skamil#endif
42931.1Skamil
42941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42961.1Skamil	if (child == 0) {
42971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42991.1Skamil
43001.1Skamil		happy = check_happy(100);
43011.1Skamil
43021.1Skamil		sigemptyset(&intmask);
43031.1Skamil		sigaddset(&intmask, sigmasked);
43041.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43051.1Skamil
43061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43081.1Skamil
43091.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
43101.1Skamil
43111.13Schristos		DPRINTF("Before exiting of the child process\n");
43121.1Skamil		_exit(exitval);
43131.1Skamil	}
43141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43151.1Skamil
43161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43181.1Skamil
43191.1Skamil	validate_status_stopped(status, sigval);
43201.1Skamil
43211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43221.1Skamil	    "without signal to be sent\n");
43231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
43241.1Skamil
43251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43271.1Skamil
43281.1Skamil	validate_status_stopped(status, sigmasked);
43291.1Skamil
43301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43311.1Skamil	    "without signal to be sent\n");
43321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43331.1Skamil
43341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43361.1Skamil
43371.1Skamil	validate_status_exited(status, exitval);
43381.1Skamil
43391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43411.1Skamil}
43421.1Skamil#endif
43431.1Skamil
43441.1SkamilATF_TC(signal5);
43451.1SkamilATF_TC_HEAD(signal5, tc)
43461.1Skamil{
43471.1Skamil	atf_tc_set_md_var(tc, "descr",
43481.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43491.1Skamil	    "catching exec() breakpoint");
43501.1Skamil}
43511.1Skamil
43521.1SkamilATF_TC_BODY(signal5, tc)
43531.1Skamil{
43541.1Skamil	const int sigval = SIGSTOP;
43551.1Skamil	const int sigmasked = SIGTRAP;
43561.1Skamil	pid_t child, wpid;
43571.1Skamil#if defined(TWAIT_HAVE_STATUS)
43581.1Skamil	int status;
43591.1Skamil#endif
43601.58Skamil	struct ptrace_siginfo info;
43611.1Skamil	sigset_t intmask;
43621.1Skamil
43631.58Skamil	memset(&info, 0, sizeof(info));
43641.14Schristos
43651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43671.1Skamil	if (child == 0) {
43681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43701.1Skamil
43711.1Skamil		sigemptyset(&intmask);
43721.1Skamil		sigaddset(&intmask, sigmasked);
43731.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43741.1Skamil
43751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43771.1Skamil
43781.13Schristos		DPRINTF("Before calling execve(2) from child\n");
43791.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
43801.1Skamil
43811.58Skamil		/* NOTREACHED */
43821.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
43831.1Skamil	}
43841.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43851.1Skamil
43861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43881.1Skamil
43891.1Skamil	validate_status_stopped(status, sigval);
43901.1Skamil
43911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43921.1Skamil	    "without signal to be sent\n");
43931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43941.1Skamil
43951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43971.1Skamil
43981.1Skamil	validate_status_stopped(status, sigmasked);
43991.1Skamil
44001.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
44011.58Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
44021.58Skamil
44031.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
44041.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
44051.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
44061.58Skamil	    info.psi_siginfo.si_errno);
44071.58Skamil
44081.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
44091.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
44101.58Skamil
44111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44121.1Skamil	    "without signal to be sent\n");
44131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44141.1Skamil
44151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44171.1Skamil
44181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44201.1Skamil}
44211.1Skamil
44221.1Skamil#if defined(TWAIT_HAVE_PID)
44231.1SkamilATF_TC(signal6);
44241.1SkamilATF_TC_HEAD(signal6, tc)
44251.1Skamil{
44261.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
44271.1Skamil	atf_tc_set_md_var(tc, "descr",
44281.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44291.1Skamil	    "catching PTRACE_FORK breakpoint");
44301.1Skamil}
44311.1Skamil
44321.1SkamilATF_TC_BODY(signal6, tc)
44331.1Skamil{
44341.1Skamil	const int exitval = 5;
44351.1Skamil	const int exitval2 = 15;
44361.1Skamil	const int sigval = SIGSTOP;
44371.1Skamil	const int sigmasked = SIGTRAP;
44381.1Skamil	pid_t child, child2, wpid;
44391.1Skamil#if defined(TWAIT_HAVE_STATUS)
44401.1Skamil	int status;
44411.1Skamil#endif
44421.1Skamil	sigset_t intmask;
44431.1Skamil	ptrace_state_t state;
44441.1Skamil	const int slen = sizeof(state);
44451.1Skamil	ptrace_event_t event;
44461.1Skamil	const int elen = sizeof(event);
44471.1Skamil
44481.38Skamil	atf_tc_expect_fail("PR kern/51918");
44491.14Schristos
44501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44521.1Skamil	if (child == 0) {
44531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44551.1Skamil
44561.1Skamil		sigemptyset(&intmask);
44571.1Skamil		sigaddset(&intmask, sigmasked);
44581.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44591.1Skamil
44601.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44611.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44621.1Skamil
44631.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
44641.1Skamil
44651.1Skamil		if (child2 == 0)
44661.1Skamil			_exit(exitval2);
44671.1Skamil
44681.1Skamil		FORKEE_REQUIRE_SUCCESS
44691.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
44701.1Skamil
44711.1Skamil		forkee_status_exited(status, exitval2);
44721.1Skamil
44731.13Schristos		DPRINTF("Before exiting of the child process\n");
44741.1Skamil		_exit(exitval);
44751.1Skamil	}
44761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44771.1Skamil
44781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44801.1Skamil
44811.1Skamil	validate_status_stopped(status, sigval);
44821.1Skamil
44831.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
44841.1Skamil	event.pe_set_event = PTRACE_FORK;
44851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
44861.1Skamil
44871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44881.1Skamil	    "without signal to be sent\n");
44891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44901.1Skamil
44911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44931.1Skamil
44941.1Skamil	validate_status_stopped(status, sigmasked);
44951.1Skamil
44961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
44971.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
44981.1Skamil
44991.1Skamil	child2 = state.pe_other_pid;
45001.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
45011.1Skamil
45021.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
45031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
45041.1Skamil	    child2);
45051.1Skamil
45061.1Skamil	validate_status_stopped(status, SIGTRAP);
45071.1Skamil
45081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
45091.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
45101.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
45111.1Skamil
45121.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
45131.1Skamil	    "without signal to be sent\n");
45141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
45151.1Skamil
45161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45171.1Skamil	    "without signal to be sent\n");
45181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45191.1Skamil
45201.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
45211.1Skamil	    TWAIT_FNAME);
45221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
45231.57Skamil	    child2);
45241.1Skamil
45251.1Skamil	validate_status_exited(status, exitval2);
45261.1Skamil
45271.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
45281.1Skamil	    TWAIT_FNAME);
45291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
45301.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
45311.1Skamil
45321.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
45331.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
45341.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45351.1Skamil
45361.1Skamil	validate_status_stopped(status, SIGCHLD);
45371.1Skamil
45381.57Skamil	DPRINTF("Before resuming the child process where it left off and "
45391.1Skamil	    "without signal to be sent\n");
45401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45411.1Skamil
45421.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
45431.1Skamil	    TWAIT_FNAME);
45441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45451.1Skamil
45461.1Skamil	validate_status_exited(status, exitval);
45471.1Skamil
45481.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
45491.57Skamil	    TWAIT_FNAME);
45501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45511.1Skamil}
45521.1Skamil#endif
45531.1Skamil
45541.1Skamil#if defined(TWAIT_HAVE_PID)
45551.1SkamilATF_TC(signal7);
45561.1SkamilATF_TC_HEAD(signal7, tc)
45571.1Skamil{
45581.1Skamil	atf_tc_set_md_var(tc, "descr",
45591.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45601.1Skamil	    "catching PTRACE_VFORK breakpoint");
45611.1Skamil}
45621.1Skamil
45631.1SkamilATF_TC_BODY(signal7, tc)
45641.1Skamil{
45651.1Skamil	const int exitval = 5;
45661.1Skamil	const int exitval2 = 15;
45671.1Skamil	const int sigval = SIGSTOP;
45681.1Skamil	const int sigmasked = SIGTRAP;
45691.1Skamil	pid_t child, child2, wpid;
45701.1Skamil#if defined(TWAIT_HAVE_STATUS)
45711.1Skamil	int status;
45721.1Skamil#endif
45731.1Skamil	sigset_t intmask;
45741.1Skamil	ptrace_state_t state;
45751.1Skamil	const int slen = sizeof(state);
45761.1Skamil	ptrace_event_t event;
45771.1Skamil	const int elen = sizeof(event);
45781.1Skamil
45791.38Skamil	atf_tc_expect_fail("PR kern/51918");
45801.14Schristos
45811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45831.1Skamil	if (child == 0) {
45841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45861.1Skamil
45871.1Skamil		sigemptyset(&intmask);
45881.1Skamil		sigaddset(&intmask, sigmasked);
45891.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45901.1Skamil
45911.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45921.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45931.1Skamil
45941.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
45951.1Skamil
45961.1Skamil		if (child2 == 0)
45971.1Skamil			_exit(exitval2);
45981.1Skamil
45991.1Skamil		FORKEE_REQUIRE_SUCCESS
46001.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
46011.1Skamil
46021.1Skamil		forkee_status_exited(status, exitval2);
46031.1Skamil
46041.13Schristos		DPRINTF("Before exiting of the child process\n");
46051.1Skamil		_exit(exitval);
46061.1Skamil	}
46071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46081.1Skamil
46091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46111.1Skamil
46121.1Skamil	validate_status_stopped(status, sigval);
46131.1Skamil
46141.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
46151.1Skamil	event.pe_set_event = PTRACE_VFORK;
46161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
46171.1Skamil
46181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46191.1Skamil	    "without signal to be sent\n");
46201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46211.1Skamil
46221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46241.1Skamil
46251.1Skamil	validate_status_stopped(status, sigmasked);
46261.1Skamil
46271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
46281.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
46291.1Skamil
46301.1Skamil	child2 = state.pe_other_pid;
46311.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
46321.1Skamil
46331.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
46341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46351.1Skamil	    child2);
46361.1Skamil
46371.1Skamil	validate_status_stopped(status, SIGTRAP);
46381.1Skamil
46391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
46401.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
46411.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
46421.1Skamil
46431.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
46441.1Skamil	    "without signal to be sent\n");
46451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
46461.1Skamil
46471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46481.1Skamil	    "without signal to be sent\n");
46491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46501.1Skamil
46511.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
46521.1Skamil	    TWAIT_FNAME);
46531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46541.57Skamil	    child2);
46551.1Skamil
46561.1Skamil	validate_status_exited(status, exitval2);
46571.1Skamil
46581.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
46591.1Skamil	    TWAIT_FNAME);
46601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
46611.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
46621.1Skamil
46631.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
46641.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
46651.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46661.1Skamil
46671.1Skamil	validate_status_stopped(status, SIGCHLD);
46681.1Skamil
46691.57Skamil	DPRINTF("Before resuming the child process where it left off and "
46701.1Skamil	    "without signal to be sent\n");
46711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46721.1Skamil
46731.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
46741.1Skamil	    TWAIT_FNAME);
46751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46761.1Skamil
46771.1Skamil	validate_status_exited(status, exitval);
46781.1Skamil
46791.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
46801.57Skamil	    TWAIT_FNAME);
46811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46821.1Skamil}
46831.1Skamil#endif
46841.1Skamil
46851.1SkamilATF_TC(signal8);
46861.1SkamilATF_TC_HEAD(signal8, tc)
46871.1Skamil{
46881.1Skamil	atf_tc_set_md_var(tc, "descr",
46891.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
46901.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
46911.1Skamil}
46921.1Skamil
46931.1SkamilATF_TC_BODY(signal8, tc)
46941.1Skamil{
46951.1Skamil	const int exitval = 5;
46961.1Skamil	const int exitval2 = 15;
46971.1Skamil	const int sigval = SIGSTOP;
46981.1Skamil	const int sigmasked = SIGTRAP;
46991.1Skamil	pid_t child, child2, wpid;
47001.1Skamil#if defined(TWAIT_HAVE_STATUS)
47011.1Skamil	int status;
47021.1Skamil#endif
47031.1Skamil	sigset_t intmask;
47041.1Skamil	ptrace_state_t state;
47051.1Skamil	const int slen = sizeof(state);
47061.1Skamil	ptrace_event_t event;
47071.1Skamil	const int elen = sizeof(event);
47081.1Skamil
47091.14Schristos	atf_tc_expect_fail("PR kern/51918");
47101.14Schristos
47111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47131.1Skamil	if (child == 0) {
47141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47161.1Skamil
47171.1Skamil		sigemptyset(&intmask);
47181.1Skamil		sigaddset(&intmask, sigmasked);
47191.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
47201.1Skamil
47211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47231.1Skamil
47241.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
47251.1Skamil
47261.1Skamil		if (child2 == 0)
47271.1Skamil			_exit(exitval2);
47281.1Skamil
47291.1Skamil		FORKEE_REQUIRE_SUCCESS
47301.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
47311.1Skamil
47321.1Skamil		forkee_status_exited(status, exitval2);
47331.1Skamil
47341.13Schristos		DPRINTF("Before exiting of the child process\n");
47351.1Skamil		_exit(exitval);
47361.1Skamil	}
47371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47381.1Skamil
47391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47411.1Skamil
47421.1Skamil	validate_status_stopped(status, sigval);
47431.1Skamil
47441.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
47451.1Skamil	    child);
47461.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
47471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
47481.1Skamil
47491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47501.1Skamil	    "without signal to be sent\n");
47511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47521.1Skamil
47531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47551.1Skamil
47561.1Skamil	validate_status_stopped(status, sigmasked);
47571.1Skamil
47581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
47591.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
47601.1Skamil
47611.1Skamil	child2 = state.pe_other_pid;
47621.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
47631.1Skamil
47641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47651.1Skamil	    "without signal to be sent\n");
47661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47671.1Skamil
47681.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
47691.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
47701.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47711.1Skamil
47721.1Skamil	validate_status_stopped(status, SIGCHLD);
47731.1Skamil
47741.57Skamil	DPRINTF("Before resuming the child process where it left off and "
47751.1Skamil	    "without signal to be sent\n");
47761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47771.1Skamil
47781.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
47791.1Skamil	    TWAIT_FNAME);
47801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47811.1Skamil
47821.1Skamil	validate_status_exited(status, exitval);
47831.1Skamil
47841.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
47851.57Skamil	    TWAIT_FNAME);
47861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47871.1Skamil}
47881.1Skamil
47891.1SkamilATF_TC(signal9);
47901.1SkamilATF_TC_HEAD(signal9, tc)
47911.1Skamil{
47921.1Skamil	atf_tc_set_md_var(tc, "descr",
47931.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
47941.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
47951.1Skamil}
47961.1Skamil
47971.1SkamilATF_TC_BODY(signal9, tc)
47981.1Skamil{
47991.1Skamil	const int exitval = 5;
48001.1Skamil	const int sigval = SIGSTOP;
48011.1Skamil	const int sigmasked = SIGTRAP;
48021.1Skamil	pid_t child, wpid;
48031.1Skamil#if defined(TWAIT_HAVE_STATUS)
48041.1Skamil	int status;
48051.1Skamil#endif
48061.1Skamil	sigset_t intmask;
48071.1Skamil	ptrace_state_t state;
48081.1Skamil	const int slen = sizeof(state);
48091.1Skamil	ptrace_event_t event;
48101.1Skamil	const int elen = sizeof(event);
48111.1Skamil	ucontext_t uc;
48121.1Skamil	lwpid_t lid;
48131.1Skamil	static const size_t ssize = 16*1024;
48141.1Skamil	void *stack;
48151.1Skamil
48161.14Schristos	atf_tc_expect_fail("PR kern/51918");
48171.14Schristos
48181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48201.1Skamil	if (child == 0) {
48211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48231.1Skamil
48241.1Skamil		sigemptyset(&intmask);
48251.1Skamil		sigaddset(&intmask, sigmasked);
48261.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
48271.1Skamil
48281.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48291.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48301.1Skamil
48311.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
48321.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
48331.1Skamil
48341.13Schristos		DPRINTF("Before making context for new lwp in child\n");
48351.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
48361.1Skamil
48371.13Schristos		DPRINTF("Before creating new in child\n");
48381.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
48391.1Skamil
48401.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
48411.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
48421.1Skamil
48431.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
48441.1Skamil		    "are the same\n", lid, the_lwp_id);
48451.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
48461.1Skamil
48471.13Schristos		DPRINTF("Before exiting of the child process\n");
48481.1Skamil		_exit(exitval);
48491.1Skamil	}
48501.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48511.1Skamil
48521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48541.1Skamil
48551.1Skamil	validate_status_stopped(status, sigval);
48561.1Skamil
48571.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
48581.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
48591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
48601.1Skamil
48611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48621.1Skamil	    "without signal to be sent\n");
48631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48641.1Skamil
48651.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48661.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
48671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48681.1Skamil
48691.1Skamil	validate_status_stopped(status, sigmasked);
48701.1Skamil
48711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
48721.1Skamil
48731.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
48741.1Skamil
48751.1Skamil	lid = state.pe_lwp;
48761.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
48771.1Skamil
48781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48791.1Skamil	    "without signal to be sent\n");
48801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48811.1Skamil
48821.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48831.1Skamil	    TWAIT_FNAME);
48841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48851.1Skamil
48861.1Skamil	validate_status_exited(status, exitval);
48871.1Skamil
48881.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48891.1Skamil	    TWAIT_FNAME);
48901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48911.1Skamil}
48921.1Skamil
48931.1SkamilATF_TC(signal10);
48941.1SkamilATF_TC_HEAD(signal10, tc)
48951.1Skamil{
48961.1Skamil	atf_tc_set_md_var(tc, "descr",
48971.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
48981.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
48991.1Skamil}
49001.1Skamil
49011.1SkamilATF_TC_BODY(signal10, tc)
49021.1Skamil{
49031.1Skamil	const int exitval = 5;
49041.1Skamil	const int sigval = SIGSTOP;
49051.1Skamil	const int sigmasked = SIGTRAP;
49061.1Skamil	pid_t child, wpid;
49071.1Skamil#if defined(TWAIT_HAVE_STATUS)
49081.1Skamil	int status;
49091.1Skamil#endif
49101.1Skamil	sigset_t intmask;
49111.1Skamil	ptrace_state_t state;
49121.1Skamil	const int slen = sizeof(state);
49131.1Skamil	ptrace_event_t event;
49141.1Skamil	const int elen = sizeof(event);
49151.1Skamil	ucontext_t uc;
49161.1Skamil	lwpid_t lid;
49171.1Skamil	static const size_t ssize = 16*1024;
49181.1Skamil	void *stack;
49191.1Skamil
49201.14Schristos	atf_tc_expect_fail("PR kern/51918");
49211.14Schristos
49221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49241.1Skamil	if (child == 0) {
49251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49271.1Skamil
49281.1Skamil		sigemptyset(&intmask);
49291.1Skamil		sigaddset(&intmask, sigmasked);
49301.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
49311.1Skamil
49321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49341.1Skamil
49351.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
49361.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
49371.1Skamil
49381.13Schristos		DPRINTF("Before making context for new lwp in child\n");
49391.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
49401.1Skamil
49411.13Schristos		DPRINTF("Before creating new in child\n");
49421.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
49431.1Skamil
49441.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
49451.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
49461.1Skamil
49471.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
49481.1Skamil		    "are the same\n", lid, the_lwp_id);
49491.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
49501.1Skamil
49511.13Schristos		DPRINTF("Before exiting of the child process\n");
49521.1Skamil		_exit(exitval);
49531.1Skamil	}
49541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49551.1Skamil
49561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49581.1Skamil
49591.1Skamil	validate_status_stopped(status, sigval);
49601.1Skamil
49611.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
49621.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
49631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
49641.1Skamil
49651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49661.1Skamil	    "without signal to be sent\n");
49671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49681.1Skamil
49691.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49701.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
49711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49721.1Skamil
49731.1Skamil	validate_status_stopped(status, sigmasked);
49741.1Skamil
49751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
49761.1Skamil
49771.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
49781.1Skamil
49791.1Skamil	lid = state.pe_lwp;
49801.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
49811.1Skamil
49821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49831.1Skamil	    "without signal to be sent\n");
49841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49851.1Skamil
49861.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49871.1Skamil	    TWAIT_FNAME);
49881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49891.1Skamil
49901.1Skamil	validate_status_exited(status, exitval);
49911.1Skamil
49921.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49931.1Skamil	    TWAIT_FNAME);
49941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49951.1Skamil}
49961.1Skamil
49971.1Skamilstatic void
49981.1Skamillwp_main_stop(void *arg)
49991.1Skamil{
50001.1Skamil	the_lwp_id = _lwp_self();
50011.1Skamil
50021.1Skamil	raise(SIGTRAP);
50031.1Skamil
50041.1Skamil	_lwp_exit();
50051.1Skamil}
50061.1Skamil
50071.1SkamilATF_TC(suspend1);
50081.1SkamilATF_TC_HEAD(suspend1, tc)
50091.1Skamil{
50101.1Skamil	atf_tc_set_md_var(tc, "descr",
50111.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
50121.1Skamil	    "resumed by a tracee");
50131.1Skamil}
50141.1Skamil
50151.1SkamilATF_TC_BODY(suspend1, tc)
50161.1Skamil{
50171.1Skamil	const int exitval = 5;
50181.1Skamil	const int sigval = SIGSTOP;
50191.1Skamil	pid_t child, wpid;
50201.1Skamil#if defined(TWAIT_HAVE_STATUS)
50211.1Skamil	int status;
50221.1Skamil#endif
50231.1Skamil	ucontext_t uc;
50241.1Skamil	lwpid_t lid;
50251.1Skamil	static const size_t ssize = 16*1024;
50261.1Skamil	void *stack;
50271.1Skamil	struct ptrace_lwpinfo pl;
50281.1Skamil	struct ptrace_siginfo psi;
50291.1Skamil	volatile int go = 0;
50301.1Skamil
50311.17Skamil	// Feature pending for refactoring
50321.17Skamil	atf_tc_expect_fail("PR kern/51995");
50331.17Skamil
50341.16Skamil	// Hangs with qemu
50351.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
50361.16Skamil
50371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50391.1Skamil	if (child == 0) {
50401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50421.1Skamil
50431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50451.1Skamil
50461.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
50471.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
50481.1Skamil
50491.13Schristos		DPRINTF("Before making context for new lwp in child\n");
50501.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
50511.1Skamil
50521.13Schristos		DPRINTF("Before creating new in child\n");
50531.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
50541.1Skamil
50551.1Skamil		while (go == 0)
50561.1Skamil			continue;
50571.1Skamil
50581.1Skamil		raise(SIGINT);
50591.1Skamil
50601.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
50611.1Skamil
50621.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
50631.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
50641.1Skamil
50651.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
50661.1Skamil		    "are the same\n", lid, the_lwp_id);
50671.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
50681.1Skamil
50691.13Schristos		DPRINTF("Before exiting of the child process\n");
50701.1Skamil		_exit(exitval);
50711.1Skamil	}
50721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50731.1Skamil
50741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50761.1Skamil
50771.1Skamil	validate_status_stopped(status, sigval);
50781.1Skamil
50791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50801.1Skamil	    "without signal to be sent\n");
50811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50821.1Skamil
50831.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50841.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
50851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50861.1Skamil
50871.1Skamil	validate_status_stopped(status, SIGTRAP);
50881.1Skamil
50891.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
50901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
50911.1Skamil
50921.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
50931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
50941.1Skamil
50951.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
50961.1Skamil	    child, getpid());
50971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
50981.1Skamil
50991.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51001.1Skamil	    "without signal to be sent\n");
51011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51021.1Skamil
51031.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
51041.1Skamil	    "SIGINT\n", TWAIT_FNAME);
51051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51061.1Skamil
51071.1Skamil	validate_status_stopped(status, SIGINT);
51081.1Skamil
51091.1Skamil	pl.pl_lwpid = 0;
51101.1Skamil
51111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
51121.1Skamil	while (pl.pl_lwpid != 0) {
51131.1Skamil
51141.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
51151.1Skamil		switch (pl.pl_lwpid) {
51161.1Skamil		case 1:
51171.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
51181.1Skamil			break;
51191.1Skamil		case 2:
51201.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
51211.1Skamil			break;
51221.1Skamil		}
51231.1Skamil	}
51241.1Skamil
51251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51261.1Skamil	    "without signal to be sent\n");
51271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51281.1Skamil
51291.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51301.1Skamil	    TWAIT_FNAME);
51311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51321.1Skamil
51331.1Skamil	validate_status_exited(status, exitval);
51341.1Skamil
51351.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51361.1Skamil	    TWAIT_FNAME);
51371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51381.1Skamil}
51391.1Skamil
51401.1SkamilATF_TC(suspend2);
51411.1SkamilATF_TC_HEAD(suspend2, tc)
51421.1Skamil{
51431.1Skamil	atf_tc_set_md_var(tc, "descr",
51441.1Skamil	    "Verify that the while the only thread within a process is "
51451.1Skamil	    "suspended, the whole process cannot be unstopped");
51461.1Skamil}
51471.1Skamil
51481.1SkamilATF_TC_BODY(suspend2, tc)
51491.1Skamil{
51501.1Skamil	const int exitval = 5;
51511.1Skamil	const int sigval = SIGSTOP;
51521.1Skamil	pid_t child, wpid;
51531.1Skamil#if defined(TWAIT_HAVE_STATUS)
51541.1Skamil	int status;
51551.1Skamil#endif
51561.1Skamil	struct ptrace_siginfo psi;
51571.1Skamil
51581.17Skamil	// Feature pending for refactoring
51591.17Skamil	atf_tc_expect_fail("PR kern/51995");
51601.17Skamil
51611.16Skamil	// Hangs with qemu
51621.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
51631.16Skamil
51641.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51651.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51661.1Skamil	if (child == 0) {
51671.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51681.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51691.1Skamil
51701.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51711.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51721.1Skamil
51731.13Schristos		DPRINTF("Before exiting of the child process\n");
51741.1Skamil		_exit(exitval);
51751.1Skamil	}
51761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51771.1Skamil
51781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51801.1Skamil
51811.1Skamil	validate_status_stopped(status, sigval);
51821.1Skamil
51831.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
51841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
51851.1Skamil
51861.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
51871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
51881.1Skamil
51891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51901.1Skamil	    "without signal to be sent\n");
51911.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
51921.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
51931.1Skamil
51941.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
51951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
51961.1Skamil
51971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51981.1Skamil	    "without signal to be sent\n");
51991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52001.1Skamil
52011.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52021.1Skamil	    TWAIT_FNAME);
52031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52041.1Skamil
52051.1Skamil	validate_status_exited(status, exitval);
52061.1Skamil
52071.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52081.1Skamil	    TWAIT_FNAME);
52091.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52101.1Skamil}
52111.1Skamil
52121.1SkamilATF_TC(resume1);
52131.1SkamilATF_TC_HEAD(resume1, tc)
52141.1Skamil{
52151.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
52161.1Skamil	atf_tc_set_md_var(tc, "descr",
52171.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
52181.1Skamil	    "resumed by the debugger");
52191.1Skamil}
52201.1Skamil
52211.1SkamilATF_TC_BODY(resume1, tc)
52221.1Skamil{
52231.1Skamil	struct msg_fds fds;
52241.1Skamil	const int exitval = 5;
52251.1Skamil	const int sigval = SIGSTOP;
52261.1Skamil	pid_t child, wpid;
52271.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
52281.1Skamil#if defined(TWAIT_HAVE_STATUS)
52291.1Skamil	int status;
52301.1Skamil#endif
52311.1Skamil	ucontext_t uc;
52321.1Skamil	lwpid_t lid;
52331.1Skamil	static const size_t ssize = 16*1024;
52341.1Skamil	void *stack;
52351.1Skamil	struct ptrace_lwpinfo pl;
52361.1Skamil	struct ptrace_siginfo psi;
52371.1Skamil
52381.17Skamil	// Feature pending for refactoring
52391.17Skamil	atf_tc_expect_fail("PR kern/51995");
52401.17Skamil
52411.15Schristos	// Hangs with qemu
52421.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
52431.1Skamil
52441.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
52451.1Skamil
52461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52481.1Skamil	if (child == 0) {
52491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52511.1Skamil
52521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52541.1Skamil
52551.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
52561.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
52571.1Skamil
52581.13Schristos		DPRINTF("Before making context for new lwp in child\n");
52591.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
52601.1Skamil
52611.13Schristos		DPRINTF("Before creating new in child\n");
52621.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
52631.1Skamil
52641.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
52651.1Skamil
52661.1Skamil		raise(SIGINT);
52671.1Skamil
52681.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
52691.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
52701.1Skamil
52711.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
52721.1Skamil		    "are the same\n", lid, the_lwp_id);
52731.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
52741.1Skamil
52751.13Schristos		DPRINTF("Before exiting of the child process\n");
52761.1Skamil		_exit(exitval);
52771.1Skamil	}
52781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52791.1Skamil
52801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52821.1Skamil
52831.1Skamil	validate_status_stopped(status, sigval);
52841.1Skamil
52851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52861.1Skamil	    "without signal to be sent\n");
52871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52881.1Skamil
52891.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52901.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
52911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52921.1Skamil
52931.1Skamil	validate_status_stopped(status, SIGTRAP);
52941.1Skamil
52951.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
52961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
52971.1Skamil
52981.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
52991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
53001.1Skamil
53011.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
53021.1Skamil
53031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53041.1Skamil	    "without signal to be sent\n");
53051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53061.1Skamil
53071.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
53081.1Skamil	    "SIGINT\n", TWAIT_FNAME);
53091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53101.1Skamil
53111.1Skamil	validate_status_stopped(status, SIGINT);
53121.1Skamil
53131.1Skamil	pl.pl_lwpid = 0;
53141.1Skamil
53151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
53161.1Skamil	while (pl.pl_lwpid != 0) {
53171.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
53181.1Skamil		switch (pl.pl_lwpid) {
53191.1Skamil		case 1:
53201.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
53211.1Skamil			break;
53221.1Skamil		case 2:
53231.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
53241.1Skamil			break;
53251.1Skamil		}
53261.1Skamil	}
53271.1Skamil
53281.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
53291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
53301.1Skamil
53311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53321.1Skamil	    "without signal to be sent\n");
53331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53341.1Skamil
53351.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53361.1Skamil	    TWAIT_FNAME);
53371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53381.1Skamil
53391.1Skamil	validate_status_exited(status, exitval);
53401.1Skamil
53411.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53421.1Skamil	    TWAIT_FNAME);
53431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53441.1Skamil
53451.1Skamil	msg_close(&fds);
53461.1Skamil
53471.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
53481.1Skamil	sleep(10);
53491.1Skamil}
53501.1Skamil
53511.1SkamilATF_TC(syscall1);
53521.1SkamilATF_TC_HEAD(syscall1, tc)
53531.1Skamil{
53541.1Skamil	atf_tc_set_md_var(tc, "descr",
53551.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
53561.1Skamil}
53571.1Skamil
53581.1SkamilATF_TC_BODY(syscall1, tc)
53591.1Skamil{
53601.1Skamil	const int exitval = 5;
53611.1Skamil	const int sigval = SIGSTOP;
53621.1Skamil	pid_t child, wpid;
53631.1Skamil#if defined(TWAIT_HAVE_STATUS)
53641.1Skamil	int status;
53651.1Skamil#endif
53661.1Skamil	struct ptrace_siginfo info;
53671.1Skamil	memset(&info, 0, sizeof(info));
53681.1Skamil
53691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53711.1Skamil	if (child == 0) {
53721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53741.1Skamil
53751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53771.1Skamil
53781.1Skamil		syscall(SYS_getpid);
53791.1Skamil
53801.13Schristos		DPRINTF("Before exiting of the child process\n");
53811.1Skamil		_exit(exitval);
53821.1Skamil	}
53831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53841.1Skamil
53851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53871.1Skamil
53881.1Skamil	validate_status_stopped(status, sigval);
53891.1Skamil
53901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53911.1Skamil	    "without signal to be sent\n");
53921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
53931.1Skamil
53941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53961.1Skamil
53971.1Skamil	validate_status_stopped(status, SIGTRAP);
53981.1Skamil
53991.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
54001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
54011.1Skamil
54021.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
54031.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
54041.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
54051.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
54061.1Skamil
54071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54081.1Skamil	    "without signal to be sent\n");
54091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
54101.1Skamil
54111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54131.1Skamil
54141.1Skamil	validate_status_stopped(status, SIGTRAP);
54151.1Skamil
54161.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
54171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
54181.1Skamil
54191.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
54201.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
54211.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
54221.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
54231.1Skamil
54241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54251.1Skamil	    "without signal to be sent\n");
54261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54271.1Skamil
54281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54301.1Skamil
54311.1Skamil	validate_status_exited(status, exitval);
54321.1Skamil
54331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54351.1Skamil}
54361.1Skamil
54371.1SkamilATF_TC(syscallemu1);
54381.1SkamilATF_TC_HEAD(syscallemu1, tc)
54391.1Skamil{
54401.1Skamil	atf_tc_set_md_var(tc, "descr",
54411.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
54421.1Skamil}
54431.1Skamil
54441.1SkamilATF_TC_BODY(syscallemu1, tc)
54451.1Skamil{
54461.1Skamil	const int exitval = 5;
54471.1Skamil	const int sigval = SIGSTOP;
54481.1Skamil	pid_t child, wpid;
54491.1Skamil#if defined(TWAIT_HAVE_STATUS)
54501.1Skamil	int status;
54511.1Skamil#endif
54521.1Skamil
54531.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
54541.6Skamil	/* syscallemu does not work on sparc (32-bit) */
54551.6Skamil	atf_tc_expect_fail("PR kern/52166");
54561.6Skamil#endif
54571.6Skamil
54581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54601.1Skamil	if (child == 0) {
54611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54631.1Skamil
54641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54661.1Skamil
54671.1Skamil		syscall(SYS_exit, 100);
54681.1Skamil
54691.13Schristos		DPRINTF("Before exiting of the child process\n");
54701.1Skamil		_exit(exitval);
54711.1Skamil	}
54721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54731.1Skamil
54741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54761.1Skamil
54771.1Skamil	validate_status_stopped(status, sigval);
54781.1Skamil
54791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54801.1Skamil	    "without signal to be sent\n");
54811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
54821.1Skamil
54831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54851.1Skamil
54861.1Skamil	validate_status_stopped(status, SIGTRAP);
54871.1Skamil
54881.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
54891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
54901.1Skamil
54911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54921.1Skamil	    "without signal to be sent\n");
54931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
54941.1Skamil
54951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54971.1Skamil
54981.1Skamil	validate_status_stopped(status, SIGTRAP);
54991.1Skamil
55001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55011.1Skamil	    "without signal to be sent\n");
55021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55031.1Skamil
55041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55061.1Skamil
55071.1Skamil	validate_status_exited(status, exitval);
55081.1Skamil
55091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55111.1Skamil}
55121.1Skamil
55131.1Skamil#include "t_ptrace_amd64_wait.h"
55141.1Skamil#include "t_ptrace_i386_wait.h"
55151.1Skamil#include "t_ptrace_x86_wait.h"
55161.1Skamil
55171.1SkamilATF_TP_ADD_TCS(tp)
55181.1Skamil{
55191.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
55201.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
55211.33Skamil
55221.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
55231.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
55241.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
55251.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
55261.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
55271.33Skamil
55281.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
55291.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
55301.59Skamil//	ATF_TP_ADD_TC(tp, traceme_crash_ill);
55311.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
55321.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
55331.59Skamil
55341.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
55351.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
55361.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
55371.50Skamil
55381.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
55391.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
55401.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
55411.50Skamil
55421.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
55431.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
55441.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
55451.50Skamil
55461.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
55471.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
55481.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
55491.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
55501.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
55511.1Skamil
55521.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
55531.37Skamil
55541.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
55551.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
55561.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
55571.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
55581.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
55591.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
55601.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
55611.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
55621.40Skamil
55631.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
55641.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
55651.52Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
55661.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
55671.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
55681.41Skamil
55691.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
55701.43Skamil
55711.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
55721.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
55731.59Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
55741.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
55751.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
55761.59Skamil
55771.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
55781.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
55791.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_terminaton_before_the_parent);
55801.51Skamil
55811.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
55821.51Skamil
55831.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
55841.51Skamil
55851.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
55861.51Skamil		tracee_sees_its_original_parent_getppid);
55871.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
55881.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
55891.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
55901.51Skamil		tracee_sees_its_original_parent_procfs_status);
55911.1Skamil
55921.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
55931.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
55941.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
55951.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
55961.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
55971.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
55981.1Skamil
55991.31Skamil	ATF_TP_ADD_TC(tp, fork1);
56001.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
56011.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
56021.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
56031.31Skamil	ATF_TP_ADD_TC(tp, fork5);
56041.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
56051.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
56061.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
56071.31Skamil
56081.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
56091.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
56101.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
56111.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
56121.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
56131.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
56141.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
56151.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
56161.1Skamil
56171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
56181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
56191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
56201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
56211.54Skamil
56221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
56231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
56241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
56251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
56261.54Skamil
56271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
56281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
56291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
56301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
56311.54Skamil
56321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
56331.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
56341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
56351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
56361.54Skamil
56371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
56381.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
56391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
56401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
56411.54Skamil
56421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
56431.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
56441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
56451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
56461.54Skamil
56471.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
56481.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
56491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
56501.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
56511.54Skamil
56521.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
56531.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
56541.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
56551.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
56561.54Skamil
56571.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
56581.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
56591.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
56601.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
56611.54Skamil
56621.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
56631.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
56641.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
56651.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
56661.1Skamil
56671.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
56681.1Skamil
56691.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
56701.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
56711.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
56721.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
56731.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
56741.1Skamil
56751.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
56761.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
56771.1Skamil
56781.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
56791.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
56801.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
56811.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
56821.1Skamil
56831.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
56841.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
56851.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
56861.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
56871.2Skamil
56881.1Skamil	ATF_TP_ADD_TC(tp, kill1);
56891.1Skamil	ATF_TP_ADD_TC(tp, kill2);
56901.1Skamil
56911.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
56921.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
56931.1Skamil
56941.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
56951.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
56961.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
56971.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
56981.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
56991.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
57001.1Skamil
57011.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
57021.1Skamil
57031.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
57041.1Skamil
57051.1Skamil	ATF_TP_ADD_TC(tp, signal1);
57061.1Skamil	ATF_TP_ADD_TC(tp, signal2);
57071.1Skamil	ATF_TP_ADD_TC(tp, signal3);
57081.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
57091.1Skamil	ATF_TP_ADD_TC(tp, signal5);
57101.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
57111.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
57121.1Skamil	ATF_TP_ADD_TC(tp, signal8);
57131.1Skamil	ATF_TP_ADD_TC(tp, signal9);
57141.1Skamil	ATF_TP_ADD_TC(tp, signal10);
57151.1Skamil
57161.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
57171.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
57181.1Skamil
57191.1Skamil	ATF_TP_ADD_TC(tp, resume1);
57201.1Skamil
57211.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
57221.1Skamil
57231.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
57241.1Skamil
57251.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
57261.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
57271.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
57281.1Skamil
57291.1Skamil	return atf_no_error();
57301.1Skamil}
5731