t_ptrace_wait.c revision 1.57
11.57Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.57 2018/05/28 11:15:48 kamil 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.57Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.57 2018/05/28 11:15:48 kamil 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.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
1811.1Skamil{
1821.1Skamil	const int exitval = 5;
1831.34Skamil	const int sigval = SIGSTOP;
1841.1Skamil	pid_t child, wpid;
1851.1Skamil	struct sigaction sa;
1861.1Skamil#if defined(TWAIT_HAVE_STATUS)
1871.1Skamil	int status;
1881.1Skamil#endif
1891.1Skamil
1901.45Skamil	struct ptrace_siginfo info;
1911.45Skamil	memset(&info, 0, sizeof(info));
1921.45Skamil
1931.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1941.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1951.1Skamil	if (child == 0) {
1961.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1971.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1981.1Skamil
1991.34Skamil		sa.sa_handler = sah;
2001.1Skamil		sa.sa_flags = SA_SIGINFO;
2011.1Skamil		sigemptyset(&sa.sa_mask);
2021.1Skamil
2031.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
2041.1Skamil
2051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2071.1Skamil
2081.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
2091.1Skamil
2101.13Schristos		DPRINTF("Before exiting of the child process\n");
2111.1Skamil		_exit(exitval);
2121.1Skamil	}
2131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2141.1Skamil
2151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2171.1Skamil
2181.1Skamil	validate_status_stopped(status, sigval);
2191.1Skamil
2201.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
2211.45Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
2221.45Skamil	                != -1);
2231.45Skamil
2241.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2251.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2261.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2271.45Skamil	    info.psi_siginfo.si_errno);
2281.45Skamil
2291.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
2301.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
2311.45Skamil
2321.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2331.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2351.1Skamil
2361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2381.1Skamil
2391.1Skamil	validate_status_exited(status, exitval);
2401.1Skamil
2411.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2431.1Skamil}
2441.1Skamil
2451.50Skamil#define TRACEME_SENDSIGNAL_HANDLE(test, sig)					\
2461.34SkamilATF_TC(test);									\
2471.34SkamilATF_TC_HEAD(test, tc)								\
2481.34Skamil{										\
2491.34Skamil	atf_tc_set_md_var(tc, "descr",						\
2501.34Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
2511.34Skamil	    "handled correctly and caught by a signal handler");		\
2521.34Skamil}										\
2531.34Skamil										\
2541.34Skamilstatic int test##_caught = 0;							\
2551.34Skamil										\
2561.34Skamilstatic void									\
2571.34Skamiltest##_sighandler(int arg)							\
2581.34Skamil{										\
2591.34Skamil	FORKEE_ASSERT_EQ(arg, sig);						\
2601.34Skamil										\
2611.34Skamil	++ test##_caught;							\
2621.34Skamil}										\
2631.34Skamil										\
2641.34SkamilATF_TC_BODY(test, tc)								\
2651.34Skamil{										\
2661.34Skamil										\
2671.50Skamil	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught);	\
2681.34Skamil}
2691.34Skamil
2701.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
2711.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
2721.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
2731.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
2741.34Skamil
2751.34Skamil/// ----------------------------------------------------------------------------
2761.34Skamil
2771.35Skamilstatic void
2781.50Skamiltraceme_sendsignal_masked(int sigsent)
2791.50Skamil{
2801.50Skamil	const int exitval = 5;
2811.50Skamil	const int sigval = SIGSTOP;
2821.50Skamil	pid_t child, wpid;
2831.50Skamil	sigset_t set;
2841.50Skamil#if defined(TWAIT_HAVE_STATUS)
2851.50Skamil	int status;
2861.50Skamil#endif
2871.50Skamil
2881.50Skamil	struct ptrace_siginfo info;
2891.50Skamil	memset(&info, 0, sizeof(info));
2901.50Skamil
2911.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2921.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2931.50Skamil	if (child == 0) {
2941.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2951.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2961.50Skamil
2971.50Skamil		sigemptyset(&set);
2981.50Skamil		sigaddset(&set, sigsent);
2991.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
3001.50Skamil
3011.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3021.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3031.50Skamil
3041.50Skamil		_exit(exitval);
3051.50Skamil	}
3061.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3071.50Skamil
3081.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3091.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3101.50Skamil
3111.50Skamil	validate_status_stopped(status, sigval);
3121.50Skamil
3131.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3141.50Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
3151.50Skamil	                != -1);
3161.50Skamil
3171.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3181.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3191.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3201.50Skamil	    info.psi_siginfo.si_errno);
3211.50Skamil
3221.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3231.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3241.50Skamil
3251.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
3261.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3271.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3281.50Skamil
3291.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3301.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3311.50Skamil
3321.50Skamil	validate_status_exited(status, exitval);
3331.50Skamil
3341.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3351.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3361.50Skamil}
3371.50Skamil
3381.50Skamil#define TRACEME_SENDSIGNAL_MASKED(test, sig)					\
3391.50SkamilATF_TC(test);									\
3401.50SkamilATF_TC_HEAD(test, tc)								\
3411.50Skamil{										\
3421.50Skamil	atf_tc_set_md_var(tc, "descr",						\
3431.50Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
3441.50Skamil	    "handled correctly and the signal is masked by SIG_BLOCK");		\
3451.50Skamil}										\
3461.50Skamil										\
3471.50SkamilATF_TC_BODY(test, tc)								\
3481.50Skamil{										\
3491.50Skamil										\
3501.50Skamil	traceme_sendsignal_masked(sig);						\
3511.50Skamil}
3521.50Skamil
3531.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
3541.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
3551.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
3561.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
3571.50Skamil
3581.50Skamil/// ----------------------------------------------------------------------------
3591.50Skamil
3601.50Skamilstatic void
3611.50Skamiltraceme_sendsignal_ignored(int sigsent)
3621.50Skamil{
3631.50Skamil	const int exitval = 5;
3641.50Skamil	const int sigval = SIGSTOP;
3651.50Skamil	pid_t child, wpid;
3661.50Skamil	struct sigaction sa;
3671.50Skamil#if defined(TWAIT_HAVE_STATUS)
3681.50Skamil	int status;
3691.50Skamil#endif
3701.50Skamil
3711.50Skamil	struct ptrace_siginfo info;
3721.50Skamil	memset(&info, 0, sizeof(info));
3731.50Skamil
3741.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3751.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
3761.50Skamil	if (child == 0) {
3771.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3781.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3791.50Skamil
3801.50Skamil		memset(&sa, 0, sizeof(sa));
3811.50Skamil		sa.sa_handler = SIG_IGN;
3821.50Skamil		sigemptyset(&sa.sa_mask);
3831.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
3841.50Skamil
3851.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3861.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3871.50Skamil
3881.50Skamil		_exit(exitval);
3891.50Skamil	}
3901.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3911.50Skamil
3921.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3931.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3941.50Skamil
3951.50Skamil	validate_status_stopped(status, sigval);
3961.50Skamil
3971.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3981.50Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
3991.50Skamil	                != -1);
4001.50Skamil
4011.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4021.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4031.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4041.50Skamil	    info.psi_siginfo.si_errno);
4051.50Skamil
4061.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4071.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4081.50Skamil
4091.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
4101.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4111.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4121.50Skamil
4131.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4141.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4151.50Skamil
4161.50Skamil	validate_status_exited(status, exitval);
4171.50Skamil
4181.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4191.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4201.50Skamil}
4211.50Skamil
4221.50Skamil#define TRACEME_SENDSIGNAL_IGNORED(test, sig)					\
4231.50SkamilATF_TC(test);									\
4241.50SkamilATF_TC_HEAD(test, tc)								\
4251.50Skamil{										\
4261.50Skamil	atf_tc_set_md_var(tc, "descr",						\
4271.50Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
4281.50Skamil	    "handled correctly and the signal is masked by SIG_IGN");		\
4291.50Skamil}										\
4301.50Skamil										\
4311.50SkamilATF_TC_BODY(test, tc)								\
4321.50Skamil{										\
4331.50Skamil										\
4341.50Skamil	traceme_sendsignal_ignored(sig);					\
4351.50Skamil}
4361.50Skamil
4371.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
4381.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort trap */
4391.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
4401.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued? */
4411.50Skamil
4421.50Skamil/// ----------------------------------------------------------------------------
4431.50Skamil
4441.50Skamilstatic void
4451.50Skamiltraceme_sendsignal_simple(int sigsent)
4461.1Skamil{
4471.35Skamil	const int sigval = SIGSTOP;
4481.35Skamil	int exitval = 0;
4491.1Skamil	pid_t child, wpid;
4501.1Skamil#if defined(TWAIT_HAVE_STATUS)
4511.1Skamil	int status;
4521.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
4531.1Skamil#endif
4541.1Skamil
4551.45Skamil	struct ptrace_siginfo info;
4561.45Skamil	memset(&info, 0, sizeof(info));
4571.45Skamil
4581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
4591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
4601.1Skamil	if (child == 0) {
4611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4631.1Skamil
4641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4661.1Skamil
4671.35Skamil		switch (sigsent) {
4681.35Skamil		case SIGCONT:
4691.48Skamil		case SIGSTOP:
4701.35Skamil			_exit(exitval);
4711.35Skamil		default:
4721.35Skamil			/* NOTREACHED */
4731.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4741.35Skamil		}
4751.1Skamil	}
4761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4771.1Skamil
4781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4801.1Skamil
4811.1Skamil	validate_status_stopped(status, sigval);
4821.1Skamil
4831.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4841.45Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
4851.45Skamil	                != -1);
4861.45Skamil
4871.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4881.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4891.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4901.45Skamil	    info.psi_siginfo.si_errno);
4911.45Skamil
4921.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4931.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4941.45Skamil
4951.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
4961.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4981.1Skamil
4991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5011.1Skamil
5021.35Skamil	switch (sigsent) {
5031.48Skamil	case SIGSTOP:
5041.48Skamil		validate_status_stopped(status, sigsent);
5051.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
5061.48Skamil		        "child\n");
5071.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
5081.48Skamil		                       sizeof(info)) != -1);
5091.48Skamil
5101.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5111.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
5121.48Skamil		        "si_errno=%#x\n",
5131.48Skamil			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5141.48Skamil		        info.psi_siginfo.si_errno);
5151.48Skamil
5161.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5171.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5181.48Skamil
5191.48Skamil		DPRINTF("Before resuming the child process where it left off "
5201.48Skamil		        "and with signal %s to be sent\n", strsignal(sigsent));
5211.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5221.48Skamil
5231.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5241.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
5251.48Skamil		                      child);
5261.48Skamil		/* FALLTHROUGH */
5271.35Skamil	case SIGCONT:
5281.35Skamil		validate_status_exited(status, exitval);
5291.35Skamil		break;
5301.35Skamil	default:
5311.35Skamil		validate_status_signaled(status, sigsent, expect_core);
5321.35Skamil		break;
5331.35Skamil	}
5341.1Skamil
5351.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5371.1Skamil}
5381.1Skamil
5391.50Skamil#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)					\
5401.35SkamilATF_TC(test);									\
5411.35SkamilATF_TC_HEAD(test, tc)								\
5421.35Skamil{										\
5431.35Skamil	atf_tc_set_md_var(tc, "descr",						\
5441.35Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
5451.35Skamil	    "handled correctly in a child without a signal handler");		\
5461.35Skamil}										\
5471.35Skamil										\
5481.35SkamilATF_TC_BODY(test, tc)								\
5491.35Skamil{										\
5501.35Skamil										\
5511.50Skamil	traceme_sendsignal_simple(sig);						\
5521.35Skamil}
5531.35Skamil
5541.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable */
5551.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable */
5561.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
5571.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
5581.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
5591.35Skamil
5601.35Skamil/// ----------------------------------------------------------------------------
5611.35Skamil
5621.37SkamilATF_TC(traceme_pid1_parent);
5631.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
5641.37Skamil{
5651.37Skamil	atf_tc_set_md_var(tc, "descr",
5661.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
5671.37Skamil}
5681.37Skamil
5691.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
5701.37Skamil{
5711.37Skamil	struct msg_fds parent_child;
5721.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
5731.37Skamil	pid_t child1, child2, wpid;
5741.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5751.37Skamil#if defined(TWAIT_HAVE_STATUS)
5761.37Skamil	int status;
5771.37Skamil#endif
5781.37Skamil
5791.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
5801.37Skamil
5811.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
5821.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
5831.37Skamil	if (child1 == 0) {
5841.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
5851.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
5861.37Skamil		if (child2 != 0) {
5871.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
5881.37Skamil			        getpid(), child2);
5891.37Skamil			_exit(exitval_child1);
5901.37Skamil		}
5911.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
5921.37Skamil
5931.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
5941.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
5951.37Skamil
5961.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5971.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
5981.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
5991.37Skamil
6001.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
6011.37Skamil
6021.37Skamil		_exit(exitval_child2);
6031.37Skamil	}
6041.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
6051.37Skamil
6061.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6071.37Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child1, &status, WEXITED),
6081.37Skamil	                      child1);
6091.37Skamil
6101.37Skamil	validate_status_exited(status, exitval_child1);
6111.37Skamil
6121.37Skamil	DPRINTF("Notify that child1 is dead\n");
6131.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
6141.37Skamil
6151.37Skamil	DPRINTF("Wait for exiting of child2\n");
6161.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
6171.37Skamil}
6181.37Skamil
6191.37Skamil/// ----------------------------------------------------------------------------
6201.37Skamil
6211.40Skamilstatic void
6221.40Skamiltraceme_vfork_raise(int sigval)
6231.40Skamil{
6241.46Skamil	const int exitval = 5, exitval_watcher = 10;
6251.46Skamil	pid_t child, parent, watcher, wpid;
6261.46Skamil	int rv;
6271.40Skamil#if defined(TWAIT_HAVE_STATUS)
6281.40Skamil	int status;
6291.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
6301.40Skamil#endif
6311.40Skamil
6321.46Skamil	/*
6331.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
6341.46Skamil	 * the SIGKILL signal to it.
6351.46Skamil	 *
6361.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
6371.46Skamil	 * simpler to reparent this process to initproc and forget about it.
6381.46Skamil	 */
6391.46Skamil	if (sigval == SIGSTOP) {
6401.46Skamil		parent = getpid();
6411.46Skamil
6421.46Skamil		watcher = fork();
6431.46Skamil		ATF_REQUIRE(watcher != 1);
6441.46Skamil		if (watcher == 0) {
6451.46Skamil			/* Double fork(2) trick to reparent to initproc */
6461.46Skamil			watcher = fork();
6471.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
6481.46Skamil			if (watcher != 0)
6491.46Skamil				_exit(exitval_watcher);
6501.46Skamil
6511.46Skamil			child = await_stopped_child(parent);
6521.46Skamil
6531.46Skamil			errno = 0;
6541.46Skamil			rv = kill(child, SIGKILL);
6551.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
6561.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
6571.46Skamil
6581.46Skamil			/* This exit value will be collected by initproc */
6591.46Skamil			_exit(0);
6601.46Skamil		}
6611.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6621.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
6631.46Skamil		                      watcher);
6641.46Skamil
6651.46Skamil		validate_status_exited(status, exitval_watcher);
6661.46Skamil
6671.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6681.46Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(watcher,
6691.46Skamil		                                                   &status, 0));
6701.46Skamil	}
6711.46Skamil
6721.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
6731.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
6741.40Skamil	if (child == 0) {
6751.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
6761.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
6771.40Skamil
6781.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
6791.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
6801.40Skamil
6811.40Skamil		switch (sigval) {
6821.46Skamil		case SIGSTOP:
6831.40Skamil		case SIGKILL:
6841.40Skamil		case SIGABRT:
6851.40Skamil		case SIGHUP:
6861.40Skamil			/* NOTREACHED */
6871.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
6881.40Skamil		default:
6891.40Skamil			DPRINTF("Before exiting of the child process\n");
6901.40Skamil			_exit(exitval);
6911.40Skamil		}
6921.40Skamil	}
6931.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6941.40Skamil
6951.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6961.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6971.40Skamil
6981.40Skamil	switch (sigval) {
6991.40Skamil	case SIGKILL:
7001.40Skamil	case SIGABRT:
7011.40Skamil	case SIGHUP:
7021.40Skamil		validate_status_signaled(status, sigval, expect_core);
7031.40Skamil		break;
7041.40Skamil	case SIGSTOP:
7051.46Skamil		validate_status_signaled(status, SIGKILL, 0);
7061.46Skamil		break;
7071.40Skamil	case SIGCONT:
7081.47Skamil	case SIGTSTP:
7091.47Skamil	case SIGTTIN:
7101.47Skamil	case SIGTTOU:
7111.40Skamil		validate_status_exited(status, exitval);
7121.40Skamil		break;
7131.40Skamil	default:
7141.40Skamil		/* NOTREACHED */
7151.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
7161.40Skamil		break;
7171.40Skamil	}
7181.40Skamil
7191.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7201.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
7211.40Skamil}
7221.40Skamil
7231.40Skamil#define TRACEME_VFORK_RAISE(test, sig)						\
7241.40SkamilATF_TC(test);									\
7251.40SkamilATF_TC_HEAD(test, tc)								\
7261.40Skamil{										\
7271.40Skamil	atf_tc_set_md_var(tc, "descr",						\
7281.42Skamil	    "Verify PT_TRACE_ME followed by raise of " #sig " in a vfork(2)ed "	\
7291.42Skamil	    "child");								\
7301.40Skamil}										\
7311.40Skamil										\
7321.40SkamilATF_TC_BODY(test, tc)								\
7331.40Skamil{										\
7341.40Skamil										\
7351.40Skamil	traceme_vfork_raise(sig);						\
7361.40Skamil}
7371.40Skamil
7381.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
7391.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
7401.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
7411.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
7421.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
7431.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
7441.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
7451.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
7461.40Skamil
7471.40Skamil/// ----------------------------------------------------------------------------
7481.40Skamil
7491.52Skamilstatic void
7501.52Skamiltraceme_vfork_crash(int sig)
7511.41Skamil{
7521.41Skamil	pid_t child, wpid;
7531.41Skamil#if defined(TWAIT_HAVE_STATUS)
7541.41Skamil	int status;
7551.41Skamil#endif
7561.41Skamil
7571.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7581.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
7591.41Skamil	if (child == 0) {
7601.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7611.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7621.41Skamil
7631.52Skamil		DPRINTF("Before executing a trap\n");
7641.52Skamil		switch (sig) {
7651.52Skamil		case SIGTRAP:
7661.52Skamil			trigger_trap();
7671.52Skamil			break;
7681.52Skamil		case SIGSEGV:
7691.52Skamil			trigger_segv();
7701.52Skamil			break;
7711.52Skamil		case SIGILL:
7721.52Skamil			trigger_ill();
7731.52Skamil			break;
7741.52Skamil		case SIGFPE:
7751.52Skamil			trigger_fpe();
7761.52Skamil			break;
7771.52Skamil		case SIGBUS:
7781.52Skamil			trigger_bus();
7791.52Skamil			break;
7801.52Skamil		default:
7811.52Skamil			/* NOTREACHED */
7821.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
7831.52Skamil		}
7841.41Skamil
7851.41Skamil		/* NOTREACHED */
7861.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
7871.41Skamil	}
7881.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7891.41Skamil
7901.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7911.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7921.41Skamil
7931.52Skamil	validate_status_signaled(status, sig, 1);
7941.41Skamil
7951.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7961.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
7971.41Skamil}
7981.41Skamil
7991.52Skamil#define TRACEME_VFORK_CRASH(test, sig)						\
8001.52SkamilATF_TC(test);									\
8011.52SkamilATF_TC_HEAD(test, tc)								\
8021.52Skamil{										\
8031.52Skamil	atf_tc_set_md_var(tc, "descr",						\
8041.52Skamil	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a "	\
8051.52Skamil	    "vfork(2)ed child");						\
8061.52Skamil}										\
8071.52Skamil										\
8081.52SkamilATF_TC_BODY(test, tc)								\
8091.52Skamil{										\
8101.52Skamil										\
8111.52Skamil	traceme_vfork_crash(sig);						\
8121.52Skamil}
8131.52Skamil
8141.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
8151.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
8161.52Skamil//TRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
8171.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
8181.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
8191.52Skamil
8201.41Skamil/// ----------------------------------------------------------------------------
8211.41Skamil
8221.43SkamilATF_TC(traceme_vfork_exec);
8231.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
8241.43Skamil{
8251.43Skamil	atf_tc_set_md_var(tc, "descr",
8261.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
8271.43Skamil}
8281.43Skamil
8291.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
8301.43Skamil{
8311.43Skamil	const int sigval = SIGTRAP;
8321.43Skamil	pid_t child, wpid;
8331.43Skamil#if defined(TWAIT_HAVE_STATUS)
8341.43Skamil	int status;
8351.43Skamil#endif
8361.43Skamil
8371.43Skamil	struct ptrace_siginfo info;
8381.43Skamil	memset(&info, 0, sizeof(info));
8391.43Skamil
8401.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8411.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
8421.43Skamil	if (child == 0) {
8431.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8441.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8451.43Skamil
8461.43Skamil		DPRINTF("Before calling execve(2) from child\n");
8471.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
8481.43Skamil
8491.43Skamil		/* NOTREACHED */
8501.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
8511.43Skamil	}
8521.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8531.43Skamil
8541.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8551.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8561.43Skamil
8571.43Skamil	validate_status_stopped(status, sigval);
8581.43Skamil
8591.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
8601.43Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
8611.43Skamil
8621.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
8631.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
8641.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
8651.43Skamil	    info.psi_siginfo.si_errno);
8661.43Skamil
8671.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
8681.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
8691.43Skamil
8701.43Skamil	DPRINTF("Before resuming the child process where it left off and "
8711.43Skamil	    "without signal to be sent\n");
8721.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8731.43Skamil
8741.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8751.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8761.43Skamil
8771.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8781.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8791.43Skamil}
8801.43Skamil
8811.43Skamil/// ----------------------------------------------------------------------------
8821.43Skamil
8831.1Skamil#if defined(TWAIT_HAVE_PID)
8841.51Skamilstatic void
8851.51Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated)
8861.1Skamil{
8871.51Skamil	/*
8881.51Skamil	 * notimeout - disable timeout in await zombie function
8891.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
8901.51Skamil	 */
8911.1Skamil
8921.1Skamil	struct msg_fds parent_tracee, parent_tracer;
8931.1Skamil	const int exitval_tracee = 5;
8941.1Skamil	const int exitval_tracer = 10;
8951.1Skamil	pid_t tracee, tracer, wpid;
8961.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8971.1Skamil#if defined(TWAIT_HAVE_STATUS)
8981.1Skamil	int status;
8991.1Skamil#endif
9001.1Skamil
9011.13Schristos	DPRINTF("Spawn tracee\n");
9021.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9031.1Skamil	tracee = atf_utils_fork();
9041.1Skamil	if (tracee == 0) {
9051.1Skamil		// Wait for parent to let us exit
9061.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
9071.1Skamil		_exit(exitval_tracee);
9081.1Skamil	}
9091.1Skamil
9101.13Schristos	DPRINTF("Spawn debugger\n");
9111.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
9121.1Skamil	tracer = atf_utils_fork();
9131.1Skamil	if (tracer == 0) {
9141.51Skamil		if(unrelated) {
9151.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
9161.51Skamil			tracer = atf_utils_fork();
9171.51Skamil			if (tracer != 0)
9181.51Skamil				_exit(exitval_tracer);
9191.51Skamil		}
9201.51Skamil
9211.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
9221.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
9231.1Skamil
9241.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
9251.1Skamil		FORKEE_REQUIRE_SUCCESS(
9261.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9271.1Skamil
9281.1Skamil		forkee_status_stopped(status, SIGSTOP);
9291.1Skamil
9301.1Skamil		/* Resume tracee with PT_CONTINUE */
9311.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
9321.1Skamil
9331.1Skamil		/* Inform parent that tracer has attached to tracee */
9341.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
9351.1Skamil
9361.1Skamil		/* Wait for parent to tell use that tracee should have exited */
9371.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
9381.1Skamil
9391.1Skamil		/* Wait for tracee and assert that it exited */
9401.1Skamil		FORKEE_REQUIRE_SUCCESS(
9411.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9421.1Skamil
9431.1Skamil		forkee_status_exited(status, exitval_tracee);
9441.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
9451.1Skamil
9461.13Schristos		DPRINTF("Before exiting of the tracer process\n");
9471.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
9481.51Skamil	}
9491.51Skamil
9501.51Skamil	if (unrelated) {
9511.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
9521.51Skamil		    "calling %s()\n", TWAIT_FNAME);
9531.51Skamil		TWAIT_REQUIRE_SUCCESS(
9541.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
9551.51Skamil
9561.51Skamil		validate_status_exited(status, exitval_tracer);
9571.51Skamil
9581.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
9591.51Skamil		    TWAIT_FNAME);
9601.51Skamil		TWAIT_REQUIRE_SUCCESS(
9611.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
9621.1Skamil	}
9631.1Skamil
9641.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
9651.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
9661.1Skamil
9671.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
9681.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
9691.1Skamil
9701.13Schristos	DPRINTF("Detect that tracee is zombie\n");
9711.51Skamil	if (notimeout)
9721.26Skamil		await_zombie_raw(tracee, 0);
9731.26Skamil	else
9741.26Skamil		await_zombie(tracee);
9751.1Skamil
9761.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
9771.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
9781.1Skamil	    TWAIT_FNAME);
9791.1Skamil	TWAIT_REQUIRE_SUCCESS(
9801.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
9811.1Skamil
9821.51Skamil	if (unrelated) {
9831.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
9841.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
9851.51Skamil	} else {
9861.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
9871.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
9881.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
9891.51Skamil		        "%s()\n", TWAIT_FNAME);
9901.51Skamil
9911.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
9921.51Skamil		        "tracee\n");
9931.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
9941.51Skamil		    tracer);
9951.1Skamil
9961.51Skamil		validate_status_exited(status, exitval_tracer);
9971.51Skamil	}
9981.1Skamil
9991.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
10001.1Skamil	    TWAIT_FNAME);
10011.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10021.1Skamil
10031.1Skamil	validate_status_exited(status, exitval_tracee);
10041.1Skamil
10051.1Skamil	msg_close(&parent_tracer);
10061.1Skamil	msg_close(&parent_tracee);
10071.1Skamil}
10081.26Skamil
10091.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
10101.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
10111.51Skamil{
10121.51Skamil	atf_tc_set_md_var(tc, "descr",
10131.51Skamil	    "Assert that tracer sees process termination before the parent");
10141.51Skamil}
10151.51Skamil
10161.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
10171.26Skamil{
10181.26Skamil
10191.51Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false);
10201.26Skamil}
10211.26Skamil
10221.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
10231.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
10241.1Skamil{
10251.1Skamil	atf_tc_set_md_var(tc, "descr",
10261.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
10271.51Skamil	    "process and no other error is reported");
10281.1Skamil}
10291.1Skamil
10301.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
10311.1Skamil{
10321.51Skamil	time_t start, end;
10331.51Skamil	double diff;
10341.51Skamil	unsigned long N = 0;
10351.1Skamil
10361.51Skamil	/*
10371.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
10381.51Skamil	 * This test body isn't specific to this race, however it's just good
10391.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
10401.51Skamil	 */
10411.1Skamil
10421.51Skamil	start = time(NULL);
10431.51Skamil	while (true) {
10441.51Skamil		DPRINTF("Step: %lu\n", N);
10451.51Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false);
10461.51Skamil		end = time(NULL);
10471.51Skamil		diff = difftime(end, start);
10481.51Skamil		if (diff >= 5.0)
10491.51Skamil			break;
10501.51Skamil		++N;
10511.1Skamil	}
10521.51Skamil	DPRINTF("Iterations: %lu\n", N);
10531.51Skamil}
10541.1Skamil
10551.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
10561.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
10571.51Skamil{
10581.51Skamil	atf_tc_set_md_var(tc, "descr",
10591.51Skamil	    "Assert that tracer sees process termination before the parent");
10601.51Skamil}
10611.1Skamil
10621.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
10631.51Skamil{
10641.1Skamil
10651.51Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true);
10661.1Skamil}
10671.1Skamil#endif
10681.1Skamil
10691.51Skamil/// ----------------------------------------------------------------------------
10701.51Skamil
10711.51SkamilATF_TC(parent_attach_to_its_child);
10721.51SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
10731.1Skamil{
10741.1Skamil	atf_tc_set_md_var(tc, "descr",
10751.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
10761.1Skamil}
10771.1Skamil
10781.51SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
10791.1Skamil{
10801.1Skamil	struct msg_fds parent_tracee;
10811.1Skamil	const int exitval_tracee = 5;
10821.1Skamil	pid_t tracee, wpid;
10831.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10841.1Skamil#if defined(TWAIT_HAVE_STATUS)
10851.1Skamil	int status;
10861.1Skamil#endif
10871.1Skamil
10881.13Schristos	DPRINTF("Spawn tracee\n");
10891.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10901.1Skamil	tracee = atf_utils_fork();
10911.1Skamil	if (tracee == 0) {
10921.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
10931.13Schristos		DPRINTF("Parent should now attach to tracee\n");
10941.1Skamil
10951.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
10961.1Skamil		/* Wait for message from the parent */
10971.1Skamil		_exit(exitval_tracee);
10981.1Skamil	}
10991.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
11001.57Skamil
11011.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
11021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
11031.1Skamil
11041.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
11051.1Skamil	    TWAIT_FNAME);
11061.1Skamil	TWAIT_REQUIRE_SUCCESS(
11071.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11081.1Skamil
11091.1Skamil	validate_status_stopped(status, SIGSTOP);
11101.1Skamil
11111.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
11121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
11131.1Skamil
11141.13Schristos	DPRINTF("Let the tracee exit now\n");
11151.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
11161.1Skamil
11171.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
11181.1Skamil	TWAIT_REQUIRE_SUCCESS(
11191.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11201.1Skamil
11211.1Skamil	validate_status_exited(status, exitval_tracee);
11221.1Skamil
11231.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
11241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
11251.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
11261.1Skamil
11271.1Skamil	msg_close(&parent_tracee);
11281.1Skamil}
11291.1Skamil
11301.51Skamil/// ----------------------------------------------------------------------------
11311.51Skamil
11321.51SkamilATF_TC(child_attach_to_its_parent);
11331.51SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
11341.1Skamil{
11351.1Skamil	atf_tc_set_md_var(tc, "descr",
11361.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
11371.1Skamil}
11381.1Skamil
11391.51SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
11401.1Skamil{
11411.1Skamil	struct msg_fds parent_tracee;
11421.1Skamil	const int exitval_tracer = 5;
11431.1Skamil	pid_t tracer, wpid;
11441.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11451.1Skamil#if defined(TWAIT_HAVE_STATUS)
11461.1Skamil	int status;
11471.1Skamil#endif
11481.1Skamil
11491.13Schristos	DPRINTF("Spawn tracer\n");
11501.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11511.1Skamil	tracer = atf_utils_fork();
11521.1Skamil	if (tracer == 0) {
11531.1Skamil
11541.1Skamil		/* Wait for message from the parent */
11551.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
11561.1Skamil
11571.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
11581.1Skamil		    getppid());
11591.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
11601.1Skamil
11611.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
11621.1Skamil		    TWAIT_FNAME);
11631.1Skamil		FORKEE_REQUIRE_SUCCESS(
11641.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
11651.1Skamil
11661.1Skamil		forkee_status_stopped(status, SIGSTOP);
11671.1Skamil
11681.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
11691.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
11701.1Skamil		    != -1);
11711.1Skamil
11721.1Skamil		/* Tell parent we are ready */
11731.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
11741.1Skamil
11751.1Skamil		_exit(exitval_tracer);
11761.1Skamil	}
11771.1Skamil
11781.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
11791.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
11801.13Schristos	DPRINTF("Allow the tracer to exit now\n");
11811.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
11821.1Skamil
11831.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
11841.1Skamil	TWAIT_REQUIRE_SUCCESS(
11851.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
11861.1Skamil
11871.1Skamil	validate_status_exited(status, exitval_tracer);
11881.1Skamil
11891.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
11901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
11911.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
11921.1Skamil
11931.1Skamil	msg_close(&parent_tracee);
11941.1Skamil}
11951.1Skamil
11961.51Skamil/// ----------------------------------------------------------------------------
11971.51Skamil
11981.1Skamil#if defined(TWAIT_HAVE_PID)
11991.1Skamil
12001.51Skamilenum tracee_sees_its_original_parent_type {
12011.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
12021.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
12031.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
12041.51Skamil};
12051.51Skamil
12061.51Skamilstatic void
12071.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
12081.1Skamil{
12091.1Skamil	struct msg_fds parent_tracer, parent_tracee;
12101.1Skamil	const int exitval_tracee = 5;
12111.1Skamil	const int exitval_tracer = 10;
12121.1Skamil	pid_t parent, tracee, tracer, wpid;
12131.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
12141.1Skamil#if defined(TWAIT_HAVE_STATUS)
12151.1Skamil	int status;
12161.1Skamil#endif
12171.51Skamil	/* sysctl(3) - kinfo_proc2 */
12181.51Skamil	int name[CTL_MAXNAME];
12191.51Skamil	struct kinfo_proc2 kp;
12201.51Skamil	size_t len = sizeof(kp);
12211.51Skamil	unsigned int namelen;
12221.51Skamil
12231.51Skamil	/* procfs - status  */
12241.51Skamil	FILE *fp;
12251.51Skamil	struct stat st;
12261.51Skamil	const char *fname = "/proc/curproc/status";
12271.51Skamil	char s_executable[MAXPATHLEN];
12281.51Skamil	int s_pid, s_ppid;
12291.51Skamil	int rv;
12301.51Skamil
12311.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
12321.51Skamil		SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 ||
12331.51Skamil		                (errno == ENOENT));
12341.51Skamil		if (rv != 0) {
12351.51Skamil			atf_tc_skip("/proc/curproc/status not found");
12361.51Skamil		}
12371.51Skamil	}
12381.1Skamil
12391.13Schristos	DPRINTF("Spawn tracee\n");
12401.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
12411.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
12421.1Skamil	tracee = atf_utils_fork();
12431.1Skamil	if (tracee == 0) {
12441.1Skamil		parent = getppid();
12451.1Skamil
12461.1Skamil		/* Emit message to the parent */
12471.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
12481.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
12491.1Skamil
12501.51Skamil		switch (type) {
12511.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
12521.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
12531.51Skamil			break;
12541.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
12551.51Skamil			namelen = 0;
12561.51Skamil			name[namelen++] = CTL_KERN;
12571.51Skamil			name[namelen++] = KERN_PROC2;
12581.51Skamil			name[namelen++] = KERN_PROC_PID;
12591.51Skamil			name[namelen++] = getpid();
12601.51Skamil			name[namelen++] = len;
12611.51Skamil			name[namelen++] = 1;
12621.51Skamil
12631.51Skamil			FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL,
12641.51Skamil			                        0),
12651.51Skamil			                 0);
12661.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
12671.51Skamil			break;
12681.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
12691.51Skamil			/*
12701.51Skamil			 * Format:
12711.51Skamil			 *  EXECUTABLE PID PPID ...
12721.51Skamil			 */
12731.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
12741.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
12751.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
12761.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
12771.51Skamil			break;
12781.51Skamil		}
12791.1Skamil
12801.1Skamil		_exit(exitval_tracee);
12811.1Skamil	}
12821.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
12831.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
12841.1Skamil
12851.13Schristos	DPRINTF("Spawn debugger\n");
12861.1Skamil	tracer = atf_utils_fork();
12871.1Skamil	if (tracer == 0) {
12881.1Skamil		/* No IPC to communicate with the child */
12891.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12901.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12911.1Skamil
12921.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12931.1Skamil		FORKEE_REQUIRE_SUCCESS(
12941.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12951.1Skamil
12961.1Skamil		forkee_status_stopped(status, SIGSTOP);
12971.1Skamil
12981.1Skamil		/* Resume tracee with PT_CONTINUE */
12991.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
13001.1Skamil
13011.1Skamil		/* Inform parent that tracer has attached to tracee */
13021.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
13031.1Skamil
13041.1Skamil		/* Wait for parent to tell use that tracee should have exited */
13051.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
13061.1Skamil
13071.1Skamil		/* Wait for tracee and assert that it exited */
13081.1Skamil		FORKEE_REQUIRE_SUCCESS(
13091.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13101.1Skamil
13111.1Skamil		forkee_status_exited(status, exitval_tracee);
13121.1Skamil
13131.13Schristos		DPRINTF("Before exiting of the tracer process\n");
13141.1Skamil		_exit(exitval_tracer);
13151.1Skamil	}
13161.1Skamil
13171.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
13181.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
13191.1Skamil
13201.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
13211.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
13221.1Skamil
13231.13Schristos	DPRINTF("Detect that tracee is zombie\n");
13241.1Skamil	await_zombie(tracee);
13251.1Skamil
13261.13Schristos	DPRINTF("Assert that there is no status about tracee - "
13271.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
13281.1Skamil	TWAIT_REQUIRE_SUCCESS(
13291.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
13301.1Skamil
13311.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
13321.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
13331.1Skamil
13341.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
13351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
13361.1Skamil	    tracer);
13371.1Skamil
13381.1Skamil	validate_status_exited(status, exitval_tracer);
13391.1Skamil
13401.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
13411.1Skamil	    TWAIT_FNAME);
13421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
13431.1Skamil	    tracee);
13441.1Skamil
13451.1Skamil	validate_status_exited(status, exitval_tracee);
13461.1Skamil
13471.1Skamil	msg_close(&parent_tracer);
13481.1Skamil	msg_close(&parent_tracee);
13491.1Skamil}
13501.1Skamil
13511.51Skamil#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)			\
13521.51SkamilATF_TC(test);									\
13531.51SkamilATF_TC_HEAD(test, tc)								\
13541.51Skamil{										\
13551.51Skamil	atf_tc_set_md_var(tc, "descr",						\
13561.51Skamil	    "Assert that tracee sees its original parent when being traced "	\
13571.51Skamil	    "(check " descr ")");						\
13581.51Skamil}										\
13591.51Skamil										\
13601.51SkamilATF_TC_BODY(test, tc)								\
13611.51Skamil{										\
13621.51Skamil										\
13631.51Skamil	tracee_sees_its_original_parent(type);					\
13641.1Skamil}
13651.1Skamil
13661.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
13671.51Skamil	tracee_sees_its_original_parent_getppid,
13681.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
13691.51Skamil	"getppid(2)");
13701.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
13711.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
13721.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
13731.51Skamil	"sysctl(3) and kinfo_proc2");
13741.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
13751.51Skamil	tracee_sees_its_original_parent_procfs_status,
13761.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
13771.51Skamil	"the status file in procfs");
13781.1Skamil#endif
13791.1Skamil
13801.51Skamil/// ----------------------------------------------------------------------------
13811.1Skamil
13821.53Skamilstatic void
13831.53Skamileventmask_preserved(int event)
13841.1Skamil{
13851.1Skamil	const int exitval = 5;
13861.1Skamil	const int sigval = SIGSTOP;
13871.1Skamil	pid_t child, wpid;
13881.1Skamil#if defined(TWAIT_HAVE_STATUS)
13891.1Skamil	int status;
13901.1Skamil#endif
13911.1Skamil	ptrace_event_t set_event, get_event;
13921.1Skamil	const int len = sizeof(ptrace_event_t);
13931.1Skamil
13941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13961.1Skamil	if (child == 0) {
13971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13991.1Skamil
14001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14021.1Skamil
14031.13Schristos		DPRINTF("Before exiting of the child process\n");
14041.1Skamil		_exit(exitval);
14051.1Skamil	}
14061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14071.1Skamil
14081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14101.1Skamil
14111.1Skamil	validate_status_stopped(status, sigval);
14121.1Skamil
14131.53Skamil	set_event.pe_set_event = event;
14141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
14161.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
14171.1Skamil
14181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14191.1Skamil	    "without signal to be sent\n");
14201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14211.1Skamil
14221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14241.1Skamil
14251.1Skamil	validate_status_exited(status, exitval);
14261.1Skamil
14271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14281.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14291.1Skamil}
14301.1Skamil
14311.53Skamil#define EVENTMASK_PRESERVED(test, event)					\
14321.53SkamilATF_TC(test);									\
14331.53SkamilATF_TC_HEAD(test, tc)								\
14341.53Skamil{										\
14351.53Skamil	atf_tc_set_md_var(tc, "descr",						\
14361.53Skamil	    "Verify that eventmask " #event " is preserved");			\
14371.53Skamil}										\
14381.53Skamil										\
14391.53SkamilATF_TC_BODY(test, tc)								\
14401.53Skamil{										\
14411.53Skamil										\
14421.53Skamil	eventmask_preserved(event);						\
14431.1Skamil}
14441.1Skamil
14451.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
14461.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
14471.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
14481.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
14491.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
14501.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
14511.1Skamil
14521.53Skamil/// ----------------------------------------------------------------------------
14531.1Skamil
14541.28Skamilstatic void
14551.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
14561.32Skamil          bool trackvforkdone, bool detachchild, bool detachparent)
14571.1Skamil{
14581.1Skamil	const int exitval = 5;
14591.1Skamil	const int exitval2 = 15;
14601.1Skamil	const int sigval = SIGSTOP;
14611.31Skamil	pid_t child, child2 = 0, wpid;
14621.1Skamil#if defined(TWAIT_HAVE_STATUS)
14631.1Skamil	int status;
14641.1Skamil#endif
14651.1Skamil	ptrace_state_t state;
14661.1Skamil	const int slen = sizeof(state);
14671.1Skamil	ptrace_event_t event;
14681.1Skamil	const int elen = sizeof(event);
14691.1Skamil
14701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14721.1Skamil	if (child == 0) {
14731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14751.1Skamil
14761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14781.1Skamil
14791.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
14801.1Skamil
14811.1Skamil		if (child2 == 0)
14821.1Skamil			_exit(exitval2);
14831.1Skamil
14841.1Skamil		FORKEE_REQUIRE_SUCCESS
14851.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
14861.1Skamil
14871.1Skamil		forkee_status_exited(status, exitval2);
14881.1Skamil
14891.13Schristos		DPRINTF("Before exiting of the child process\n");
14901.1Skamil		_exit(exitval);
14911.1Skamil	}
14921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14931.1Skamil
14941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14961.1Skamil
14971.1Skamil	validate_status_stopped(status, sigval);
14981.1Skamil
14991.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
15001.30Skamil	        trackfork ? "|PTRACE_FORK" : "",
15011.30Skamil	        trackvfork ? "|PTRACE_VFORK" : "",
15021.30Skamil	        trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
15031.30Skamil	event.pe_set_event = 0;
15041.30Skamil	if (trackfork)
15051.30Skamil		event.pe_set_event |= PTRACE_FORK;
15061.30Skamil	if (trackvfork)
15071.30Skamil		event.pe_set_event |= PTRACE_VFORK;
15081.30Skamil	if (trackvforkdone)
15091.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
15101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
15111.1Skamil
15121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15131.1Skamil	    "without signal to be sent\n");
15141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15151.1Skamil
15161.29Skamil#if defined(TWAIT_HAVE_PID)
15171.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
15181.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
15191.29Skamil		        child);
15201.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
15211.29Skamil		                      child);
15221.1Skamil
15231.29Skamil		validate_status_stopped(status, SIGTRAP);
15241.1Skamil
15251.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
15261.29Skamil		                       slen) != -1);
15271.31Skamil		if (trackfork && fn == fork) {
15281.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
15291.30Skamil			       PTRACE_FORK);
15301.30Skamil		}
15311.31Skamil		if (trackvfork && fn == vfork) {
15321.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
15331.30Skamil			       PTRACE_VFORK);
15341.30Skamil		}
15351.29Skamil
15361.29Skamil		child2 = state.pe_other_pid;
15371.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
15381.29Skamil
15391.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
15401.29Skamil		        "%d\n", TWAIT_FNAME, child2, child);
15411.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
15421.29Skamil		    child2);
15431.1Skamil
15441.29Skamil		validate_status_stopped(status, SIGTRAP);
15451.1Skamil
15461.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state,
15471.29Skamil		                       slen) != -1);
15481.31Skamil		if (trackfork && fn == fork) {
15491.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
15501.30Skamil			       PTRACE_FORK);
15511.30Skamil		}
15521.31Skamil		if (trackvfork && fn == vfork) {
15531.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
15541.30Skamil			       PTRACE_VFORK);
15551.30Skamil		}
15561.30Skamil
15571.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
15581.29Skamil
15591.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
15601.29Skamil		    "and without signal to be sent\n");
15611.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0)
15621.29Skamil		                != -1);
15631.29Skamil
15641.29Skamil		DPRINTF("Before resuming the child process where it left off "
15651.29Skamil		        "and without signal to be sent\n");
15661.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15671.30Skamil	}
15681.30Skamil#endif
15691.30Skamil
15701.31Skamil	if (trackvforkdone && fn == vfork) {
15711.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
15721.30Skamil		        child);
15731.30Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
15741.30Skamil		                      child);
15751.30Skamil
15761.30Skamil		validate_status_stopped(status, SIGTRAP);
15771.30Skamil
15781.30Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
15791.30Skamil		                       slen) != -1);
15801.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
15811.30Skamil
15821.30Skamil		child2 = state.pe_other_pid;
15831.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
15841.30Skamil		        child2);
15851.30Skamil
15861.30Skamil		DPRINTF("Before resuming the child process where it left off "
15871.30Skamil		        "and without signal to be sent\n");
15881.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15891.30Skamil	}
15901.29Skamil
15911.30Skamil#if defined(TWAIT_HAVE_PID)
15921.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
15931.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
15941.29Skamil		        "\n", TWAIT_FNAME);
15951.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
15961.29Skamil		    child2);
15971.29Skamil
15981.29Skamil		validate_status_exited(status, exitval2);
15991.29Skamil
16001.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
16011.29Skamil		        "process\n", TWAIT_FNAME);
16021.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
16031.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
16041.29Skamil	}
16051.29Skamil#endif
16061.1Skamil
16071.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
16081.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
16091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16101.1Skamil
16111.1Skamil	validate_status_stopped(status, SIGCHLD);
16121.1Skamil
16131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16141.1Skamil	    "without signal to be sent\n");
16151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16161.1Skamil
16171.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
16181.1Skamil	    TWAIT_FNAME);
16191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16201.1Skamil
16211.1Skamil	validate_status_exited(status, exitval);
16221.1Skamil
16231.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
16241.1Skamil	    TWAIT_FNAME);
16251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16261.1Skamil}
16271.28Skamil
16281.32Skamil#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent)	\
16291.32SkamilATF_TC(name);									\
16301.32SkamilATF_TC_HEAD(name, tc)								\
16311.32Skamil{										\
16321.32Skamil	atf_tc_set_md_var(tc, "descr", descr);					\
16331.32Skamil}										\
16341.32Skamil										\
16351.32SkamilATF_TC_BODY(name, tc)								\
16361.32Skamil{										\
16371.32Skamil										\
16381.32Skamil	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);		\
16391.32Skamil}
16401.32Skamil
16411.32Skamil#define F false
16421.32Skamil#define T true
16431.32Skamil
16441.32Skamil#define F_IF__0(x)
16451.32Skamil#define F_IF__1(x) x
16461.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
16471.32Skamil#define F_IF_(x,y) F_IF__(x,y)
16481.32Skamil#define F_IF(x,y) F_IF_(x,y)
16491.32Skamil
16501.32Skamil#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit)	\
16511.32Skamil        "Verify " #function "(2) called with 0"					\
16521.32Skamil        F_IF(forkbit,"|PTRACE_FORK")						\
16531.32Skamil        F_IF(vforkbit,"|PTRACE_VFORK")						\
16541.32Skamil        F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")					\
16551.32Skamil        " in EVENT_MASK."							\
16561.32Skamil        F_IF(dchildbit," Detach child in this test.")				\
16571.32Skamil        F_IF(dparentbit," Detach parent in this test.")
16581.1Skamil
16591.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
16601.31Skamil#if defined(TWAIT_HAVE_PID)
16611.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
16621.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
16631.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
16641.31Skamil#endif
16651.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
16661.31Skamil#if defined(TWAIT_HAVE_PID)
16671.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
16681.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
16691.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
16701.31Skamil#endif
16711.1Skamil
16721.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
16731.31Skamil#if defined(TWAIT_HAVE_PID)
16741.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
16751.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
16761.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
16771.31Skamil#endif
16781.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
16791.31Skamil#if defined(TWAIT_HAVE_PID)
16801.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
16811.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
16821.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
16831.31Skamil#endif
16841.31Skamil
16851.54Skamil/// ----------------------------------------------------------------------------
16861.31Skamil
16871.54Skamilenum bytes_transfer_type {
16881.54Skamil	BYTES_TRANSFER_DATA,
16891.54Skamil	BYTES_TRANSFER_DATAIO,
16901.54Skamil	BYTES_TRANSFER_TEXT,
16911.54Skamil	BYTES_TRANSFER_TEXTIO,
16921.54Skamil	BYTES_TRANSFER_AUXV
16931.54Skamil};
16941.31Skamil
16951.54Skamilstatic int __used
16961.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
16971.54Skamil{
16981.54Skamil	int e, f, g, h;
16991.1Skamil
17001.54Skamil	a *= 4;
17011.54Skamil	b += 3;
17021.54Skamil	c -= 2;
17031.54Skamil	d /= 1;
17041.1Skamil
17051.54Skamil	e = strtol("10", NULL, 10);
17061.54Skamil	f = strtol("20", NULL, 10);
17071.54Skamil	g = strtol("30", NULL, 10);
17081.54Skamil	h = strtol("40", NULL, 10);
17091.1Skamil
17101.54Skamil	return (a + b * c - d) + (e * f - g / h);
17111.1Skamil}
17121.1Skamil
17131.54Skamilstatic void
17141.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
17151.1Skamil{
17161.1Skamil	const int exitval = 5;
17171.1Skamil	const int sigval = SIGSTOP;
17181.1Skamil	pid_t child, wpid;
17191.54Skamil	bool skip = false;
17201.1Skamil
17211.54Skamil	int lookup_me = 0;
17221.54Skamil	uint8_t lookup_me8 = 0;
17231.54Skamil	uint16_t lookup_me16 = 0;
17241.54Skamil	uint32_t lookup_me32 = 0;
17251.54Skamil	uint64_t lookup_me64 = 0;
17261.1Skamil
17271.54Skamil	int magic = 0x13579246;
17281.54Skamil	uint8_t magic8 = 0xab;
17291.54Skamil	uint16_t magic16 = 0x1234;
17301.54Skamil	uint32_t magic32 = 0x98765432;
17311.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
17321.1Skamil
17331.54Skamil	struct ptrace_io_desc io;
17341.1Skamil#if defined(TWAIT_HAVE_STATUS)
17351.1Skamil	int status;
17361.1Skamil#endif
17371.56Skamil	/* 512 is more than enough, for the purposes of ATF it's good enough */
17381.56Skamil	AuxInfo ai[512], *aip;
17391.55Schristos
17401.55Schristos	ATF_REQUIRE(size < sizeof(ai));
17411.1Skamil
17421.54Skamil	/* Prepare variables for .TEXT transfers */
17431.54Skamil	switch (type) {
17441.54Skamil	case BYTES_TRANSFER_TEXT:
17451.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
17461.54Skamil		break;
17471.54Skamil	case BYTES_TRANSFER_TEXTIO:
17481.54Skamil		switch (size) {
17491.54Skamil		case 8:
17501.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
17511.54Skamil			break;
17521.54Skamil		case 16:
17531.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
17541.54Skamil			break;
17551.54Skamil		case 32:
17561.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
17571.54Skamil			break;
17581.54Skamil		case 64:
17591.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
17601.54Skamil			break;
17611.54Skamil		}
17621.54Skamil		break;
17631.54Skamil	default:
17641.54Skamil		break;
17651.54Skamil	}
17661.1Skamil
17671.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
17681.54Skamil	switch (type) {
17691.54Skamil	case BYTES_TRANSFER_TEXTIO:
17701.54Skamil	case BYTES_TRANSFER_DATAIO:
17711.54Skamil		io.piod_op = operation;
17721.54Skamil		switch (size) {
17731.54Skamil		case 8:
17741.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
17751.54Skamil			               (void *)bytes_transfer_dummy :
17761.54Skamil			               &lookup_me8;
17771.54Skamil			io.piod_addr = &lookup_me8;
17781.54Skamil			io.piod_len = sizeof(lookup_me8);
17791.54Skamil			break;
17801.54Skamil		case 16:
17811.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
17821.54Skamil			               (void *)bytes_transfer_dummy :
17831.54Skamil			               &lookup_me16;
17841.54Skamil			io.piod_addr = &lookup_me16;
17851.54Skamil			io.piod_len = sizeof(lookup_me16);
17861.54Skamil			break;
17871.54Skamil		case 32:
17881.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
17891.54Skamil			               (void *)bytes_transfer_dummy :
17901.54Skamil			               &lookup_me32;
17911.54Skamil			io.piod_addr = &lookup_me32;
17921.54Skamil			io.piod_len = sizeof(lookup_me32);
17931.54Skamil			break;
17941.54Skamil		case 64:
17951.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
17961.54Skamil			               (void *)bytes_transfer_dummy :
17971.54Skamil			               &lookup_me64;
17981.54Skamil			io.piod_addr = &lookup_me64;
17991.54Skamil			io.piod_len = sizeof(lookup_me64);
18001.54Skamil			break;
18011.54Skamil		default:
18021.54Skamil			break;
18031.54Skamil		}
18041.54Skamil		break;
18051.54Skamil	case BYTES_TRANSFER_AUXV:
18061.54Skamil		io.piod_op = operation;
18071.54Skamil		io.piod_offs = 0;
18081.54Skamil		io.piod_addr = ai;
18091.54Skamil		io.piod_len = size;
18101.54Skamil		break;
18111.54Skamil	default:
18121.54Skamil		break;
18131.1Skamil	}
18141.1Skamil
18151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18171.1Skamil	if (child == 0) {
18181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18201.1Skamil
18211.54Skamil		switch (type) {
18221.54Skamil		case BYTES_TRANSFER_DATA:
18231.54Skamil			switch (operation) {
18241.54Skamil			case PT_READ_D:
18251.54Skamil			case PT_READ_I:
18261.54Skamil				lookup_me = magic;
18271.54Skamil				break;
18281.54Skamil			default:
18291.54Skamil				break;
18301.54Skamil			}
18311.54Skamil			break;
18321.54Skamil		case BYTES_TRANSFER_DATAIO:
18331.54Skamil			switch (operation) {
18341.54Skamil			case PIOD_READ_D:
18351.54Skamil			case PIOD_READ_I:
18361.54Skamil				switch (size) {
18371.54Skamil				case 8:
18381.54Skamil					lookup_me8 = magic8;
18391.54Skamil					break;
18401.54Skamil				case 16:
18411.54Skamil					lookup_me16 = magic16;
18421.54Skamil					break;
18431.54Skamil				case 32:
18441.54Skamil					lookup_me32 = magic32;
18451.54Skamil					break;
18461.54Skamil				case 64:
18471.54Skamil					lookup_me64 = magic64;
18481.54Skamil					break;
18491.54Skamil				default:
18501.54Skamil					break;
18511.54Skamil				}
18521.54Skamil				break;
18531.54Skamil			default:
18541.54Skamil				break;
18551.54Skamil			}
18561.54Skamil		default:
18571.54Skamil			break;
18581.54Skamil		}
18591.54Skamil
18601.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18611.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18621.1Skamil
18631.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
18641.54Skamil		switch (type) {
18651.54Skamil		case BYTES_TRANSFER_DATA:
18661.54Skamil			switch (operation) {
18671.54Skamil			case PT_WRITE_D:
18681.54Skamil			case PT_WRITE_I:
18691.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
18701.54Skamil				break;
18711.54Skamil			default:
18721.54Skamil				break;
18731.54Skamil			}
18741.54Skamil			break;
18751.54Skamil		case BYTES_TRANSFER_DATAIO:
18761.54Skamil			switch (operation) {
18771.54Skamil			case PIOD_WRITE_D:
18781.54Skamil			case PIOD_WRITE_I:
18791.54Skamil				switch (size) {
18801.54Skamil				case 8:
18811.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
18821.54Skamil					break;
18831.54Skamil				case 16:
18841.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
18851.54Skamil					break;
18861.54Skamil				case 32:
18871.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
18881.54Skamil					break;
18891.54Skamil				case 64:
18901.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
18911.54Skamil					break;
18921.54Skamil				default:
18931.54Skamil					break;
18941.54Skamil				}
18951.54Skamil				break;
18961.54Skamil			default:
18971.54Skamil				break;
18981.54Skamil			}
18991.54Skamil			break;
19001.54Skamil		case BYTES_TRANSFER_TEXT:
19011.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
19021.54Skamil			                     sizeof(magic)) == 0);
19031.54Skamil			break;
19041.54Skamil		case BYTES_TRANSFER_TEXTIO:
19051.54Skamil			switch (size) {
19061.54Skamil			case 8:
19071.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
19081.54Skamil				                     bytes_transfer_dummy,
19091.54Skamil				                     sizeof(magic8)) == 0);
19101.54Skamil				break;
19111.54Skamil			case 16:
19121.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
19131.54Skamil				                     bytes_transfer_dummy,
19141.54Skamil				                     sizeof(magic16)) == 0);
19151.54Skamil				break;
19161.54Skamil			case 32:
19171.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
19181.54Skamil				                     bytes_transfer_dummy,
19191.54Skamil				                     sizeof(magic32)) == 0);
19201.54Skamil				break;
19211.54Skamil			case 64:
19221.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
19231.54Skamil				                     bytes_transfer_dummy,
19241.54Skamil				                     sizeof(magic64)) == 0);
19251.54Skamil				break;
19261.54Skamil			}
19271.54Skamil			break;
19281.54Skamil		default:
19291.54Skamil			break;
19301.54Skamil		}
19311.54Skamil
19321.13Schristos		DPRINTF("Before exiting of the child process\n");
19331.1Skamil		_exit(exitval);
19341.1Skamil	}
19351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19361.1Skamil
19371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19391.1Skamil
19401.1Skamil	validate_status_stopped(status, sigval);
19411.1Skamil
19421.54Skamil	/* Check PaX MPROTECT */
19431.54Skamil	if (!can_we_write_to_text(child)) {
19441.54Skamil		switch (type) {
19451.54Skamil		case BYTES_TRANSFER_TEXTIO:
19461.54Skamil			switch (operation) {
19471.54Skamil			case PIOD_WRITE_D:
19481.54Skamil			case PIOD_WRITE_I:
19491.54Skamil				skip = true;
19501.54Skamil				break;
19511.54Skamil			default:
19521.54Skamil				break;
19531.54Skamil			}
19541.54Skamil			break;
19551.54Skamil		case BYTES_TRANSFER_TEXT:
19561.54Skamil			switch (operation) {
19571.54Skamil			case PT_WRITE_D:
19581.54Skamil			case PT_WRITE_I:
19591.54Skamil				skip = true;
19601.54Skamil				break;
19611.54Skamil			default:
19621.54Skamil				break;
19631.54Skamil			}
19641.54Skamil			break;
19651.54Skamil		default:
19661.54Skamil			break;
19671.54Skamil		}
19681.54Skamil	}
19691.1Skamil
19701.54Skamil	/* Bailout cleanly killing the child process */
19711.54Skamil	if (skip) {
19721.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
19731.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19741.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
19751.54Skamil		                      child);
19761.1Skamil
19771.54Skamil		validate_status_signaled(status, SIGKILL, 0);
19781.1Skamil
19791.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
19801.54Skamil	}
19811.1Skamil
19821.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
19831.54Skamil	       "parent=%d\n", child, getpid());
19841.1Skamil
19851.54Skamil	switch (type) {
19861.54Skamil	case BYTES_TRANSFER_TEXTIO:
19871.54Skamil	case BYTES_TRANSFER_DATAIO:
19881.54Skamil	case BYTES_TRANSFER_AUXV:
19891.54Skamil		switch (operation) {
19901.54Skamil		case PIOD_WRITE_D:
19911.54Skamil		case PIOD_WRITE_I:
19921.54Skamil			switch (size) {
19931.54Skamil			case 8:
19941.54Skamil				lookup_me8 = magic8;
19951.54Skamil				break;
19961.54Skamil			case 16:
19971.54Skamil				lookup_me16 = magic16;
19981.54Skamil				break;
19991.54Skamil			case 32:
20001.54Skamil				lookup_me32 = magic32;
20011.54Skamil				break;
20021.54Skamil			case 64:
20031.54Skamil				lookup_me64 = magic64;
20041.54Skamil				break;
20051.54Skamil			default:
20061.54Skamil				break;
20071.54Skamil			}
20081.54Skamil			break;
20091.54Skamil		default:
20101.54Skamil			break;
20111.54Skamil		}
20121.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20131.54Skamil		switch (operation) {
20141.54Skamil		case PIOD_READ_D:
20151.54Skamil		case PIOD_READ_I:
20161.54Skamil			switch (size) {
20171.54Skamil			case 8:
20181.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
20191.54Skamil				break;
20201.54Skamil			case 16:
20211.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
20221.54Skamil				break;
20231.54Skamil			case 32:
20241.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
20251.54Skamil				break;
20261.54Skamil			case 64:
20271.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
20281.54Skamil				break;
20291.54Skamil			default:
20301.54Skamil				break;
20311.54Skamil			}
20321.54Skamil			break;
20331.54Skamil		case PIOD_READ_AUXV:
20341.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
20351.54Skamil			        io.piod_len);
20361.54Skamil			ATF_REQUIRE(io.piod_len > 0);
20371.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
20381.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
20391.54Skamil				    (long long int)aip->a_type,
20401.54Skamil				    (long long int)aip->a_v);
20411.54Skamil			break;
20421.54Skamil		default:
20431.54Skamil			break;
20441.54Skamil		}
20451.54Skamil		break;
20461.54Skamil	case BYTES_TRANSFER_TEXT:
20471.54Skamil		switch (operation) {
20481.54Skamil		case PT_READ_D:
20491.54Skamil		case PT_READ_I:
20501.54Skamil			errno = 0;
20511.54Skamil			lookup_me = ptrace(operation, child,
20521.54Skamil			                   bytes_transfer_dummy, 0);
20531.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
20541.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
20551.54Skamil			break;
20561.54Skamil		case PT_WRITE_D:
20571.54Skamil		case PT_WRITE_I:
20581.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
20591.54Skamil			                       bytes_transfer_dummy, magic)
20601.54Skamil			                != -1);
20611.54Skamil			break;
20621.54Skamil		default:
20631.54Skamil			break;
20641.54Skamil		}
20651.54Skamil		break;
20661.54Skamil	case BYTES_TRANSFER_DATA:
20671.54Skamil		switch (operation) {
20681.54Skamil		case PT_READ_D:
20691.54Skamil		case PT_READ_I:
20701.54Skamil			errno = 0;
20711.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
20721.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
20731.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
20741.54Skamil			break;
20751.54Skamil		case PT_WRITE_D:
20761.54Skamil		case PT_WRITE_I:
20771.54Skamil			lookup_me = magic;
20781.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
20791.54Skamil			                       magic) != -1);
20801.54Skamil			break;
20811.54Skamil		default:
20821.54Skamil			break;
20831.54Skamil		}
20841.54Skamil		break;
20851.54Skamil	default:
20861.54Skamil		break;
20871.54Skamil	}
20881.1Skamil
20891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20901.1Skamil	    "without signal to be sent\n");
20911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20921.1Skamil
20931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20951.1Skamil
20961.1Skamil	validate_status_exited(status, exitval);
20971.1Skamil
20981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21001.1Skamil}
21011.1Skamil
21021.54Skamil#define BYTES_TRANSFER(test, operation, size, type)				\
21031.54SkamilATF_TC(test);									\
21041.54SkamilATF_TC_HEAD(test, tc)								\
21051.54Skamil{										\
21061.54Skamil	atf_tc_set_md_var(tc, "descr",						\
21071.54Skamil	    "Verify bytes transfer operation" #operation " and size " #size	\
21081.54Skamil	    " of type " #type);							\
21091.54Skamil}										\
21101.54Skamil										\
21111.54SkamilATF_TC_BODY(test, tc)								\
21121.54Skamil{										\
21131.54Skamil										\
21141.54Skamil	bytes_transfer(operation, size, BYTES_TRANSFER_##type);			\
21151.1Skamil}
21161.1Skamil
21171.54Skamil// DATA
21181.1Skamil
21191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
21201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
21211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
21221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
21231.54Skamil
21241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
21251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
21261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
21271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
21281.54Skamil
21291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
21301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
21311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
21321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
21331.54Skamil
21341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
21351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
21361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
21371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
21381.54Skamil
21391.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
21401.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
21411.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
21421.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
21431.54Skamil
21441.54Skamil// TEXT
21451.54Skamil
21461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
21471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
21481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
21491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
21501.54Skamil
21511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
21521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
21531.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
21541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
21551.54Skamil
21561.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
21571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
21581.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
21591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
21601.54Skamil
21611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
21621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
21631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
21641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
21651.54Skamil
21661.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
21671.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
21681.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
21691.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
21701.1Skamil
21711.54Skamil// AUXV
21721.1Skamil
21731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
21741.1Skamil
21751.54Skamil/// ----------------------------------------------------------------------------
21761.1Skamil
21771.1Skamil#if defined(HAVE_GPREGS)
21781.1SkamilATF_TC(regs1);
21791.1SkamilATF_TC_HEAD(regs1, tc)
21801.1Skamil{
21811.1Skamil	atf_tc_set_md_var(tc, "descr",
21821.1Skamil	    "Verify plain PT_GETREGS call without further steps");
21831.1Skamil}
21841.1Skamil
21851.1SkamilATF_TC_BODY(regs1, tc)
21861.1Skamil{
21871.1Skamil	const int exitval = 5;
21881.1Skamil	const int sigval = SIGSTOP;
21891.1Skamil	pid_t child, wpid;
21901.1Skamil#if defined(TWAIT_HAVE_STATUS)
21911.1Skamil	int status;
21921.1Skamil#endif
21931.1Skamil	struct reg r;
21941.1Skamil
21951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21971.1Skamil	if (child == 0) {
21981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22001.1Skamil
22011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22031.1Skamil
22041.13Schristos		DPRINTF("Before exiting of the child process\n");
22051.1Skamil		_exit(exitval);
22061.1Skamil	}
22071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22081.1Skamil
22091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22111.1Skamil
22121.1Skamil	validate_status_stopped(status, sigval);
22131.1Skamil
22141.13Schristos	DPRINTF("Call GETREGS for the child process\n");
22151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
22161.1Skamil
22171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22181.1Skamil	    "without signal to be sent\n");
22191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22201.1Skamil
22211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22231.1Skamil
22241.1Skamil	validate_status_exited(status, exitval);
22251.1Skamil
22261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22281.1Skamil}
22291.1Skamil#endif
22301.1Skamil
22311.1Skamil#if defined(HAVE_GPREGS)
22321.1SkamilATF_TC(regs2);
22331.1SkamilATF_TC_HEAD(regs2, tc)
22341.1Skamil{
22351.1Skamil	atf_tc_set_md_var(tc, "descr",
22361.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
22371.1Skamil}
22381.1Skamil
22391.1SkamilATF_TC_BODY(regs2, tc)
22401.1Skamil{
22411.1Skamil	const int exitval = 5;
22421.1Skamil	const int sigval = SIGSTOP;
22431.1Skamil	pid_t child, wpid;
22441.1Skamil#if defined(TWAIT_HAVE_STATUS)
22451.1Skamil	int status;
22461.1Skamil#endif
22471.1Skamil	struct reg r;
22481.1Skamil
22491.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22501.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22511.1Skamil	if (child == 0) {
22521.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22531.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22541.1Skamil
22551.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22561.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22571.1Skamil
22581.13Schristos		DPRINTF("Before exiting of the child process\n");
22591.1Skamil		_exit(exitval);
22601.1Skamil	}
22611.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22621.1Skamil
22631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22651.1Skamil
22661.1Skamil	validate_status_stopped(status, sigval);
22671.1Skamil
22681.13Schristos	DPRINTF("Call GETREGS for the child process\n");
22691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
22701.1Skamil
22711.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
22721.1Skamil
22731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22741.1Skamil	    "without signal to be sent\n");
22751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22761.1Skamil
22771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22791.1Skamil
22801.1Skamil	validate_status_exited(status, exitval);
22811.1Skamil
22821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22841.1Skamil}
22851.1Skamil#endif
22861.1Skamil
22871.1Skamil#if defined(HAVE_GPREGS)
22881.1SkamilATF_TC(regs3);
22891.1SkamilATF_TC_HEAD(regs3, tc)
22901.1Skamil{
22911.1Skamil	atf_tc_set_md_var(tc, "descr",
22921.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
22931.1Skamil}
22941.1Skamil
22951.1SkamilATF_TC_BODY(regs3, tc)
22961.1Skamil{
22971.1Skamil	const int exitval = 5;
22981.1Skamil	const int sigval = SIGSTOP;
22991.1Skamil	pid_t child, wpid;
23001.1Skamil#if defined(TWAIT_HAVE_STATUS)
23011.1Skamil	int status;
23021.1Skamil#endif
23031.1Skamil	struct reg r;
23041.1Skamil
23051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23071.1Skamil	if (child == 0) {
23081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23101.1Skamil
23111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23131.1Skamil
23141.13Schristos		DPRINTF("Before exiting of the child process\n");
23151.1Skamil		_exit(exitval);
23161.1Skamil	}
23171.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23181.1Skamil
23191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23211.1Skamil
23221.1Skamil	validate_status_stopped(status, sigval);
23231.1Skamil
23241.13Schristos	DPRINTF("Call GETREGS for the child process\n");
23251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
23261.1Skamil
23271.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
23281.1Skamil
23291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23301.1Skamil	    "without signal to be sent\n");
23311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23321.1Skamil
23331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23351.1Skamil
23361.1Skamil	validate_status_exited(status, exitval);
23371.1Skamil
23381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23401.1Skamil}
23411.1Skamil#endif
23421.1Skamil
23431.1Skamil#if defined(HAVE_GPREGS)
23441.1SkamilATF_TC(regs4);
23451.1SkamilATF_TC_HEAD(regs4, tc)
23461.1Skamil{
23471.1Skamil	atf_tc_set_md_var(tc, "descr",
23481.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
23491.1Skamil}
23501.1Skamil
23511.1SkamilATF_TC_BODY(regs4, tc)
23521.1Skamil{
23531.1Skamil	const int exitval = 5;
23541.1Skamil	const int sigval = SIGSTOP;
23551.1Skamil	pid_t child, wpid;
23561.1Skamil#if defined(TWAIT_HAVE_STATUS)
23571.1Skamil	int status;
23581.1Skamil#endif
23591.1Skamil	struct reg r;
23601.1Skamil
23611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23631.1Skamil	if (child == 0) {
23641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23661.1Skamil
23671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23691.1Skamil
23701.13Schristos		DPRINTF("Before exiting of the child process\n");
23711.1Skamil		_exit(exitval);
23721.1Skamil	}
23731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23741.1Skamil
23751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23771.1Skamil
23781.1Skamil	validate_status_stopped(status, sigval);
23791.1Skamil
23801.13Schristos	DPRINTF("Call GETREGS for the child process\n");
23811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
23821.1Skamil
23831.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
23841.1Skamil
23851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23861.1Skamil	    "without signal to be sent\n");
23871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23881.1Skamil
23891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23911.1Skamil
23921.1Skamil	validate_status_exited(status, exitval);
23931.1Skamil
23941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23951.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23961.1Skamil}
23971.1Skamil#endif
23981.1Skamil
23991.1Skamil#if defined(HAVE_GPREGS)
24001.1SkamilATF_TC(regs5);
24011.1SkamilATF_TC_HEAD(regs5, tc)
24021.1Skamil{
24031.1Skamil	atf_tc_set_md_var(tc, "descr",
24041.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
24051.1Skamil}
24061.1Skamil
24071.1SkamilATF_TC_BODY(regs5, tc)
24081.1Skamil{
24091.1Skamil	const int exitval = 5;
24101.1Skamil	const int sigval = SIGSTOP;
24111.1Skamil	pid_t child, wpid;
24121.1Skamil#if defined(TWAIT_HAVE_STATUS)
24131.1Skamil	int status;
24141.1Skamil#endif
24151.1Skamil	struct reg r;
24161.1Skamil
24171.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24181.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24191.1Skamil	if (child == 0) {
24201.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24211.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24221.1Skamil
24231.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24241.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24251.1Skamil
24261.13Schristos		DPRINTF("Before exiting of the child process\n");
24271.1Skamil		_exit(exitval);
24281.1Skamil	}
24291.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24301.1Skamil
24311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24331.1Skamil
24341.1Skamil	validate_status_stopped(status, sigval);
24351.1Skamil
24361.13Schristos	DPRINTF("Call GETREGS for the child process\n");
24371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
24381.1Skamil
24391.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
24401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
24411.1Skamil
24421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24431.1Skamil	    "without signal to be sent\n");
24441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24451.1Skamil
24461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24481.1Skamil
24491.1Skamil	validate_status_exited(status, exitval);
24501.1Skamil
24511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24531.1Skamil}
24541.1Skamil#endif
24551.1Skamil
24561.1Skamil#if defined(HAVE_FPREGS)
24571.1SkamilATF_TC(fpregs1);
24581.1SkamilATF_TC_HEAD(fpregs1, tc)
24591.1Skamil{
24601.1Skamil	atf_tc_set_md_var(tc, "descr",
24611.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
24621.1Skamil}
24631.1Skamil
24641.1SkamilATF_TC_BODY(fpregs1, tc)
24651.1Skamil{
24661.1Skamil	const int exitval = 5;
24671.1Skamil	const int sigval = SIGSTOP;
24681.1Skamil	pid_t child, wpid;
24691.1Skamil#if defined(TWAIT_HAVE_STATUS)
24701.1Skamil	int status;
24711.1Skamil#endif
24721.1Skamil	struct fpreg r;
24731.1Skamil
24741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24761.1Skamil	if (child == 0) {
24771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24791.1Skamil
24801.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24811.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24821.1Skamil
24831.13Schristos		DPRINTF("Before exiting of the child process\n");
24841.1Skamil		_exit(exitval);
24851.1Skamil	}
24861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24871.1Skamil
24881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24901.1Skamil
24911.1Skamil	validate_status_stopped(status, sigval);
24921.1Skamil
24931.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
24941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
24951.1Skamil
24961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24971.1Skamil	    "without signal to be sent\n");
24981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24991.1Skamil
25001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25021.1Skamil
25031.1Skamil	validate_status_exited(status, exitval);
25041.1Skamil
25051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25071.1Skamil}
25081.1Skamil#endif
25091.1Skamil
25101.1Skamil#if defined(HAVE_FPREGS)
25111.1SkamilATF_TC(fpregs2);
25121.1SkamilATF_TC_HEAD(fpregs2, tc)
25131.1Skamil{
25141.1Skamil	atf_tc_set_md_var(tc, "descr",
25151.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
25161.1Skamil	    "regs");
25171.1Skamil}
25181.1Skamil
25191.1SkamilATF_TC_BODY(fpregs2, tc)
25201.1Skamil{
25211.1Skamil	const int exitval = 5;
25221.1Skamil	const int sigval = SIGSTOP;
25231.1Skamil	pid_t child, wpid;
25241.1Skamil#if defined(TWAIT_HAVE_STATUS)
25251.1Skamil	int status;
25261.1Skamil#endif
25271.1Skamil	struct fpreg r;
25281.1Skamil
25291.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25301.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25311.1Skamil	if (child == 0) {
25321.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25331.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25341.1Skamil
25351.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25361.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25371.1Skamil
25381.13Schristos		DPRINTF("Before exiting of the child process\n");
25391.1Skamil		_exit(exitval);
25401.1Skamil	}
25411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25421.1Skamil
25431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25451.1Skamil
25461.1Skamil	validate_status_stopped(status, sigval);
25471.1Skamil
25481.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
25491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
25501.1Skamil
25511.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
25521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
25531.1Skamil
25541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25551.1Skamil	    "without signal to be sent\n");
25561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25571.1Skamil
25581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25601.1Skamil
25611.1Skamil	validate_status_exited(status, exitval);
25621.1Skamil
25631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25651.1Skamil}
25661.1Skamil#endif
25671.1Skamil
25681.1Skamil#if defined(PT_STEP)
25691.1Skamilstatic void
25701.2Skamilptrace_step(int N, int setstep)
25711.1Skamil{
25721.1Skamil	const int exitval = 5;
25731.1Skamil	const int sigval = SIGSTOP;
25741.1Skamil	pid_t child, wpid;
25751.1Skamil#if defined(TWAIT_HAVE_STATUS)
25761.1Skamil	int status;
25771.1Skamil#endif
25781.1Skamil	int happy;
25791.1Skamil
25801.1Skamil#if defined(__arm__)
25811.1Skamil	/* PT_STEP not supported on arm 32-bit */
25821.1Skamil	atf_tc_expect_fail("PR kern/52119");
25831.1Skamil#endif
25841.1Skamil
25851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25871.1Skamil	if (child == 0) {
25881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25901.1Skamil
25911.1Skamil		happy = check_happy(999);
25921.1Skamil
25931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25951.1Skamil
25961.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
25971.1Skamil
25981.13Schristos		DPRINTF("Before exiting of the child process\n");
25991.1Skamil		_exit(exitval);
26001.1Skamil	}
26011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26021.1Skamil
26031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26051.1Skamil
26061.1Skamil	validate_status_stopped(status, sigval);
26071.1Skamil
26081.1Skamil	while (N --> 0) {
26091.2Skamil		if (setstep) {
26101.13Schristos			DPRINTF("Before resuming the child process where it "
26111.2Skamil			    "left off and without signal to be sent (use "
26121.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
26131.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
26141.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
26151.2Skamil			    != -1);
26161.2Skamil		} else {
26171.13Schristos			DPRINTF("Before resuming the child process where it "
26181.2Skamil			    "left off and without signal to be sent (use "
26191.2Skamil			    "PT_STEP)\n");
26201.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
26211.2Skamil			    != -1);
26221.2Skamil		}
26231.1Skamil
26241.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26251.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
26261.1Skamil		    child);
26271.1Skamil
26281.1Skamil		validate_status_stopped(status, SIGTRAP);
26291.2Skamil
26301.2Skamil		if (setstep) {
26311.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
26321.2Skamil		}
26331.1Skamil	}
26341.1Skamil
26351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26361.1Skamil	    "without signal to be sent\n");
26371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26381.1Skamil
26391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26411.1Skamil
26421.1Skamil	validate_status_exited(status, exitval);
26431.1Skamil
26441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26461.1Skamil}
26471.1Skamil#endif
26481.1Skamil
26491.1Skamil#if defined(PT_STEP)
26501.1SkamilATF_TC(step1);
26511.1SkamilATF_TC_HEAD(step1, tc)
26521.1Skamil{
26531.1Skamil	atf_tc_set_md_var(tc, "descr",
26541.1Skamil	    "Verify single PT_STEP call");
26551.1Skamil}
26561.1Skamil
26571.1SkamilATF_TC_BODY(step1, tc)
26581.1Skamil{
26591.2Skamil	ptrace_step(1, 0);
26601.1Skamil}
26611.1Skamil#endif
26621.1Skamil
26631.1Skamil#if defined(PT_STEP)
26641.1SkamilATF_TC(step2);
26651.1SkamilATF_TC_HEAD(step2, tc)
26661.1Skamil{
26671.1Skamil	atf_tc_set_md_var(tc, "descr",
26681.1Skamil	    "Verify PT_STEP called twice");
26691.1Skamil}
26701.1Skamil
26711.1SkamilATF_TC_BODY(step2, tc)
26721.1Skamil{
26731.2Skamil	ptrace_step(2, 0);
26741.1Skamil}
26751.1Skamil#endif
26761.1Skamil
26771.1Skamil#if defined(PT_STEP)
26781.1SkamilATF_TC(step3);
26791.1SkamilATF_TC_HEAD(step3, tc)
26801.1Skamil{
26811.1Skamil	atf_tc_set_md_var(tc, "descr",
26821.1Skamil	    "Verify PT_STEP called three times");
26831.1Skamil}
26841.1Skamil
26851.1SkamilATF_TC_BODY(step3, tc)
26861.1Skamil{
26871.2Skamil	ptrace_step(3, 0);
26881.1Skamil}
26891.1Skamil#endif
26901.1Skamil
26911.1Skamil#if defined(PT_STEP)
26921.1SkamilATF_TC(step4);
26931.1SkamilATF_TC_HEAD(step4, tc)
26941.1Skamil{
26951.1Skamil	atf_tc_set_md_var(tc, "descr",
26961.1Skamil	    "Verify PT_STEP called four times");
26971.1Skamil}
26981.1Skamil
26991.1SkamilATF_TC_BODY(step4, tc)
27001.1Skamil{
27011.2Skamil	ptrace_step(4, 0);
27021.2Skamil}
27031.2Skamil#endif
27041.2Skamil
27051.2Skamil#if defined(PT_STEP)
27061.2SkamilATF_TC(setstep1);
27071.2SkamilATF_TC_HEAD(setstep1, tc)
27081.2Skamil{
27091.2Skamil	atf_tc_set_md_var(tc, "descr",
27101.2Skamil	    "Verify single PT_SETSTEP call");
27111.2Skamil}
27121.2Skamil
27131.2SkamilATF_TC_BODY(setstep1, tc)
27141.2Skamil{
27151.2Skamil	ptrace_step(1, 1);
27161.2Skamil}
27171.2Skamil#endif
27181.2Skamil
27191.2Skamil#if defined(PT_STEP)
27201.2SkamilATF_TC(setstep2);
27211.2SkamilATF_TC_HEAD(setstep2, tc)
27221.2Skamil{
27231.2Skamil	atf_tc_set_md_var(tc, "descr",
27241.2Skamil	    "Verify PT_SETSTEP called twice");
27251.2Skamil}
27261.2Skamil
27271.2SkamilATF_TC_BODY(setstep2, tc)
27281.2Skamil{
27291.2Skamil	ptrace_step(2, 1);
27301.2Skamil}
27311.2Skamil#endif
27321.2Skamil
27331.2Skamil#if defined(PT_STEP)
27341.2SkamilATF_TC(setstep3);
27351.2SkamilATF_TC_HEAD(setstep3, tc)
27361.2Skamil{
27371.2Skamil	atf_tc_set_md_var(tc, "descr",
27381.2Skamil	    "Verify PT_SETSTEP called three times");
27391.2Skamil}
27401.2Skamil
27411.2SkamilATF_TC_BODY(setstep3, tc)
27421.2Skamil{
27431.2Skamil	ptrace_step(3, 1);
27441.2Skamil}
27451.2Skamil#endif
27461.2Skamil
27471.2Skamil#if defined(PT_STEP)
27481.2SkamilATF_TC(setstep4);
27491.2SkamilATF_TC_HEAD(setstep4, tc)
27501.2Skamil{
27511.2Skamil	atf_tc_set_md_var(tc, "descr",
27521.2Skamil	    "Verify PT_SETSTEP called four times");
27531.2Skamil}
27541.2Skamil
27551.2SkamilATF_TC_BODY(setstep4, tc)
27561.2Skamil{
27571.2Skamil	ptrace_step(4, 1);
27581.1Skamil}
27591.1Skamil#endif
27601.1Skamil
27611.1SkamilATF_TC(kill1);
27621.1SkamilATF_TC_HEAD(kill1, tc)
27631.1Skamil{
27641.1Skamil	atf_tc_set_md_var(tc, "descr",
27651.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
27661.1Skamil}
27671.1Skamil
27681.1SkamilATF_TC_BODY(kill1, tc)
27691.1Skamil{
27701.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
27711.1Skamil	pid_t child, wpid;
27721.1Skamil#if defined(TWAIT_HAVE_STATUS)
27731.1Skamil	int status;
27741.1Skamil#endif
27751.1Skamil
27761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27781.1Skamil	if (child == 0) {
27791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27811.1Skamil
27821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27841.1Skamil
27851.1Skamil		/* NOTREACHED */
27861.1Skamil		FORKEE_ASSERTX(0 &&
27871.1Skamil		    "Child should be terminated by a signal from its parent");
27881.1Skamil	}
27891.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27901.1Skamil
27911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27931.1Skamil
27941.1Skamil	validate_status_stopped(status, sigval);
27951.1Skamil
27961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27971.1Skamil	    "without signal to be sent\n");
27981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
27991.1Skamil
28001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28021.1Skamil
28031.1Skamil	validate_status_signaled(status, sigsent, 0);
28041.1Skamil
28051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28071.1Skamil}
28081.1Skamil
28091.1SkamilATF_TC(kill2);
28101.1SkamilATF_TC_HEAD(kill2, tc)
28111.1Skamil{
28121.1Skamil	atf_tc_set_md_var(tc, "descr",
28131.1Skamil	    "Verify that PT_KILL terminates child");
28141.1Skamil}
28151.1Skamil
28161.1SkamilATF_TC_BODY(kill2, tc)
28171.1Skamil{
28181.1Skamil	const int sigval = SIGSTOP;
28191.1Skamil	pid_t child, wpid;
28201.1Skamil#if defined(TWAIT_HAVE_STATUS)
28211.1Skamil	int status;
28221.1Skamil#endif
28231.1Skamil
28241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28261.1Skamil	if (child == 0) {
28271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28291.1Skamil
28301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28321.1Skamil
28331.1Skamil		/* NOTREACHED */
28341.1Skamil		FORKEE_ASSERTX(0 &&
28351.1Skamil		    "Child should be terminated by a signal from its parent");
28361.1Skamil	}
28371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28381.1Skamil
28391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28411.1Skamil
28421.1Skamil	validate_status_stopped(status, sigval);
28431.1Skamil
28441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28451.1Skamil	    "without signal to be sent\n");
28461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
28471.1Skamil
28481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28501.1Skamil
28511.1Skamil	validate_status_signaled(status, SIGKILL, 0);
28521.1Skamil
28531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28551.1Skamil}
28561.1Skamil
28571.1SkamilATF_TC(lwpinfo1);
28581.1SkamilATF_TC_HEAD(lwpinfo1, tc)
28591.1Skamil{
28601.1Skamil	atf_tc_set_md_var(tc, "descr",
28611.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
28621.1Skamil}
28631.1Skamil
28641.1SkamilATF_TC_BODY(lwpinfo1, tc)
28651.1Skamil{
28661.1Skamil	const int exitval = 5;
28671.1Skamil	const int sigval = SIGSTOP;
28681.1Skamil	pid_t child, wpid;
28691.1Skamil#if defined(TWAIT_HAVE_STATUS)
28701.1Skamil	int status;
28711.1Skamil#endif
28721.1Skamil	struct ptrace_lwpinfo info = {0, 0};
28731.1Skamil
28741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28761.1Skamil	if (child == 0) {
28771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28791.1Skamil
28801.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28811.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28821.1Skamil
28831.13Schristos		DPRINTF("Before exiting of the child process\n");
28841.1Skamil		_exit(exitval);
28851.1Skamil	}
28861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28871.1Skamil
28881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28901.1Skamil
28911.1Skamil	validate_status_stopped(status, sigval);
28921.1Skamil
28931.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
28941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
28951.1Skamil
28961.13Schristos	DPRINTF("Assert that there exists a thread\n");
28971.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
28981.1Skamil
28991.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
29001.1Skamil	    info.pl_lwpid);
29011.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
29021.1Skamil	    "Received event %d != expected event %d",
29031.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
29041.1Skamil
29051.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
29061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
29071.1Skamil
29081.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
29091.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
29101.1Skamil
29111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29121.1Skamil	    "without signal to be sent\n");
29131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29141.1Skamil
29151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29171.1Skamil
29181.1Skamil	validate_status_exited(status, exitval);
29191.1Skamil
29201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29221.1Skamil}
29231.1Skamil
29241.1Skamil#if defined(TWAIT_HAVE_PID)
29251.1SkamilATF_TC(lwpinfo2);
29261.1SkamilATF_TC_HEAD(lwpinfo2, tc)
29271.1Skamil{
29281.1Skamil	atf_tc_set_md_var(tc, "descr",
29291.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
29301.1Skamil	    "tracer)");
29311.1Skamil}
29321.1Skamil
29331.1SkamilATF_TC_BODY(lwpinfo2, tc)
29341.1Skamil{
29351.1Skamil	struct msg_fds parent_tracee, parent_tracer;
29361.1Skamil	const int exitval_tracee = 5;
29371.1Skamil	const int exitval_tracer = 10;
29381.1Skamil	pid_t tracee, tracer, wpid;
29391.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
29401.1Skamil#if defined(TWAIT_HAVE_STATUS)
29411.1Skamil	int status;
29421.1Skamil#endif
29431.1Skamil	struct ptrace_lwpinfo info = {0, 0};
29441.1Skamil
29451.13Schristos	DPRINTF("Spawn tracee\n");
29461.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
29471.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
29481.1Skamil	tracee = atf_utils_fork();
29491.1Skamil	if (tracee == 0) {
29501.1Skamil
29511.1Skamil		/* Wait for message from the parent */
29521.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
29531.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
29541.1Skamil
29551.1Skamil		_exit(exitval_tracee);
29561.1Skamil	}
29571.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
29581.1Skamil
29591.13Schristos	DPRINTF("Spawn debugger\n");
29601.1Skamil	tracer = atf_utils_fork();
29611.1Skamil	if (tracer == 0) {
29621.1Skamil		/* No IPC to communicate with the child */
29631.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
29641.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
29651.1Skamil
29661.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
29671.1Skamil		FORKEE_REQUIRE_SUCCESS(
29681.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
29691.1Skamil
29701.1Skamil		forkee_status_stopped(status, SIGSTOP);
29711.1Skamil
29721.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
29731.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
29741.1Skamil		    != -1);
29751.1Skamil
29761.13Schristos		DPRINTF("Assert that there exists a thread\n");
29771.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
29781.1Skamil
29791.13Schristos		DPRINTF("Assert that lwp thread %d received event "
29801.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
29811.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
29821.1Skamil
29831.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
29841.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
29851.1Skamil		    != -1);
29861.1Skamil
29871.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
29881.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
29891.1Skamil
29901.1Skamil		/* Resume tracee with PT_CONTINUE */
29911.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
29921.1Skamil
29931.1Skamil		/* Inform parent that tracer has attached to tracee */
29941.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
29951.1Skamil		/* Wait for parent */
29961.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
29971.1Skamil
29981.1Skamil		/* Wait for tracee and assert that it exited */
29991.1Skamil		FORKEE_REQUIRE_SUCCESS(
30001.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
30011.1Skamil
30021.1Skamil		forkee_status_exited(status, exitval_tracee);
30031.1Skamil
30041.13Schristos		DPRINTF("Before exiting of the tracer process\n");
30051.1Skamil		_exit(exitval_tracer);
30061.1Skamil	}
30071.1Skamil
30081.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
30091.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
30101.1Skamil
30111.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
30121.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
30131.1Skamil
30141.13Schristos	DPRINTF("Detect that tracee is zombie\n");
30151.1Skamil	await_zombie(tracee);
30161.1Skamil
30171.13Schristos	DPRINTF("Assert that there is no status about tracee - "
30181.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
30191.1Skamil	TWAIT_REQUIRE_SUCCESS(
30201.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
30211.1Skamil
30221.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
30231.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
30241.1Skamil
30251.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
30261.1Skamil	    TWAIT_FNAME);
30271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
30281.1Skamil	    tracer);
30291.1Skamil
30301.1Skamil	validate_status_exited(status, exitval_tracer);
30311.1Skamil
30321.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
30331.1Skamil	    TWAIT_FNAME);
30341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
30351.1Skamil	    tracee);
30361.1Skamil
30371.1Skamil	validate_status_exited(status, exitval_tracee);
30381.1Skamil
30391.1Skamil	msg_close(&parent_tracer);
30401.1Skamil	msg_close(&parent_tracee);
30411.1Skamil}
30421.1Skamil#endif
30431.1Skamil
30441.1SkamilATF_TC(siginfo1);
30451.1SkamilATF_TC_HEAD(siginfo1, tc)
30461.1Skamil{
30471.1Skamil	atf_tc_set_md_var(tc, "descr",
30481.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
30491.1Skamil}
30501.1Skamil
30511.1SkamilATF_TC_BODY(siginfo1, tc)
30521.1Skamil{
30531.1Skamil	const int exitval = 5;
30541.1Skamil	const int sigval = SIGTRAP;
30551.1Skamil	pid_t child, wpid;
30561.1Skamil#if defined(TWAIT_HAVE_STATUS)
30571.1Skamil	int status;
30581.1Skamil#endif
30591.1Skamil	struct ptrace_siginfo info;
30601.1Skamil	memset(&info, 0, sizeof(info));
30611.1Skamil
30621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30641.1Skamil	if (child == 0) {
30651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30671.1Skamil
30681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30701.1Skamil
30711.13Schristos		DPRINTF("Before exiting of the child process\n");
30721.1Skamil		_exit(exitval);
30731.1Skamil	}
30741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30751.1Skamil
30761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30781.1Skamil
30791.1Skamil	validate_status_stopped(status, sigval);
30801.1Skamil
30811.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
30821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
30831.1Skamil
30841.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
30851.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
30861.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
30871.1Skamil	    info.psi_siginfo.si_errno);
30881.1Skamil
30891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30901.1Skamil	    "without signal to be sent\n");
30911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30921.1Skamil
30931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30951.1Skamil
30961.1Skamil	validate_status_exited(status, exitval);
30971.1Skamil
30981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31001.1Skamil}
31011.1Skamil
31021.1SkamilATF_TC(siginfo2);
31031.1SkamilATF_TC_HEAD(siginfo2, tc)
31041.1Skamil{
31051.1Skamil	atf_tc_set_md_var(tc, "descr",
31061.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
31071.1Skamil	    "modification of SIGINT from tracee");
31081.1Skamil}
31091.1Skamil
31101.1Skamilstatic int siginfo2_caught = 0;
31111.1Skamil
31121.1Skamilstatic void
31131.1Skamilsiginfo2_sighandler(int sig)
31141.1Skamil{
31151.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
31161.1Skamil
31171.1Skamil	++siginfo2_caught;
31181.1Skamil}
31191.1Skamil
31201.1SkamilATF_TC_BODY(siginfo2, tc)
31211.1Skamil{
31221.1Skamil	const int exitval = 5;
31231.1Skamil	const int sigval = SIGINT;
31241.1Skamil	pid_t child, wpid;
31251.1Skamil	struct sigaction sa;
31261.1Skamil#if defined(TWAIT_HAVE_STATUS)
31271.1Skamil	int status;
31281.1Skamil#endif
31291.1Skamil	struct ptrace_siginfo info;
31301.1Skamil	memset(&info, 0, sizeof(info));
31311.1Skamil
31321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31341.1Skamil	if (child == 0) {
31351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31371.1Skamil
31381.1Skamil		sa.sa_handler = siginfo2_sighandler;
31391.1Skamil		sa.sa_flags = SA_SIGINFO;
31401.1Skamil		sigemptyset(&sa.sa_mask);
31411.1Skamil
31421.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
31431.1Skamil
31441.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31451.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31461.1Skamil
31471.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
31481.1Skamil
31491.13Schristos		DPRINTF("Before exiting of the child process\n");
31501.1Skamil		_exit(exitval);
31511.1Skamil	}
31521.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31531.1Skamil
31541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31561.1Skamil
31571.1Skamil	validate_status_stopped(status, sigval);
31581.1Skamil
31591.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
31601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
31611.1Skamil
31621.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
31631.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
31641.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
31651.1Skamil	    info.psi_siginfo.si_errno);
31661.1Skamil
31671.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
31681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
31691.1Skamil
31701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31711.1Skamil	    "without signal to be sent\n");
31721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
31731.1Skamil
31741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31761.1Skamil
31771.1Skamil	validate_status_exited(status, exitval);
31781.1Skamil
31791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31811.1Skamil}
31821.1Skamil
31831.1SkamilATF_TC(siginfo3);
31841.1SkamilATF_TC_HEAD(siginfo3, tc)
31851.1Skamil{
31861.1Skamil	atf_tc_set_md_var(tc, "descr",
31871.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
31881.1Skamil	    "setting signal to new value");
31891.1Skamil}
31901.1Skamil
31911.1Skamilstatic int siginfo3_caught = 0;
31921.1Skamil
31931.1Skamilstatic void
31941.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
31951.1Skamil{
31961.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
31971.1Skamil
31981.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
31991.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
32001.1Skamil
32011.1Skamil	++siginfo3_caught;
32021.1Skamil}
32031.1Skamil
32041.1SkamilATF_TC_BODY(siginfo3, tc)
32051.1Skamil{
32061.1Skamil	const int exitval = 5;
32071.1Skamil	const int sigval = SIGINT;
32081.1Skamil	const int sigfaked = SIGTRAP;
32091.1Skamil	const int sicodefaked = TRAP_BRKPT;
32101.1Skamil	pid_t child, wpid;
32111.1Skamil	struct sigaction sa;
32121.1Skamil#if defined(TWAIT_HAVE_STATUS)
32131.1Skamil	int status;
32141.1Skamil#endif
32151.1Skamil	struct ptrace_siginfo info;
32161.1Skamil	memset(&info, 0, sizeof(info));
32171.1Skamil
32181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32201.1Skamil	if (child == 0) {
32211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32231.1Skamil
32241.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
32251.1Skamil		sa.sa_flags = SA_SIGINFO;
32261.1Skamil		sigemptyset(&sa.sa_mask);
32271.1Skamil
32281.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
32291.1Skamil
32301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32321.1Skamil
32331.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
32341.1Skamil
32351.13Schristos		DPRINTF("Before exiting of the child process\n");
32361.1Skamil		_exit(exitval);
32371.1Skamil	}
32381.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32391.1Skamil
32401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32421.1Skamil
32431.1Skamil	validate_status_stopped(status, sigval);
32441.1Skamil
32451.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
32461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
32471.1Skamil
32481.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
32491.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
32501.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
32511.1Skamil	    info.psi_siginfo.si_errno);
32521.1Skamil
32531.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
32541.1Skamil	    sigfaked, sicodefaked);
32551.1Skamil	info.psi_siginfo.si_signo = sigfaked;
32561.1Skamil	info.psi_siginfo.si_code = sicodefaked;
32571.1Skamil
32581.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
32591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
32601.1Skamil
32611.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
32621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
32631.1Skamil
32641.13Schristos	DPRINTF("Before checking siginfo_t\n");
32651.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
32661.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
32671.1Skamil
32681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32691.1Skamil	    "without signal to be sent\n");
32701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
32711.1Skamil
32721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32741.1Skamil
32751.1Skamil	validate_status_exited(status, exitval);
32761.1Skamil
32771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32791.1Skamil}
32801.1Skamil
32811.1SkamilATF_TC(siginfo4);
32821.1SkamilATF_TC_HEAD(siginfo4, tc)
32831.1Skamil{
32841.1Skamil	atf_tc_set_md_var(tc, "descr",
32851.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
32861.1Skamil}
32871.1Skamil
32881.1SkamilATF_TC_BODY(siginfo4, tc)
32891.1Skamil{
32901.1Skamil	const int sigval = SIGTRAP;
32911.1Skamil	pid_t child, wpid;
32921.1Skamil#if defined(TWAIT_HAVE_STATUS)
32931.1Skamil	int status;
32941.1Skamil#endif
32951.1Skamil
32961.1Skamil	struct ptrace_siginfo info;
32971.1Skamil	memset(&info, 0, sizeof(info));
32981.1Skamil
32991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33011.1Skamil	if (child == 0) {
33021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33041.1Skamil
33051.13Schristos		DPRINTF("Before calling execve(2) from child\n");
33061.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
33071.1Skamil
33081.1Skamil		FORKEE_ASSERT(0 && "Not reached");
33091.1Skamil	}
33101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33111.1Skamil
33121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33141.1Skamil
33151.1Skamil	validate_status_stopped(status, sigval);
33161.1Skamil
33171.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
33181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
33191.1Skamil
33201.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
33211.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
33221.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
33231.1Skamil	    info.psi_siginfo.si_errno);
33241.1Skamil
33251.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
33261.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
33271.1Skamil
33281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33291.1Skamil	    "without signal to be sent\n");
33301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33311.1Skamil
33321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33341.1Skamil
33351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33371.1Skamil}
33381.1Skamil
33391.1Skamil#if defined(TWAIT_HAVE_PID)
33401.1SkamilATF_TC(siginfo5);
33411.1SkamilATF_TC_HEAD(siginfo5, tc)
33421.1Skamil{
33431.1Skamil	atf_tc_set_md_var(tc, "descr",
33441.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
33451.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
33461.1Skamil}
33471.1Skamil
33481.1SkamilATF_TC_BODY(siginfo5, tc)
33491.1Skamil{
33501.1Skamil	const int exitval = 5;
33511.1Skamil	const int exitval2 = 15;
33521.1Skamil	const int sigval = SIGSTOP;
33531.1Skamil	pid_t child, child2, wpid;
33541.1Skamil#if defined(TWAIT_HAVE_STATUS)
33551.1Skamil	int status;
33561.1Skamil#endif
33571.1Skamil	ptrace_state_t state;
33581.1Skamil	const int slen = sizeof(state);
33591.1Skamil	ptrace_event_t event;
33601.1Skamil	const int elen = sizeof(event);
33611.1Skamil	struct ptrace_siginfo info;
33621.1Skamil
33631.1Skamil	memset(&info, 0, sizeof(info));
33641.1Skamil
33651.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33661.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33671.1Skamil	if (child == 0) {
33681.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33691.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33701.1Skamil
33711.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33721.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33731.1Skamil
33741.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
33751.1Skamil
33761.1Skamil		if (child2 == 0)
33771.1Skamil			_exit(exitval2);
33781.1Skamil
33791.1Skamil		FORKEE_REQUIRE_SUCCESS
33801.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
33811.1Skamil
33821.1Skamil		forkee_status_exited(status, exitval2);
33831.1Skamil
33841.13Schristos		DPRINTF("Before exiting of the child process\n");
33851.1Skamil		_exit(exitval);
33861.1Skamil	}
33871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33881.1Skamil
33891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33911.1Skamil
33921.1Skamil	validate_status_stopped(status, sigval);
33931.1Skamil
33941.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
33951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
33961.1Skamil
33971.13Schristos	DPRINTF("Before checking siginfo_t\n");
33981.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
33991.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
34001.1Skamil
34011.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
34021.1Skamil	event.pe_set_event = PTRACE_FORK;
34031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
34041.1Skamil
34051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34061.1Skamil	    "without signal to be sent\n");
34071.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
34081.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
34091.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
34101.1Skamil                "state.pe_other_pid=child)\n", child);
34111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34121.1Skamil
34131.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
34141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34151.1Skamil
34161.1Skamil	validate_status_stopped(status, SIGTRAP);
34171.1Skamil
34181.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
34191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
34201.1Skamil
34211.13Schristos	DPRINTF("Before checking siginfo_t\n");
34221.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
34231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
34241.1Skamil
34251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
34261.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
34271.1Skamil
34281.1Skamil	child2 = state.pe_other_pid;
34291.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
34301.1Skamil
34311.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
34321.1Skamil	    TWAIT_FNAME, child2, child);
34331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
34341.1Skamil	    child2);
34351.1Skamil
34361.1Skamil	validate_status_stopped(status, SIGTRAP);
34371.1Skamil
34381.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
34391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
34401.1Skamil
34411.13Schristos	DPRINTF("Before checking siginfo_t\n");
34421.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
34431.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
34441.1Skamil
34451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
34461.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
34471.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
34481.1Skamil
34491.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
34501.1Skamil	    "without signal to be sent\n");
34511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
34521.1Skamil
34531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34541.1Skamil	    "without signal to be sent\n");
34551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34561.1Skamil
34571.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
34581.1Skamil	    TWAIT_FNAME);
34591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
34601.1Skamil	    child2);
34611.1Skamil
34621.1Skamil	validate_status_exited(status, exitval2);
34631.1Skamil
34641.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
34651.1Skamil	    TWAIT_FNAME);
34661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
34671.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
34681.1Skamil
34691.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
34701.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
34711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34721.1Skamil
34731.1Skamil	validate_status_stopped(status, SIGCHLD);
34741.1Skamil
34751.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
34761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
34771.1Skamil
34781.13Schristos	DPRINTF("Before checking siginfo_t\n");
34791.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
34801.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
34811.1Skamil
34821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34831.1Skamil	    "without signal to be sent\n");
34841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34851.1Skamil
34861.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
34871.1Skamil	    TWAIT_FNAME);
34881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34891.1Skamil
34901.1Skamil	validate_status_exited(status, exitval);
34911.1Skamil
34921.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
34931.1Skamil	    TWAIT_FNAME);
34941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34951.1Skamil}
34961.1Skamil#endif
34971.1Skamil
34981.1Skamil#if defined(PT_STEP)
34991.1SkamilATF_TC(siginfo6);
35001.1SkamilATF_TC_HEAD(siginfo6, tc)
35011.1Skamil{
35021.1Skamil	atf_tc_set_md_var(tc, "descr",
35031.1Skamil	    "Verify single PT_STEP call with signal information check");
35041.1Skamil}
35051.1Skamil
35061.1SkamilATF_TC_BODY(siginfo6, tc)
35071.1Skamil{
35081.1Skamil	const int exitval = 5;
35091.1Skamil	const int sigval = SIGSTOP;
35101.1Skamil	pid_t child, wpid;
35111.1Skamil#if defined(TWAIT_HAVE_STATUS)
35121.1Skamil	int status;
35131.1Skamil#endif
35141.1Skamil	int happy;
35151.1Skamil	struct ptrace_siginfo info;
35161.1Skamil
35171.1Skamil#if defined(__arm__)
35181.1Skamil	/* PT_STEP not supported on arm 32-bit */
35191.1Skamil	atf_tc_expect_fail("PR kern/52119");
35201.1Skamil#endif
35211.1Skamil
35221.1Skamil	memset(&info, 0, sizeof(info));
35231.1Skamil
35241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35261.1Skamil	if (child == 0) {
35271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35291.1Skamil
35301.1Skamil		happy = check_happy(100);
35311.1Skamil
35321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35341.1Skamil
35351.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
35361.1Skamil
35371.13Schristos		DPRINTF("Before exiting of the child process\n");
35381.1Skamil		_exit(exitval);
35391.1Skamil	}
35401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35411.1Skamil
35421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35441.1Skamil
35451.1Skamil	validate_status_stopped(status, sigval);
35461.1Skamil
35471.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35491.1Skamil
35501.13Schristos	DPRINTF("Before checking siginfo_t\n");
35511.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
35521.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
35531.1Skamil
35541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35551.1Skamil	    "without signal to be sent (use PT_STEP)\n");
35561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
35571.1Skamil
35581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35601.1Skamil
35611.1Skamil	validate_status_stopped(status, SIGTRAP);
35621.1Skamil
35631.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35651.1Skamil
35661.13Schristos	DPRINTF("Before checking siginfo_t\n");
35671.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
35681.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
35691.1Skamil
35701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35711.1Skamil	    "without signal to be sent\n");
35721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35731.1Skamil
35741.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35761.1Skamil
35771.1Skamil	validate_status_exited(status, exitval);
35781.1Skamil
35791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35811.1Skamil}
35821.1Skamil#endif
35831.1Skamil
35841.1Skamilvolatile lwpid_t the_lwp_id = 0;
35851.1Skamil
35861.1Skamilstatic void
35871.1Skamillwp_main_func(void *arg)
35881.1Skamil{
35891.1Skamil	the_lwp_id = _lwp_self();
35901.1Skamil	_lwp_exit();
35911.1Skamil}
35921.1Skamil
35931.1SkamilATF_TC(lwp_create1);
35941.1SkamilATF_TC_HEAD(lwp_create1, tc)
35951.1Skamil{
35961.1Skamil	atf_tc_set_md_var(tc, "descr",
35971.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
35981.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
35991.1Skamil}
36001.1Skamil
36011.1SkamilATF_TC_BODY(lwp_create1, tc)
36021.1Skamil{
36031.1Skamil	const int exitval = 5;
36041.1Skamil	const int sigval = SIGSTOP;
36051.1Skamil	pid_t child, wpid;
36061.1Skamil#if defined(TWAIT_HAVE_STATUS)
36071.1Skamil	int status;
36081.1Skamil#endif
36091.1Skamil	ptrace_state_t state;
36101.1Skamil	const int slen = sizeof(state);
36111.1Skamil	ptrace_event_t event;
36121.1Skamil	const int elen = sizeof(event);
36131.1Skamil	ucontext_t uc;
36141.1Skamil	lwpid_t lid;
36151.1Skamil	static const size_t ssize = 16*1024;
36161.1Skamil	void *stack;
36171.1Skamil
36181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36201.1Skamil	if (child == 0) {
36211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36231.1Skamil
36241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36261.1Skamil
36271.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
36281.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
36291.1Skamil
36301.13Schristos		DPRINTF("Before making context for new lwp in child\n");
36311.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
36321.1Skamil
36331.13Schristos		DPRINTF("Before creating new in child\n");
36341.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
36351.1Skamil
36361.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
36371.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
36381.1Skamil
36391.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
36401.1Skamil		    "are the same\n", lid, the_lwp_id);
36411.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
36421.1Skamil
36431.13Schristos		DPRINTF("Before exiting of the child process\n");
36441.1Skamil		_exit(exitval);
36451.1Skamil	}
36461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36471.1Skamil
36481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36501.1Skamil
36511.1Skamil	validate_status_stopped(status, sigval);
36521.1Skamil
36531.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
36541.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
36551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
36561.1Skamil
36571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36581.1Skamil	    "without signal to be sent\n");
36591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36601.1Skamil
36611.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
36621.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
36631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36641.1Skamil
36651.1Skamil	validate_status_stopped(status, SIGTRAP);
36661.1Skamil
36671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
36681.1Skamil
36691.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
36701.1Skamil
36711.1Skamil	lid = state.pe_lwp;
36721.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
36731.1Skamil
36741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36751.1Skamil	    "without signal to be sent\n");
36761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36771.1Skamil
36781.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
36791.1Skamil	    TWAIT_FNAME);
36801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36811.1Skamil
36821.1Skamil	validate_status_exited(status, exitval);
36831.1Skamil
36841.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
36851.1Skamil	    TWAIT_FNAME);
36861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36871.1Skamil}
36881.1Skamil
36891.1SkamilATF_TC(lwp_exit1);
36901.1SkamilATF_TC_HEAD(lwp_exit1, tc)
36911.1Skamil{
36921.1Skamil	atf_tc_set_md_var(tc, "descr",
36931.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
36941.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
36951.1Skamil}
36961.1Skamil
36971.1SkamilATF_TC_BODY(lwp_exit1, tc)
36981.1Skamil{
36991.1Skamil	const int exitval = 5;
37001.1Skamil	const int sigval = SIGSTOP;
37011.1Skamil	pid_t child, wpid;
37021.1Skamil#if defined(TWAIT_HAVE_STATUS)
37031.1Skamil	int status;
37041.1Skamil#endif
37051.1Skamil	ptrace_state_t state;
37061.1Skamil	const int slen = sizeof(state);
37071.1Skamil	ptrace_event_t event;
37081.1Skamil	const int elen = sizeof(event);
37091.1Skamil	ucontext_t uc;
37101.1Skamil	lwpid_t lid;
37111.1Skamil	static const size_t ssize = 16*1024;
37121.1Skamil	void *stack;
37131.1Skamil
37141.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37151.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37161.1Skamil	if (child == 0) {
37171.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37181.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37191.1Skamil
37201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37221.1Skamil
37231.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
37241.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
37251.1Skamil
37261.13Schristos		DPRINTF("Before making context for new lwp in child\n");
37271.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
37281.1Skamil
37291.13Schristos		DPRINTF("Before creating new in child\n");
37301.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
37311.1Skamil
37321.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
37331.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
37341.1Skamil
37351.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
37361.1Skamil		    "are the same\n", lid, the_lwp_id);
37371.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
37381.1Skamil
37391.13Schristos		DPRINTF("Before exiting of the child process\n");
37401.1Skamil		_exit(exitval);
37411.1Skamil	}
37421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37431.1Skamil
37441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37461.1Skamil
37471.1Skamil	validate_status_stopped(status, sigval);
37481.1Skamil
37491.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
37501.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
37511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
37521.1Skamil
37531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37541.1Skamil	    "without signal to be sent\n");
37551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37561.1Skamil
37571.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
37581.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
37591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37601.1Skamil
37611.1Skamil	validate_status_stopped(status, SIGTRAP);
37621.1Skamil
37631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
37641.1Skamil
37651.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
37661.1Skamil
37671.1Skamil	lid = state.pe_lwp;
37681.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
37691.1Skamil
37701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37711.1Skamil	    "without signal to be sent\n");
37721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37731.1Skamil
37741.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
37751.1Skamil	    TWAIT_FNAME);
37761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37771.1Skamil
37781.1Skamil	validate_status_exited(status, exitval);
37791.1Skamil
37801.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
37811.1Skamil	    TWAIT_FNAME);
37821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37831.1Skamil}
37841.1Skamil
37851.1SkamilATF_TC(signal1);
37861.1SkamilATF_TC_HEAD(signal1, tc)
37871.1Skamil{
37881.1Skamil	atf_tc_set_md_var(tc, "descr",
37891.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
37901.1Skamil	    "from catching other signals");
37911.1Skamil}
37921.1Skamil
37931.1SkamilATF_TC_BODY(signal1, tc)
37941.1Skamil{
37951.1Skamil	const int exitval = 5;
37961.1Skamil	const int sigval = SIGSTOP;
37971.1Skamil	const int sigmasked = SIGTRAP;
37981.1Skamil	const int signotmasked = SIGINT;
37991.1Skamil	pid_t child, wpid;
38001.1Skamil#if defined(TWAIT_HAVE_STATUS)
38011.1Skamil	int status;
38021.1Skamil#endif
38031.1Skamil	sigset_t intmask;
38041.1Skamil
38051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38071.1Skamil	if (child == 0) {
38081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38101.1Skamil
38111.1Skamil		sigemptyset(&intmask);
38121.1Skamil		sigaddset(&intmask, sigmasked);
38131.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
38141.1Skamil
38151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38171.1Skamil
38181.13Schristos		DPRINTF("Before raising %s from child\n",
38191.1Skamil		    strsignal(signotmasked));
38201.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
38211.1Skamil
38221.13Schristos		DPRINTF("Before exiting of the child process\n");
38231.1Skamil		_exit(exitval);
38241.1Skamil	}
38251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38261.1Skamil
38271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38291.1Skamil
38301.1Skamil	validate_status_stopped(status, sigval);
38311.1Skamil
38321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38331.1Skamil	    "without signal to be sent\n");
38341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38351.1Skamil
38361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38381.1Skamil
38391.1Skamil	validate_status_stopped(status, signotmasked);
38401.1Skamil
38411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38421.1Skamil	    "without signal to be sent\n");
38431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, 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_exited(status, exitval);
38491.1Skamil
38501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38521.1Skamil}
38531.1Skamil
38541.1SkamilATF_TC(signal2);
38551.1SkamilATF_TC_HEAD(signal2, tc)
38561.1Skamil{
38571.1Skamil	atf_tc_set_md_var(tc, "descr",
38581.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
38591.1Skamil	    "catching this raised signal");
38601.1Skamil}
38611.1Skamil
38621.1SkamilATF_TC_BODY(signal2, tc)
38631.1Skamil{
38641.1Skamil	const int exitval = 5;
38651.1Skamil	const int sigval = SIGSTOP;
38661.1Skamil	const int sigmasked = SIGTRAP;
38671.1Skamil	pid_t child, wpid;
38681.1Skamil#if defined(TWAIT_HAVE_STATUS)
38691.1Skamil	int status;
38701.1Skamil#endif
38711.1Skamil	sigset_t intmask;
38721.1Skamil
38731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38751.1Skamil	if (child == 0) {
38761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38781.1Skamil
38791.1Skamil		sigemptyset(&intmask);
38801.1Skamil		sigaddset(&intmask, sigmasked);
38811.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
38821.1Skamil
38831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38851.1Skamil
38861.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
38871.1Skamil		    strsignal(sigmasked));
38881.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
38891.1Skamil
38901.13Schristos		DPRINTF("Before exiting of the child process\n");
38911.1Skamil		_exit(exitval);
38921.1Skamil	}
38931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38941.1Skamil
38951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38971.1Skamil
38981.1Skamil	validate_status_stopped(status, sigval);
38991.1Skamil
39001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39011.1Skamil	    "without signal to be sent\n");
39021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39031.1Skamil
39041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39061.1Skamil
39071.1Skamil	validate_status_exited(status, exitval);
39081.1Skamil
39091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39111.1Skamil}
39121.1Skamil
39131.1SkamilATF_TC(signal3);
39141.1SkamilATF_TC_HEAD(signal3, tc)
39151.1Skamil{
39161.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
39171.1Skamil	atf_tc_set_md_var(tc, "descr",
39181.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
39191.1Skamil	    "catching software breakpoints");
39201.1Skamil}
39211.1Skamil
39221.1SkamilATF_TC_BODY(signal3, tc)
39231.1Skamil{
39241.1Skamil	const int exitval = 5;
39251.1Skamil	const int sigval = SIGSTOP;
39261.1Skamil	const int sigmasked = SIGTRAP;
39271.1Skamil	pid_t child, wpid;
39281.1Skamil#if defined(TWAIT_HAVE_STATUS)
39291.1Skamil	int status;
39301.1Skamil#endif
39311.1Skamil	sigset_t intmask;
39321.1Skamil
39331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39351.1Skamil	if (child == 0) {
39361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39381.1Skamil
39391.1Skamil		sigemptyset(&intmask);
39401.1Skamil		sigaddset(&intmask, sigmasked);
39411.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
39421.1Skamil
39431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39451.1Skamil
39461.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
39471.52Skamil		trigger_trap();
39481.1Skamil
39491.13Schristos		DPRINTF("Before exiting of the child process\n");
39501.1Skamil		_exit(exitval);
39511.1Skamil	}
39521.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39531.1Skamil
39541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39561.1Skamil
39571.1Skamil	validate_status_stopped(status, sigval);
39581.1Skamil
39591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39601.1Skamil	    "without signal to be sent\n");
39611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39621.1Skamil
39631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39651.1Skamil
39661.1Skamil	validate_status_stopped(status, sigmasked);
39671.1Skamil
39681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39691.1Skamil	    "without signal to be sent\n");
39701.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
39711.1Skamil
39721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39741.1Skamil
39751.49Skamil	validate_status_signaled(status, SIGKILL, 0);
39761.1Skamil
39771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39791.1Skamil}
39801.1Skamil
39811.1Skamil#if defined(PT_STEP)
39821.1SkamilATF_TC(signal4);
39831.1SkamilATF_TC_HEAD(signal4, tc)
39841.1Skamil{
39851.1Skamil	atf_tc_set_md_var(tc, "descr",
39861.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
39871.1Skamil	    "catching single step trap");
39881.1Skamil}
39891.1Skamil
39901.1SkamilATF_TC_BODY(signal4, tc)
39911.1Skamil{
39921.1Skamil	const int exitval = 5;
39931.1Skamil	const int sigval = SIGSTOP;
39941.1Skamil	const int sigmasked = SIGTRAP;
39951.1Skamil	pid_t child, wpid;
39961.1Skamil#if defined(TWAIT_HAVE_STATUS)
39971.1Skamil	int status;
39981.1Skamil#endif
39991.1Skamil	sigset_t intmask;
40001.1Skamil	int happy;
40011.1Skamil
40021.1Skamil#if defined(__arm__)
40031.5Skamil	/* PT_STEP not supported on arm 32-bit */
40041.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
40051.1Skamil#endif
40061.1Skamil
40071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40091.1Skamil	if (child == 0) {
40101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40121.1Skamil
40131.1Skamil		happy = check_happy(100);
40141.1Skamil
40151.1Skamil		sigemptyset(&intmask);
40161.1Skamil		sigaddset(&intmask, sigmasked);
40171.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
40181.1Skamil
40191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40211.1Skamil
40221.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
40231.1Skamil
40241.13Schristos		DPRINTF("Before exiting of the child process\n");
40251.1Skamil		_exit(exitval);
40261.1Skamil	}
40271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40281.1Skamil
40291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40311.1Skamil
40321.1Skamil	validate_status_stopped(status, sigval);
40331.1Skamil
40341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40351.1Skamil	    "without signal to be sent\n");
40361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
40371.1Skamil
40381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40401.1Skamil
40411.1Skamil	validate_status_stopped(status, sigmasked);
40421.1Skamil
40431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40441.1Skamil	    "without signal to be sent\n");
40451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40461.1Skamil
40471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40491.1Skamil
40501.1Skamil	validate_status_exited(status, exitval);
40511.1Skamil
40521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40531.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40541.1Skamil}
40551.1Skamil#endif
40561.1Skamil
40571.1SkamilATF_TC(signal5);
40581.1SkamilATF_TC_HEAD(signal5, tc)
40591.1Skamil{
40601.1Skamil	atf_tc_set_md_var(tc, "descr",
40611.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
40621.1Skamil	    "catching exec() breakpoint");
40631.1Skamil}
40641.1Skamil
40651.1SkamilATF_TC_BODY(signal5, tc)
40661.1Skamil{
40671.1Skamil	const int exitval = 5;
40681.1Skamil	const int sigval = SIGSTOP;
40691.1Skamil	const int sigmasked = SIGTRAP;
40701.1Skamil	pid_t child, wpid;
40711.1Skamil#if defined(TWAIT_HAVE_STATUS)
40721.1Skamil	int status;
40731.1Skamil#endif
40741.1Skamil	sigset_t intmask;
40751.1Skamil
40761.14Schristos	atf_tc_expect_fail("wrong signal");
40771.14Schristos
40781.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40791.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40801.1Skamil	if (child == 0) {
40811.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40821.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40831.1Skamil
40841.1Skamil		sigemptyset(&intmask);
40851.1Skamil		sigaddset(&intmask, sigmasked);
40861.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
40871.1Skamil
40881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40901.1Skamil
40911.13Schristos		DPRINTF("Before calling execve(2) from child\n");
40921.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
40931.1Skamil
40941.13Schristos		DPRINTF("Before exiting of the child process\n");
40951.1Skamil		_exit(exitval);
40961.1Skamil	}
40971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40981.1Skamil
40991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41011.1Skamil
41021.1Skamil	validate_status_stopped(status, sigval);
41031.1Skamil
41041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41051.1Skamil	    "without signal to be sent\n");
41061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41071.1Skamil
41081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41101.1Skamil
41111.1Skamil	validate_status_stopped(status, sigmasked);
41121.1Skamil
41131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41141.1Skamil	    "without signal to be sent\n");
41151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41161.1Skamil
41171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41191.1Skamil
41201.1Skamil	validate_status_exited(status, exitval);
41211.1Skamil
41221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41241.1Skamil}
41251.1Skamil
41261.1Skamil#if defined(TWAIT_HAVE_PID)
41271.1SkamilATF_TC(signal6);
41281.1SkamilATF_TC_HEAD(signal6, tc)
41291.1Skamil{
41301.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
41311.1Skamil	atf_tc_set_md_var(tc, "descr",
41321.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
41331.1Skamil	    "catching PTRACE_FORK breakpoint");
41341.1Skamil}
41351.1Skamil
41361.1SkamilATF_TC_BODY(signal6, tc)
41371.1Skamil{
41381.1Skamil	const int exitval = 5;
41391.1Skamil	const int exitval2 = 15;
41401.1Skamil	const int sigval = SIGSTOP;
41411.1Skamil	const int sigmasked = SIGTRAP;
41421.1Skamil	pid_t child, child2, wpid;
41431.1Skamil#if defined(TWAIT_HAVE_STATUS)
41441.1Skamil	int status;
41451.1Skamil#endif
41461.1Skamil	sigset_t intmask;
41471.1Skamil	ptrace_state_t state;
41481.1Skamil	const int slen = sizeof(state);
41491.1Skamil	ptrace_event_t event;
41501.1Skamil	const int elen = sizeof(event);
41511.1Skamil
41521.38Skamil	atf_tc_expect_fail("PR kern/51918");
41531.14Schristos
41541.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41551.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41561.1Skamil	if (child == 0) {
41571.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41581.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41591.1Skamil
41601.1Skamil		sigemptyset(&intmask);
41611.1Skamil		sigaddset(&intmask, sigmasked);
41621.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
41631.1Skamil
41641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41661.1Skamil
41671.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
41681.1Skamil
41691.1Skamil		if (child2 == 0)
41701.1Skamil			_exit(exitval2);
41711.1Skamil
41721.1Skamil		FORKEE_REQUIRE_SUCCESS
41731.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
41741.1Skamil
41751.1Skamil		forkee_status_exited(status, exitval2);
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("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
41881.1Skamil	event.pe_set_event = PTRACE_FORK;
41891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
41901.1Skamil
41911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41921.1Skamil	    "without signal to be sent\n");
41931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41941.1Skamil
41951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41971.1Skamil
41981.1Skamil	validate_status_stopped(status, sigmasked);
41991.1Skamil
42001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
42011.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
42021.1Skamil
42031.1Skamil	child2 = state.pe_other_pid;
42041.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
42051.1Skamil
42061.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
42071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
42081.1Skamil	    child2);
42091.1Skamil
42101.1Skamil	validate_status_stopped(status, SIGTRAP);
42111.1Skamil
42121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
42131.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
42141.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
42151.1Skamil
42161.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
42171.1Skamil	    "without signal to be sent\n");
42181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
42191.1Skamil
42201.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42211.1Skamil	    "without signal to be sent\n");
42221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42231.1Skamil
42241.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
42251.1Skamil	    TWAIT_FNAME);
42261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
42271.57Skamil	    child2);
42281.1Skamil
42291.1Skamil	validate_status_exited(status, exitval2);
42301.1Skamil
42311.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
42321.1Skamil	    TWAIT_FNAME);
42331.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
42341.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
42351.1Skamil
42361.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
42371.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
42381.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42391.1Skamil
42401.1Skamil	validate_status_stopped(status, SIGCHLD);
42411.1Skamil
42421.57Skamil	DPRINTF("Before resuming the child process where it left off and "
42431.1Skamil	    "without signal to be sent\n");
42441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42451.1Skamil
42461.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
42471.1Skamil	    TWAIT_FNAME);
42481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42491.1Skamil
42501.1Skamil	validate_status_exited(status, exitval);
42511.1Skamil
42521.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
42531.57Skamil	    TWAIT_FNAME);
42541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42551.1Skamil}
42561.1Skamil#endif
42571.1Skamil
42581.1Skamil#if defined(TWAIT_HAVE_PID)
42591.1SkamilATF_TC(signal7);
42601.1SkamilATF_TC_HEAD(signal7, tc)
42611.1Skamil{
42621.1Skamil	atf_tc_set_md_var(tc, "descr",
42631.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
42641.1Skamil	    "catching PTRACE_VFORK breakpoint");
42651.1Skamil}
42661.1Skamil
42671.1SkamilATF_TC_BODY(signal7, tc)
42681.1Skamil{
42691.1Skamil	const int exitval = 5;
42701.1Skamil	const int exitval2 = 15;
42711.1Skamil	const int sigval = SIGSTOP;
42721.1Skamil	const int sigmasked = SIGTRAP;
42731.1Skamil	pid_t child, child2, wpid;
42741.1Skamil#if defined(TWAIT_HAVE_STATUS)
42751.1Skamil	int status;
42761.1Skamil#endif
42771.1Skamil	sigset_t intmask;
42781.1Skamil	ptrace_state_t state;
42791.1Skamil	const int slen = sizeof(state);
42801.1Skamil	ptrace_event_t event;
42811.1Skamil	const int elen = sizeof(event);
42821.1Skamil
42831.38Skamil	atf_tc_expect_fail("PR kern/51918");
42841.14Schristos
42851.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42861.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42871.1Skamil	if (child == 0) {
42881.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42891.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42901.1Skamil
42911.1Skamil		sigemptyset(&intmask);
42921.1Skamil		sigaddset(&intmask, sigmasked);
42931.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42941.1Skamil
42951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42971.1Skamil
42981.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
42991.1Skamil
43001.1Skamil		if (child2 == 0)
43011.1Skamil			_exit(exitval2);
43021.1Skamil
43031.1Skamil		FORKEE_REQUIRE_SUCCESS
43041.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
43051.1Skamil
43061.1Skamil		forkee_status_exited(status, exitval2);
43071.1Skamil
43081.13Schristos		DPRINTF("Before exiting of the child process\n");
43091.1Skamil		_exit(exitval);
43101.1Skamil	}
43111.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43121.1Skamil
43131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43151.1Skamil
43161.1Skamil	validate_status_stopped(status, sigval);
43171.1Skamil
43181.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
43191.1Skamil	event.pe_set_event = PTRACE_VFORK;
43201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
43211.1Skamil
43221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43231.1Skamil	    "without signal to be sent\n");
43241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43251.1Skamil
43261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43281.1Skamil
43291.1Skamil	validate_status_stopped(status, sigmasked);
43301.1Skamil
43311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
43321.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
43331.1Skamil
43341.1Skamil	child2 = state.pe_other_pid;
43351.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
43361.1Skamil
43371.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
43381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
43391.1Skamil	    child2);
43401.1Skamil
43411.1Skamil	validate_status_stopped(status, SIGTRAP);
43421.1Skamil
43431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
43441.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
43451.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
43461.1Skamil
43471.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
43481.1Skamil	    "without signal to be sent\n");
43491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
43501.1Skamil
43511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43521.1Skamil	    "without signal to be sent\n");
43531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43541.1Skamil
43551.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
43561.1Skamil	    TWAIT_FNAME);
43571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
43581.57Skamil	    child2);
43591.1Skamil
43601.1Skamil	validate_status_exited(status, exitval2);
43611.1Skamil
43621.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
43631.1Skamil	    TWAIT_FNAME);
43641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
43651.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
43661.1Skamil
43671.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
43681.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
43691.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43701.1Skamil
43711.1Skamil	validate_status_stopped(status, SIGCHLD);
43721.1Skamil
43731.57Skamil	DPRINTF("Before resuming the child process where it left off and "
43741.1Skamil	    "without signal to be sent\n");
43751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43761.1Skamil
43771.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
43781.1Skamil	    TWAIT_FNAME);
43791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43801.1Skamil
43811.1Skamil	validate_status_exited(status, exitval);
43821.1Skamil
43831.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
43841.57Skamil	    TWAIT_FNAME);
43851.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43861.1Skamil}
43871.1Skamil#endif
43881.1Skamil
43891.1SkamilATF_TC(signal8);
43901.1SkamilATF_TC_HEAD(signal8, tc)
43911.1Skamil{
43921.1Skamil	atf_tc_set_md_var(tc, "descr",
43931.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43941.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
43951.1Skamil}
43961.1Skamil
43971.1SkamilATF_TC_BODY(signal8, tc)
43981.1Skamil{
43991.1Skamil	const int exitval = 5;
44001.1Skamil	const int exitval2 = 15;
44011.1Skamil	const int sigval = SIGSTOP;
44021.1Skamil	const int sigmasked = SIGTRAP;
44031.1Skamil	pid_t child, child2, wpid;
44041.1Skamil#if defined(TWAIT_HAVE_STATUS)
44051.1Skamil	int status;
44061.1Skamil#endif
44071.1Skamil	sigset_t intmask;
44081.1Skamil	ptrace_state_t state;
44091.1Skamil	const int slen = sizeof(state);
44101.1Skamil	ptrace_event_t event;
44111.1Skamil	const int elen = sizeof(event);
44121.1Skamil
44131.14Schristos	atf_tc_expect_fail("PR kern/51918");
44141.14Schristos
44151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44171.1Skamil	if (child == 0) {
44181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44201.1Skamil
44211.1Skamil		sigemptyset(&intmask);
44221.1Skamil		sigaddset(&intmask, sigmasked);
44231.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44241.1Skamil
44251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44271.1Skamil
44281.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
44291.1Skamil
44301.1Skamil		if (child2 == 0)
44311.1Skamil			_exit(exitval2);
44321.1Skamil
44331.1Skamil		FORKEE_REQUIRE_SUCCESS
44341.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
44351.1Skamil
44361.1Skamil		forkee_status_exited(status, exitval2);
44371.1Skamil
44381.13Schristos		DPRINTF("Before exiting of the child process\n");
44391.1Skamil		_exit(exitval);
44401.1Skamil	}
44411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44421.1Skamil
44431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44451.1Skamil
44461.1Skamil	validate_status_stopped(status, sigval);
44471.1Skamil
44481.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
44491.1Skamil	    child);
44501.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
44511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
44521.1Skamil
44531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44541.1Skamil	    "without signal to be sent\n");
44551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44561.1Skamil
44571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44591.1Skamil
44601.1Skamil	validate_status_stopped(status, sigmasked);
44611.1Skamil
44621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
44631.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
44641.1Skamil
44651.1Skamil	child2 = state.pe_other_pid;
44661.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
44671.1Skamil
44681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44691.1Skamil	    "without signal to be sent\n");
44701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44711.1Skamil
44721.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
44731.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
44741.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44751.1Skamil
44761.1Skamil	validate_status_stopped(status, SIGCHLD);
44771.1Skamil
44781.57Skamil	DPRINTF("Before resuming the child process where it left off and "
44791.1Skamil	    "without signal to be sent\n");
44801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44811.1Skamil
44821.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
44831.1Skamil	    TWAIT_FNAME);
44841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44851.1Skamil
44861.1Skamil	validate_status_exited(status, exitval);
44871.1Skamil
44881.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
44891.57Skamil	    TWAIT_FNAME);
44901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44911.1Skamil}
44921.1Skamil
44931.1SkamilATF_TC(signal9);
44941.1SkamilATF_TC_HEAD(signal9, tc)
44951.1Skamil{
44961.1Skamil	atf_tc_set_md_var(tc, "descr",
44971.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44981.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
44991.1Skamil}
45001.1Skamil
45011.1SkamilATF_TC_BODY(signal9, tc)
45021.1Skamil{
45031.1Skamil	const int exitval = 5;
45041.1Skamil	const int sigval = SIGSTOP;
45051.1Skamil	const int sigmasked = SIGTRAP;
45061.1Skamil	pid_t child, wpid;
45071.1Skamil#if defined(TWAIT_HAVE_STATUS)
45081.1Skamil	int status;
45091.1Skamil#endif
45101.1Skamil	sigset_t intmask;
45111.1Skamil	ptrace_state_t state;
45121.1Skamil	const int slen = sizeof(state);
45131.1Skamil	ptrace_event_t event;
45141.1Skamil	const int elen = sizeof(event);
45151.1Skamil	ucontext_t uc;
45161.1Skamil	lwpid_t lid;
45171.1Skamil	static const size_t ssize = 16*1024;
45181.1Skamil	void *stack;
45191.1Skamil
45201.14Schristos	atf_tc_expect_fail("PR kern/51918");
45211.14Schristos
45221.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45231.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45241.1Skamil	if (child == 0) {
45251.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45261.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45271.1Skamil
45281.1Skamil		sigemptyset(&intmask);
45291.1Skamil		sigaddset(&intmask, sigmasked);
45301.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45311.1Skamil
45321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45341.1Skamil
45351.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
45361.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
45371.1Skamil
45381.13Schristos		DPRINTF("Before making context for new lwp in child\n");
45391.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
45401.1Skamil
45411.13Schristos		DPRINTF("Before creating new in child\n");
45421.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
45431.1Skamil
45441.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
45451.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
45461.1Skamil
45471.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
45481.1Skamil		    "are the same\n", lid, the_lwp_id);
45491.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
45501.1Skamil
45511.13Schristos		DPRINTF("Before exiting of the child process\n");
45521.1Skamil		_exit(exitval);
45531.1Skamil	}
45541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45551.1Skamil
45561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45581.1Skamil
45591.1Skamil	validate_status_stopped(status, sigval);
45601.1Skamil
45611.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
45621.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
45631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
45641.1Skamil
45651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45661.1Skamil	    "without signal to be sent\n");
45671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45681.1Skamil
45691.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
45701.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
45711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45721.1Skamil
45731.1Skamil	validate_status_stopped(status, sigmasked);
45741.1Skamil
45751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
45761.1Skamil
45771.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
45781.1Skamil
45791.1Skamil	lid = state.pe_lwp;
45801.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
45811.1Skamil
45821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45831.1Skamil	    "without signal to be sent\n");
45841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45851.1Skamil
45861.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
45871.1Skamil	    TWAIT_FNAME);
45881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45891.1Skamil
45901.1Skamil	validate_status_exited(status, exitval);
45911.1Skamil
45921.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
45931.1Skamil	    TWAIT_FNAME);
45941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45951.1Skamil}
45961.1Skamil
45971.1SkamilATF_TC(signal10);
45981.1SkamilATF_TC_HEAD(signal10, tc)
45991.1Skamil{
46001.1Skamil	atf_tc_set_md_var(tc, "descr",
46011.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
46021.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
46031.1Skamil}
46041.1Skamil
46051.1SkamilATF_TC_BODY(signal10, tc)
46061.1Skamil{
46071.1Skamil	const int exitval = 5;
46081.1Skamil	const int sigval = SIGSTOP;
46091.1Skamil	const int sigmasked = SIGTRAP;
46101.1Skamil	pid_t child, wpid;
46111.1Skamil#if defined(TWAIT_HAVE_STATUS)
46121.1Skamil	int status;
46131.1Skamil#endif
46141.1Skamil	sigset_t intmask;
46151.1Skamil	ptrace_state_t state;
46161.1Skamil	const int slen = sizeof(state);
46171.1Skamil	ptrace_event_t event;
46181.1Skamil	const int elen = sizeof(event);
46191.1Skamil	ucontext_t uc;
46201.1Skamil	lwpid_t lid;
46211.1Skamil	static const size_t ssize = 16*1024;
46221.1Skamil	void *stack;
46231.1Skamil
46241.14Schristos	atf_tc_expect_fail("PR kern/51918");
46251.14Schristos
46261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46281.1Skamil	if (child == 0) {
46291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46311.1Skamil
46321.1Skamil		sigemptyset(&intmask);
46331.1Skamil		sigaddset(&intmask, sigmasked);
46341.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46351.1Skamil
46361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46381.1Skamil
46391.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
46401.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
46411.1Skamil
46421.13Schristos		DPRINTF("Before making context for new lwp in child\n");
46431.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
46441.1Skamil
46451.13Schristos		DPRINTF("Before creating new in child\n");
46461.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
46471.1Skamil
46481.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
46491.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
46501.1Skamil
46511.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
46521.1Skamil		    "are the same\n", lid, the_lwp_id);
46531.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
46541.1Skamil
46551.13Schristos		DPRINTF("Before exiting of the child process\n");
46561.1Skamil		_exit(exitval);
46571.1Skamil	}
46581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46591.1Skamil
46601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46621.1Skamil
46631.1Skamil	validate_status_stopped(status, sigval);
46641.1Skamil
46651.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
46661.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
46671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
46681.1Skamil
46691.13Schristos	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 stopped "
46741.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
46751.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46761.1Skamil
46771.1Skamil	validate_status_stopped(status, sigmasked);
46781.1Skamil
46791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
46801.1Skamil
46811.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
46821.1Skamil
46831.1Skamil	lid = state.pe_lwp;
46841.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
46851.1Skamil
46861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46871.1Skamil	    "without signal to be sent\n");
46881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46891.1Skamil
46901.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
46911.1Skamil	    TWAIT_FNAME);
46921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46931.1Skamil
46941.1Skamil	validate_status_exited(status, exitval);
46951.1Skamil
46961.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
46971.1Skamil	    TWAIT_FNAME);
46981.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46991.1Skamil}
47001.1Skamil
47011.1Skamilstatic void
47021.1Skamillwp_main_stop(void *arg)
47031.1Skamil{
47041.1Skamil	the_lwp_id = _lwp_self();
47051.1Skamil
47061.1Skamil	raise(SIGTRAP);
47071.1Skamil
47081.1Skamil	_lwp_exit();
47091.1Skamil}
47101.1Skamil
47111.1SkamilATF_TC(suspend1);
47121.1SkamilATF_TC_HEAD(suspend1, tc)
47131.1Skamil{
47141.1Skamil	atf_tc_set_md_var(tc, "descr",
47151.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
47161.1Skamil	    "resumed by a tracee");
47171.1Skamil}
47181.1Skamil
47191.1SkamilATF_TC_BODY(suspend1, tc)
47201.1Skamil{
47211.1Skamil	const int exitval = 5;
47221.1Skamil	const int sigval = SIGSTOP;
47231.1Skamil	pid_t child, wpid;
47241.1Skamil#if defined(TWAIT_HAVE_STATUS)
47251.1Skamil	int status;
47261.1Skamil#endif
47271.1Skamil	ucontext_t uc;
47281.1Skamil	lwpid_t lid;
47291.1Skamil	static const size_t ssize = 16*1024;
47301.1Skamil	void *stack;
47311.1Skamil	struct ptrace_lwpinfo pl;
47321.1Skamil	struct ptrace_siginfo psi;
47331.1Skamil	volatile int go = 0;
47341.1Skamil
47351.17Skamil	// Feature pending for refactoring
47361.17Skamil	atf_tc_expect_fail("PR kern/51995");
47371.17Skamil
47381.16Skamil	// Hangs with qemu
47391.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
47401.16Skamil
47411.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47421.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47431.1Skamil	if (child == 0) {
47441.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47451.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47461.1Skamil
47471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47491.1Skamil
47501.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
47511.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
47521.1Skamil
47531.13Schristos		DPRINTF("Before making context for new lwp in child\n");
47541.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
47551.1Skamil
47561.13Schristos		DPRINTF("Before creating new in child\n");
47571.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
47581.1Skamil
47591.1Skamil		while (go == 0)
47601.1Skamil			continue;
47611.1Skamil
47621.1Skamil		raise(SIGINT);
47631.1Skamil
47641.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
47651.1Skamil
47661.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
47671.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
47681.1Skamil
47691.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
47701.1Skamil		    "are the same\n", lid, the_lwp_id);
47711.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
47721.1Skamil
47731.13Schristos		DPRINTF("Before exiting of the child process\n");
47741.1Skamil		_exit(exitval);
47751.1Skamil	}
47761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47771.1Skamil
47781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47801.1Skamil
47811.1Skamil	validate_status_stopped(status, sigval);
47821.1Skamil
47831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47841.1Skamil	    "without signal to be sent\n");
47851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47861.1Skamil
47871.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
47881.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
47891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47901.1Skamil
47911.1Skamil	validate_status_stopped(status, SIGTRAP);
47921.1Skamil
47931.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
47941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
47951.1Skamil
47961.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
47971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
47981.1Skamil
47991.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
48001.1Skamil	    child, getpid());
48011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
48021.1Skamil
48031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48041.1Skamil	    "without signal to be sent\n");
48051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48061.1Skamil
48071.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48081.1Skamil	    "SIGINT\n", TWAIT_FNAME);
48091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48101.1Skamil
48111.1Skamil	validate_status_stopped(status, SIGINT);
48121.1Skamil
48131.1Skamil	pl.pl_lwpid = 0;
48141.1Skamil
48151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
48161.1Skamil	while (pl.pl_lwpid != 0) {
48171.1Skamil
48181.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
48191.1Skamil		switch (pl.pl_lwpid) {
48201.1Skamil		case 1:
48211.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
48221.1Skamil			break;
48231.1Skamil		case 2:
48241.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
48251.1Skamil			break;
48261.1Skamil		}
48271.1Skamil	}
48281.1Skamil
48291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48301.1Skamil	    "without signal to be sent\n");
48311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48321.1Skamil
48331.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48341.1Skamil	    TWAIT_FNAME);
48351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48361.1Skamil
48371.1Skamil	validate_status_exited(status, exitval);
48381.1Skamil
48391.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48401.1Skamil	    TWAIT_FNAME);
48411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48421.1Skamil}
48431.1Skamil
48441.1SkamilATF_TC(suspend2);
48451.1SkamilATF_TC_HEAD(suspend2, tc)
48461.1Skamil{
48471.1Skamil	atf_tc_set_md_var(tc, "descr",
48481.1Skamil	    "Verify that the while the only thread within a process is "
48491.1Skamil	    "suspended, the whole process cannot be unstopped");
48501.1Skamil}
48511.1Skamil
48521.1SkamilATF_TC_BODY(suspend2, tc)
48531.1Skamil{
48541.1Skamil	const int exitval = 5;
48551.1Skamil	const int sigval = SIGSTOP;
48561.1Skamil	pid_t child, wpid;
48571.1Skamil#if defined(TWAIT_HAVE_STATUS)
48581.1Skamil	int status;
48591.1Skamil#endif
48601.1Skamil	struct ptrace_siginfo psi;
48611.1Skamil
48621.17Skamil	// Feature pending for refactoring
48631.17Skamil	atf_tc_expect_fail("PR kern/51995");
48641.17Skamil
48651.16Skamil	// Hangs with qemu
48661.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
48671.16Skamil
48681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48701.1Skamil	if (child == 0) {
48711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48731.1Skamil
48741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48761.1Skamil
48771.13Schristos		DPRINTF("Before exiting of the child process\n");
48781.1Skamil		_exit(exitval);
48791.1Skamil	}
48801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48811.1Skamil
48821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48841.1Skamil
48851.1Skamil	validate_status_stopped(status, sigval);
48861.1Skamil
48871.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
48881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
48891.1Skamil
48901.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
48911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
48921.1Skamil
48931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48941.1Skamil	    "without signal to be sent\n");
48951.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
48961.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
48971.1Skamil
48981.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
48991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
49001.1Skamil
49011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49021.1Skamil	    "without signal to be sent\n");
49031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49041.1Skamil
49051.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49061.1Skamil	    TWAIT_FNAME);
49071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49081.1Skamil
49091.1Skamil	validate_status_exited(status, exitval);
49101.1Skamil
49111.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49121.1Skamil	    TWAIT_FNAME);
49131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49141.1Skamil}
49151.1Skamil
49161.1SkamilATF_TC(resume1);
49171.1SkamilATF_TC_HEAD(resume1, tc)
49181.1Skamil{
49191.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
49201.1Skamil	atf_tc_set_md_var(tc, "descr",
49211.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
49221.1Skamil	    "resumed by the debugger");
49231.1Skamil}
49241.1Skamil
49251.1SkamilATF_TC_BODY(resume1, tc)
49261.1Skamil{
49271.1Skamil	struct msg_fds fds;
49281.1Skamil	const int exitval = 5;
49291.1Skamil	const int sigval = SIGSTOP;
49301.1Skamil	pid_t child, wpid;
49311.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
49321.1Skamil#if defined(TWAIT_HAVE_STATUS)
49331.1Skamil	int status;
49341.1Skamil#endif
49351.1Skamil	ucontext_t uc;
49361.1Skamil	lwpid_t lid;
49371.1Skamil	static const size_t ssize = 16*1024;
49381.1Skamil	void *stack;
49391.1Skamil	struct ptrace_lwpinfo pl;
49401.1Skamil	struct ptrace_siginfo psi;
49411.1Skamil
49421.17Skamil	// Feature pending for refactoring
49431.17Skamil	atf_tc_expect_fail("PR kern/51995");
49441.17Skamil
49451.15Schristos	// Hangs with qemu
49461.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
49471.1Skamil
49481.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
49491.1Skamil
49501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49521.1Skamil	if (child == 0) {
49531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49551.1Skamil
49561.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49571.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49581.1Skamil
49591.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
49601.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
49611.1Skamil
49621.13Schristos		DPRINTF("Before making context for new lwp in child\n");
49631.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
49641.1Skamil
49651.13Schristos		DPRINTF("Before creating new in child\n");
49661.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
49671.1Skamil
49681.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
49691.1Skamil
49701.1Skamil		raise(SIGINT);
49711.1Skamil
49721.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
49731.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
49741.1Skamil
49751.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
49761.1Skamil		    "are the same\n", lid, the_lwp_id);
49771.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
49781.1Skamil
49791.13Schristos		DPRINTF("Before exiting of the child process\n");
49801.1Skamil		_exit(exitval);
49811.1Skamil	}
49821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49831.1Skamil
49841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49861.1Skamil
49871.1Skamil	validate_status_stopped(status, sigval);
49881.1Skamil
49891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49901.1Skamil	    "without signal to be sent\n");
49911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49921.1Skamil
49931.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49941.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
49951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49961.1Skamil
49971.1Skamil	validate_status_stopped(status, SIGTRAP);
49981.1Skamil
49991.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
50001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
50011.1Skamil
50021.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
50031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
50041.1Skamil
50051.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
50061.1Skamil
50071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50081.1Skamil	    "without signal to be sent\n");
50091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50101.1Skamil
50111.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50121.1Skamil	    "SIGINT\n", TWAIT_FNAME);
50131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50141.1Skamil
50151.1Skamil	validate_status_stopped(status, SIGINT);
50161.1Skamil
50171.1Skamil	pl.pl_lwpid = 0;
50181.1Skamil
50191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
50201.1Skamil	while (pl.pl_lwpid != 0) {
50211.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
50221.1Skamil		switch (pl.pl_lwpid) {
50231.1Skamil		case 1:
50241.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
50251.1Skamil			break;
50261.1Skamil		case 2:
50271.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
50281.1Skamil			break;
50291.1Skamil		}
50301.1Skamil	}
50311.1Skamil
50321.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
50331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
50341.1Skamil
50351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50361.1Skamil	    "without signal to be sent\n");
50371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50381.1Skamil
50391.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50401.1Skamil	    TWAIT_FNAME);
50411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50421.1Skamil
50431.1Skamil	validate_status_exited(status, exitval);
50441.1Skamil
50451.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
50461.1Skamil	    TWAIT_FNAME);
50471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50481.1Skamil
50491.1Skamil	msg_close(&fds);
50501.1Skamil
50511.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
50521.1Skamil	sleep(10);
50531.1Skamil}
50541.1Skamil
50551.1SkamilATF_TC(syscall1);
50561.1SkamilATF_TC_HEAD(syscall1, tc)
50571.1Skamil{
50581.1Skamil	atf_tc_set_md_var(tc, "descr",
50591.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
50601.1Skamil}
50611.1Skamil
50621.1SkamilATF_TC_BODY(syscall1, tc)
50631.1Skamil{
50641.1Skamil	const int exitval = 5;
50651.1Skamil	const int sigval = SIGSTOP;
50661.1Skamil	pid_t child, wpid;
50671.1Skamil#if defined(TWAIT_HAVE_STATUS)
50681.1Skamil	int status;
50691.1Skamil#endif
50701.1Skamil	struct ptrace_siginfo info;
50711.1Skamil	memset(&info, 0, sizeof(info));
50721.1Skamil
50731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50751.1Skamil	if (child == 0) {
50761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50781.1Skamil
50791.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50801.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50811.1Skamil
50821.1Skamil		syscall(SYS_getpid);
50831.1Skamil
50841.13Schristos		DPRINTF("Before exiting of the child process\n");
50851.1Skamil		_exit(exitval);
50861.1Skamil	}
50871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50881.1Skamil
50891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50911.1Skamil
50921.1Skamil	validate_status_stopped(status, sigval);
50931.1Skamil
50941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50951.1Skamil	    "without signal to be sent\n");
50961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
50971.1Skamil
50981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51001.1Skamil
51011.1Skamil	validate_status_stopped(status, SIGTRAP);
51021.1Skamil
51031.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51051.1Skamil
51061.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
51071.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
51081.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51091.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
51101.1Skamil
51111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51121.1Skamil	    "without signal to be sent\n");
51131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51141.1Skamil
51151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51171.1Skamil
51181.1Skamil	validate_status_stopped(status, SIGTRAP);
51191.1Skamil
51201.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51221.1Skamil
51231.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
51241.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
51251.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51261.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
51271.1Skamil
51281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51291.1Skamil	    "without signal to be sent\n");
51301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51311.1Skamil
51321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51341.1Skamil
51351.1Skamil	validate_status_exited(status, exitval);
51361.1Skamil
51371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51391.1Skamil}
51401.1Skamil
51411.1SkamilATF_TC(syscallemu1);
51421.1SkamilATF_TC_HEAD(syscallemu1, tc)
51431.1Skamil{
51441.1Skamil	atf_tc_set_md_var(tc, "descr",
51451.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
51461.1Skamil}
51471.1Skamil
51481.1SkamilATF_TC_BODY(syscallemu1, 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
51571.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
51581.6Skamil	/* syscallemu does not work on sparc (32-bit) */
51591.6Skamil	atf_tc_expect_fail("PR kern/52166");
51601.6Skamil#endif
51611.6Skamil
51621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51641.1Skamil	if (child == 0) {
51651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51671.1Skamil
51681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51701.1Skamil
51711.1Skamil		syscall(SYS_exit, 100);
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 resuming the child process where it left off and "
51841.1Skamil	    "without signal to be sent\n");
51851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51861.1Skamil
51871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51891.1Skamil
51901.1Skamil	validate_status_stopped(status, SIGTRAP);
51911.1Skamil
51921.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
51931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
51941.1Skamil
51951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51961.1Skamil	    "without signal to be sent\n");
51971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
51981.1Skamil
51991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52011.1Skamil
52021.1Skamil	validate_status_stopped(status, SIGTRAP);
52031.1Skamil
52041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52051.1Skamil	    "without signal to be sent\n");
52061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52071.1Skamil
52081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52101.1Skamil
52111.1Skamil	validate_status_exited(status, exitval);
52121.1Skamil
52131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52151.1Skamil}
52161.1Skamil
52171.1Skamil#include "t_ptrace_amd64_wait.h"
52181.1Skamil#include "t_ptrace_i386_wait.h"
52191.1Skamil#include "t_ptrace_x86_wait.h"
52201.1Skamil
52211.1SkamilATF_TP_ADD_TCS(tp)
52221.1Skamil{
52231.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
52241.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
52251.33Skamil
52261.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
52271.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
52281.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
52291.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
52301.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
52311.33Skamil
52321.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
52331.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
52341.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
52351.50Skamil
52361.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
52371.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
52381.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
52391.50Skamil
52401.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
52411.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
52421.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
52431.50Skamil
52441.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
52451.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
52461.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
52471.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
52481.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
52491.1Skamil
52501.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
52511.37Skamil
52521.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
52531.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
52541.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
52551.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
52561.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
52571.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
52581.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
52591.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
52601.40Skamil
52611.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
52621.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
52631.52Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
52641.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
52651.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
52661.41Skamil
52671.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
52681.43Skamil
52691.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
52701.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
52711.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_terminaton_before_the_parent);
52721.51Skamil
52731.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
52741.51Skamil
52751.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
52761.51Skamil
52771.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
52781.51Skamil		tracee_sees_its_original_parent_getppid);
52791.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
52801.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
52811.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
52821.51Skamil		tracee_sees_its_original_parent_procfs_status);
52831.1Skamil
52841.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
52851.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
52861.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
52871.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
52881.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
52891.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
52901.1Skamil
52911.31Skamil	ATF_TP_ADD_TC(tp, fork1);
52921.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
52931.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
52941.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
52951.31Skamil	ATF_TP_ADD_TC(tp, fork5);
52961.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
52971.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
52981.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
52991.31Skamil
53001.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
53011.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
53021.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
53031.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
53041.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
53051.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
53061.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
53071.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
53081.1Skamil
53091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
53101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
53111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
53121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
53131.54Skamil
53141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
53151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
53161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
53171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
53181.54Skamil
53191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
53201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
53211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
53221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
53231.54Skamil
53241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
53251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
53261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
53271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
53281.54Skamil
53291.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
53301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
53311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
53321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
53331.54Skamil
53341.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
53351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
53361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
53371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
53381.54Skamil
53391.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
53401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
53411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
53421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
53431.54Skamil
53441.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
53451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
53461.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
53471.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
53481.54Skamil
53491.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
53501.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
53511.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
53521.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
53531.54Skamil
53541.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
53551.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
53561.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
53571.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
53581.1Skamil
53591.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
53601.1Skamil
53611.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
53621.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
53631.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
53641.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
53651.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
53661.1Skamil
53671.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
53681.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
53691.1Skamil
53701.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
53711.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
53721.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
53731.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
53741.1Skamil
53751.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
53761.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
53771.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
53781.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
53791.2Skamil
53801.1Skamil	ATF_TP_ADD_TC(tp, kill1);
53811.1Skamil	ATF_TP_ADD_TC(tp, kill2);
53821.1Skamil
53831.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
53841.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
53851.1Skamil
53861.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
53871.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
53881.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
53891.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
53901.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
53911.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
53921.1Skamil
53931.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
53941.1Skamil
53951.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
53961.1Skamil
53971.1Skamil	ATF_TP_ADD_TC(tp, signal1);
53981.1Skamil	ATF_TP_ADD_TC(tp, signal2);
53991.1Skamil	ATF_TP_ADD_TC(tp, signal3);
54001.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
54011.1Skamil	ATF_TP_ADD_TC(tp, signal5);
54021.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
54031.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
54041.1Skamil	ATF_TP_ADD_TC(tp, signal8);
54051.1Skamil	ATF_TP_ADD_TC(tp, signal9);
54061.1Skamil	ATF_TP_ADD_TC(tp, signal10);
54071.1Skamil
54081.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
54091.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
54101.1Skamil
54111.1Skamil	ATF_TP_ADD_TC(tp, resume1);
54121.1Skamil
54131.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
54141.1Skamil
54151.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
54161.1Skamil
54171.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
54181.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
54191.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
54201.1Skamil
54211.1Skamil	return atf_no_error();
54221.1Skamil}
5423