t_ptrace_wait.c revision 1.67
11.67Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.67 2018/08/13 22:59:52 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.67Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.67 2018/08/13 22:59:52 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.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
641.61Skre	sizeof(msg)) == 0)
651.1Skamil
661.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
671.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
681.61Skre	sizeof(msg)) == 0)
691.1Skamil
701.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
711.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
721.61Skre	sizeof(msg)) == 0)
731.1Skamil
741.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
751.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
761.61Skre	sizeof(msg)) == 0)
771.13Schristos
781.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
791.13Schristos    strerror(errno))
801.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
811.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
821.13Schristos
831.13Schristosstatic int debug = 0;
841.13Schristos
851.13Schristos#define DPRINTF(a, ...)	do  \
861.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
871.13Schristos    while (/*CONSTCOND*/0)
881.1Skamil
891.34Skamil/// ----------------------------------------------------------------------------
901.34Skamil
911.33Skamilstatic void
921.33Skamiltraceme_raise(int sigval)
931.1Skamil{
941.1Skamil	const int exitval = 5;
951.1Skamil	pid_t child, wpid;
961.1Skamil#if defined(TWAIT_HAVE_STATUS)
971.1Skamil	int status;
981.1Skamil#endif
991.1Skamil
1001.45Skamil	struct ptrace_siginfo info;
1011.45Skamil	memset(&info, 0, sizeof(info));
1021.45Skamil
1031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1051.1Skamil	if (child == 0) {
1061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1081.1Skamil
1091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1111.1Skamil
1121.36Skamil		switch (sigval) {
1131.36Skamil		case SIGKILL:
1141.36Skamil			/* NOTREACHED */
1151.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1161.36Skamil		default:
1171.36Skamil			DPRINTF("Before exiting of the child process\n");
1181.36Skamil			_exit(exitval);
1191.36Skamil		}
1201.1Skamil	}
1211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1221.1Skamil
1231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1251.1Skamil
1261.36Skamil	switch (sigval) {
1271.36Skamil	case SIGKILL:
1281.36Skamil		validate_status_signaled(status, sigval, 0);
1291.36Skamil		break;
1301.36Skamil	default:
1311.36Skamil		validate_status_stopped(status, sigval);
1321.1Skamil
1331.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1341.61Skre			"child\n");
1351.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1361.61Skre			sizeof(info)) != -1);
1371.45Skamil
1381.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1391.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1401.61Skre			"si_errno=%#x\n",
1411.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1421.61Skre			info.psi_siginfo.si_errno);
1431.45Skamil
1441.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1451.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1461.45Skamil
1471.36Skamil		DPRINTF("Before resuming the child process where it left off "
1481.36Skamil		    "and without signal to be sent\n");
1491.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1501.1Skamil
1511.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1521.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1531.61Skre		    child);
1541.36Skamil		break;
1551.36Skamil	}
1561.1Skamil
1571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1591.1Skamil}
1601.1Skamil
1611.61Skre#define TRACEME_RAISE(test, sig)					\
1621.61SkreATF_TC(test);								\
1631.61SkreATF_TC_HEAD(test, tc)							\
1641.61Skre{									\
1651.61Skre	atf_tc_set_md_var(tc, "descr",					\
1661.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1671.61Skre}									\
1681.61Skre									\
1691.61SkreATF_TC_BODY(test, tc)							\
1701.61Skre{									\
1711.61Skre									\
1721.61Skre	traceme_raise(sig);						\
1731.33Skamil}
1741.33Skamil
1751.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1761.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1771.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1781.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1791.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1801.33Skamil
1811.34Skamil/// ----------------------------------------------------------------------------
1821.1Skamil
1831.1Skamilstatic void
1841.59Skamiltraceme_crash(int sig)
1851.59Skamil{
1861.59Skamil	pid_t child, wpid;
1871.59Skamil#if defined(TWAIT_HAVE_STATUS)
1881.59Skamil	int status;
1891.59Skamil#endif
1901.59Skamil	struct ptrace_siginfo info;
1911.61Skre
1921.59Skamil	memset(&info, 0, sizeof(info));
1931.59Skamil
1941.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
1951.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
1961.59Skamil	if (child == 0) {
1971.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1981.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1991.59Skamil
2001.59Skamil		DPRINTF("Before executing a trap\n");
2011.59Skamil		switch (sig) {
2021.59Skamil		case SIGTRAP:
2031.59Skamil			trigger_trap();
2041.59Skamil			break;
2051.59Skamil		case SIGSEGV:
2061.59Skamil			trigger_segv();
2071.59Skamil			break;
2081.59Skamil		case SIGILL:
2091.59Skamil			trigger_ill();
2101.59Skamil			break;
2111.59Skamil		case SIGFPE:
2121.59Skamil			trigger_fpe();
2131.59Skamil			break;
2141.59Skamil		case SIGBUS:
2151.59Skamil			trigger_bus();
2161.59Skamil			break;
2171.59Skamil		default:
2181.59Skamil			/* NOTREACHED */
2191.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2201.59Skamil		}
2211.59Skamil
2221.59Skamil		/* NOTREACHED */
2231.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
2241.59Skamil	}
2251.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2261.59Skamil
2271.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2281.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2291.59Skamil
2301.59Skamil	validate_status_stopped(status, sig);
2311.59Skamil
2321.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
2331.61Skre	SYSCALL_REQUIRE(
2341.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2351.59Skamil
2361.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2371.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2381.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2391.61Skre	    info.psi_siginfo.si_errno);
2401.59Skamil
2411.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
2421.59Skamil	switch (sig) {
2431.59Skamil	case SIGTRAP:
2441.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
2451.59Skamil		break;
2461.59Skamil	case SIGSEGV:
2471.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
2481.59Skamil		break;
2491.59Skamil//	case SIGILL:
2501.59Skamil//		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_ILLOP);
2511.59Skamil//		break;
2521.59Skamil	case SIGFPE:
2531.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
2541.59Skamil		break;
2551.59Skamil	case SIGBUS:
2561.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
2571.59Skamil		break;
2581.59Skamil	}
2591.59Skamil
2601.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
2611.59Skamil
2621.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2631.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2641.59Skamil
2651.59Skamil	validate_status_signaled(status, SIGKILL, 0);
2661.59Skamil
2671.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2681.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2691.59Skamil}
2701.59Skamil
2711.61Skre#define TRACEME_CRASH(test, sig)					\
2721.61SkreATF_TC(test);								\
2731.61SkreATF_TC_HEAD(test, tc)							\
2741.61Skre{									\
2751.61Skre	atf_tc_set_md_var(tc, "descr",					\
2761.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
2771.61Skre}									\
2781.61Skre									\
2791.61SkreATF_TC_BODY(test, tc)							\
2801.61Skre{									\
2811.61Skre									\
2821.61Skre	traceme_crash(sig);						\
2831.59Skamil}
2841.59Skamil
2851.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
2861.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
2871.59Skamil//TRACEME_CRASH(traceme_crash_ill, SIGILL)
2881.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
2891.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
2901.59Skamil
2911.59Skamil/// ----------------------------------------------------------------------------
2921.59Skamil
2931.59Skamilstatic void
2941.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
2951.1Skamil{
2961.1Skamil	const int exitval = 5;
2971.34Skamil	const int sigval = SIGSTOP;
2981.1Skamil	pid_t child, wpid;
2991.1Skamil	struct sigaction sa;
3001.1Skamil#if defined(TWAIT_HAVE_STATUS)
3011.1Skamil	int status;
3021.1Skamil#endif
3031.61Skre	struct ptrace_siginfo info;
3041.1Skamil
3051.45Skamil	memset(&info, 0, sizeof(info));
3061.45Skamil
3071.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
3081.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
3091.1Skamil	if (child == 0) {
3101.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3111.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3121.1Skamil
3131.34Skamil		sa.sa_handler = sah;
3141.1Skamil		sa.sa_flags = SA_SIGINFO;
3151.1Skamil		sigemptyset(&sa.sa_mask);
3161.1Skamil
3171.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
3181.1Skamil
3191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3211.1Skamil
3221.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
3231.1Skamil
3241.13Schristos		DPRINTF("Before exiting of the child process\n");
3251.1Skamil		_exit(exitval);
3261.1Skamil	}
3271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3281.1Skamil
3291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3311.1Skamil
3321.1Skamil	validate_status_stopped(status, sigval);
3331.1Skamil
3341.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3351.61Skre	SYSCALL_REQUIRE(
3361.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3371.45Skamil
3381.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3391.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3401.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3411.45Skamil	    info.psi_siginfo.si_errno);
3421.45Skamil
3431.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3441.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3451.45Skamil
3461.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
3471.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3491.1Skamil
3501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3521.1Skamil
3531.1Skamil	validate_status_exited(status, exitval);
3541.1Skamil
3551.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3561.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3571.1Skamil}
3581.1Skamil
3591.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
3601.61SkreATF_TC(test);								\
3611.61SkreATF_TC_HEAD(test, tc)							\
3621.61Skre{									\
3631.61Skre	atf_tc_set_md_var(tc, "descr",					\
3641.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
3651.61Skre	    "handled correctly and caught by a signal handler");	\
3661.61Skre}									\
3671.61Skre									\
3681.61Skrestatic int test##_caught = 0;						\
3691.61Skre									\
3701.61Skrestatic void								\
3711.61Skretest##_sighandler(int arg)						\
3721.61Skre{									\
3731.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
3741.61Skre									\
3751.61Skre	++ test##_caught;						\
3761.61Skre}									\
3771.61Skre									\
3781.61SkreATF_TC_BODY(test, tc)							\
3791.61Skre{									\
3801.61Skre									\
3811.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
3821.34Skamil}
3831.34Skamil
3841.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
3851.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
3861.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
3871.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
3881.34Skamil
3891.34Skamil/// ----------------------------------------------------------------------------
3901.34Skamil
3911.35Skamilstatic void
3921.50Skamiltraceme_sendsignal_masked(int sigsent)
3931.50Skamil{
3941.50Skamil	const int exitval = 5;
3951.50Skamil	const int sigval = SIGSTOP;
3961.50Skamil	pid_t child, wpid;
3971.50Skamil	sigset_t set;
3981.50Skamil#if defined(TWAIT_HAVE_STATUS)
3991.50Skamil	int status;
4001.50Skamil#endif
4011.61Skre	struct ptrace_siginfo info;
4021.50Skamil
4031.50Skamil	memset(&info, 0, sizeof(info));
4041.50Skamil
4051.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4061.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4071.50Skamil	if (child == 0) {
4081.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4091.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4101.50Skamil
4111.50Skamil		sigemptyset(&set);
4121.50Skamil		sigaddset(&set, sigsent);
4131.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
4141.50Skamil
4151.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4161.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4171.50Skamil
4181.50Skamil		_exit(exitval);
4191.50Skamil	}
4201.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4211.50Skamil
4221.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4231.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4241.50Skamil
4251.50Skamil	validate_status_stopped(status, sigval);
4261.50Skamil
4271.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4281.61Skre	SYSCALL_REQUIRE(
4291.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4301.50Skamil
4311.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4321.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4331.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4341.50Skamil	    info.psi_siginfo.si_errno);
4351.50Skamil
4361.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4371.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4381.50Skamil
4391.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
4401.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4411.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4421.50Skamil
4431.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4441.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4451.50Skamil
4461.50Skamil	validate_status_exited(status, exitval);
4471.50Skamil
4481.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4491.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4501.50Skamil}
4511.50Skamil
4521.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
4531.61SkreATF_TC(test);								\
4541.61SkreATF_TC_HEAD(test, tc)							\
4551.61Skre{									\
4561.61Skre	atf_tc_set_md_var(tc, "descr",					\
4571.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
4581.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
4591.61Skre}									\
4601.61Skre									\
4611.61SkreATF_TC_BODY(test, tc)							\
4621.61Skre{									\
4631.61Skre									\
4641.61Skre	traceme_sendsignal_masked(sig);					\
4651.50Skamil}
4661.50Skamil
4671.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4681.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
4691.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
4701.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
4711.50Skamil
4721.50Skamil/// ----------------------------------------------------------------------------
4731.50Skamil
4741.50Skamilstatic void
4751.50Skamiltraceme_sendsignal_ignored(int sigsent)
4761.50Skamil{
4771.50Skamil	const int exitval = 5;
4781.50Skamil	const int sigval = SIGSTOP;
4791.50Skamil	pid_t child, wpid;
4801.50Skamil	struct sigaction sa;
4811.50Skamil#if defined(TWAIT_HAVE_STATUS)
4821.50Skamil	int status;
4831.50Skamil#endif
4841.61Skre	struct ptrace_siginfo info;
4851.50Skamil
4861.50Skamil	memset(&info, 0, sizeof(info));
4871.50Skamil
4881.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4891.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4901.50Skamil	if (child == 0) {
4911.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4921.61Skre
4931.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4941.50Skamil
4951.50Skamil		memset(&sa, 0, sizeof(sa));
4961.50Skamil		sa.sa_handler = SIG_IGN;
4971.50Skamil		sigemptyset(&sa.sa_mask);
4981.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
4991.50Skamil
5001.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5011.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5021.50Skamil
5031.50Skamil		_exit(exitval);
5041.50Skamil	}
5051.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5061.50Skamil
5071.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5081.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5091.50Skamil
5101.50Skamil	validate_status_stopped(status, sigval);
5111.50Skamil
5121.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5131.61Skre	SYSCALL_REQUIRE(
5141.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5151.50Skamil
5161.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5171.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5181.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5191.50Skamil	    info.psi_siginfo.si_errno);
5201.50Skamil
5211.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5221.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5231.50Skamil
5241.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
5251.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
5261.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5271.50Skamil
5281.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5291.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5301.50Skamil
5311.50Skamil	validate_status_exited(status, exitval);
5321.50Skamil
5331.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5341.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5351.50Skamil}
5361.50Skamil
5371.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
5381.61SkreATF_TC(test);								\
5391.61SkreATF_TC_HEAD(test, tc)							\
5401.61Skre{									\
5411.61Skre	atf_tc_set_md_var(tc, "descr",					\
5421.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
5431.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
5441.61Skre}									\
5451.61Skre									\
5461.61SkreATF_TC_BODY(test, tc)							\
5471.61Skre{									\
5481.61Skre									\
5491.61Skre	traceme_sendsignal_ignored(sig);				\
5501.50Skamil}
5511.50Skamil
5521.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
5531.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
5541.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
5551.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
5561.50Skamil
5571.50Skamil/// ----------------------------------------------------------------------------
5581.50Skamil
5591.50Skamilstatic void
5601.50Skamiltraceme_sendsignal_simple(int sigsent)
5611.1Skamil{
5621.35Skamil	const int sigval = SIGSTOP;
5631.35Skamil	int exitval = 0;
5641.1Skamil	pid_t child, wpid;
5651.1Skamil#if defined(TWAIT_HAVE_STATUS)
5661.1Skamil	int status;
5671.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
5681.1Skamil#endif
5691.61Skre	struct ptrace_siginfo info;
5701.1Skamil
5711.45Skamil	memset(&info, 0, sizeof(info));
5721.45Skamil
5731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
5741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
5751.1Skamil	if (child == 0) {
5761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5781.1Skamil
5791.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5801.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5811.1Skamil
5821.35Skamil		switch (sigsent) {
5831.35Skamil		case SIGCONT:
5841.48Skamil		case SIGSTOP:
5851.35Skamil			_exit(exitval);
5861.35Skamil		default:
5871.35Skamil			/* NOTREACHED */
5881.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5891.35Skamil		}
5901.1Skamil	}
5911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5921.1Skamil
5931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5951.1Skamil
5961.1Skamil	validate_status_stopped(status, sigval);
5971.1Skamil
5981.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5991.61Skre	SYSCALL_REQUIRE(
6001.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6011.45Skamil
6021.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6031.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6041.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6051.45Skamil	    info.psi_siginfo.si_errno);
6061.45Skamil
6071.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6081.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6091.45Skamil
6101.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
6111.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
6121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6131.1Skamil
6141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6161.1Skamil
6171.35Skamil	switch (sigsent) {
6181.48Skamil	case SIGSTOP:
6191.48Skamil		validate_status_stopped(status, sigsent);
6201.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
6211.61Skre		    "child\n");
6221.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
6231.61Skre		    sizeof(info)) != -1);
6241.48Skamil
6251.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6261.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
6271.61Skre		    "si_errno=%#x\n",
6281.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6291.61Skre		    info.psi_siginfo.si_errno);
6301.48Skamil
6311.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6321.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6331.48Skamil
6341.48Skamil		DPRINTF("Before resuming the child process where it left off "
6351.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
6361.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6371.48Skamil
6381.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6391.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
6401.61Skre		    child);
6411.48Skamil		/* FALLTHROUGH */
6421.35Skamil	case SIGCONT:
6431.35Skamil		validate_status_exited(status, exitval);
6441.35Skamil		break;
6451.35Skamil	default:
6461.35Skamil		validate_status_signaled(status, sigsent, expect_core);
6471.35Skamil		break;
6481.35Skamil	}
6491.1Skamil
6501.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6511.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6521.1Skamil}
6531.1Skamil
6541.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
6551.61SkreATF_TC(test);								\
6561.61SkreATF_TC_HEAD(test, tc)							\
6571.61Skre{									\
6581.61Skre	atf_tc_set_md_var(tc, "descr",					\
6591.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
6601.61Skre	    "handled correctly in a child without a signal handler");	\
6611.61Skre}									\
6621.61Skre									\
6631.61SkreATF_TC_BODY(test, tc)							\
6641.61Skre{									\
6651.61Skre									\
6661.61Skre	traceme_sendsignal_simple(sig);					\
6671.35Skamil}
6681.35Skamil
6691.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
6701.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
6711.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
6721.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
6731.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
6741.35Skamil
6751.35Skamil/// ----------------------------------------------------------------------------
6761.35Skamil
6771.37SkamilATF_TC(traceme_pid1_parent);
6781.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
6791.37Skamil{
6801.37Skamil	atf_tc_set_md_var(tc, "descr",
6811.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
6821.37Skamil}
6831.37Skamil
6841.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
6851.37Skamil{
6861.37Skamil	struct msg_fds parent_child;
6871.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
6881.37Skamil	pid_t child1, child2, wpid;
6891.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6901.37Skamil#if defined(TWAIT_HAVE_STATUS)
6911.37Skamil	int status;
6921.37Skamil#endif
6931.37Skamil
6941.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
6951.37Skamil
6961.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
6971.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
6981.37Skamil	if (child1 == 0) {
6991.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
7001.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
7011.37Skamil		if (child2 != 0) {
7021.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
7031.61Skre			    getpid(), child2);
7041.37Skamil			_exit(exitval_child1);
7051.37Skamil		}
7061.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
7071.37Skamil
7081.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
7091.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
7101.37Skamil
7111.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7121.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
7131.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
7141.37Skamil
7151.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
7161.37Skamil
7171.37Skamil		_exit(exitval_child2);
7181.37Skamil	}
7191.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
7201.37Skamil
7211.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7221.61Skre	TWAIT_REQUIRE_SUCCESS(
7231.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
7241.37Skamil
7251.37Skamil	validate_status_exited(status, exitval_child1);
7261.37Skamil
7271.37Skamil	DPRINTF("Notify that child1 is dead\n");
7281.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
7291.37Skamil
7301.37Skamil	DPRINTF("Wait for exiting of child2\n");
7311.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
7321.37Skamil}
7331.37Skamil
7341.37Skamil/// ----------------------------------------------------------------------------
7351.37Skamil
7361.40Skamilstatic void
7371.40Skamiltraceme_vfork_raise(int sigval)
7381.40Skamil{
7391.46Skamil	const int exitval = 5, exitval_watcher = 10;
7401.46Skamil	pid_t child, parent, watcher, wpid;
7411.46Skamil	int rv;
7421.40Skamil#if defined(TWAIT_HAVE_STATUS)
7431.40Skamil	int status;
7441.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
7451.40Skamil#endif
7461.40Skamil
7471.46Skamil	/*
7481.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
7491.46Skamil	 * the SIGKILL signal to it.
7501.46Skamil	 *
7511.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
7521.46Skamil	 * simpler to reparent this process to initproc and forget about it.
7531.46Skamil	 */
7541.46Skamil	if (sigval == SIGSTOP) {
7551.46Skamil		parent = getpid();
7561.46Skamil
7571.46Skamil		watcher = fork();
7581.46Skamil		ATF_REQUIRE(watcher != 1);
7591.46Skamil		if (watcher == 0) {
7601.46Skamil			/* Double fork(2) trick to reparent to initproc */
7611.46Skamil			watcher = fork();
7621.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
7631.46Skamil			if (watcher != 0)
7641.46Skamil				_exit(exitval_watcher);
7651.46Skamil
7661.46Skamil			child = await_stopped_child(parent);
7671.46Skamil
7681.46Skamil			errno = 0;
7691.46Skamil			rv = kill(child, SIGKILL);
7701.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
7711.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
7721.46Skamil
7731.46Skamil			/* This exit value will be collected by initproc */
7741.46Skamil			_exit(0);
7751.46Skamil		}
7761.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7771.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
7781.61Skre		    watcher);
7791.46Skamil
7801.46Skamil		validate_status_exited(status, exitval_watcher);
7811.46Skamil
7821.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7831.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
7841.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
7851.46Skamil	}
7861.46Skamil
7871.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7881.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
7891.40Skamil	if (child == 0) {
7901.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7911.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7921.40Skamil
7931.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7941.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7951.40Skamil
7961.40Skamil		switch (sigval) {
7971.46Skamil		case SIGSTOP:
7981.40Skamil		case SIGKILL:
7991.40Skamil		case SIGABRT:
8001.40Skamil		case SIGHUP:
8011.40Skamil			/* NOTREACHED */
8021.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
8031.40Skamil		default:
8041.40Skamil			DPRINTF("Before exiting of the child process\n");
8051.40Skamil			_exit(exitval);
8061.40Skamil		}
8071.40Skamil	}
8081.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8091.40Skamil
8101.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8111.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8121.40Skamil
8131.40Skamil	switch (sigval) {
8141.40Skamil	case SIGKILL:
8151.40Skamil	case SIGABRT:
8161.40Skamil	case SIGHUP:
8171.40Skamil		validate_status_signaled(status, sigval, expect_core);
8181.40Skamil		break;
8191.40Skamil	case SIGSTOP:
8201.46Skamil		validate_status_signaled(status, SIGKILL, 0);
8211.46Skamil		break;
8221.40Skamil	case SIGCONT:
8231.47Skamil	case SIGTSTP:
8241.47Skamil	case SIGTTIN:
8251.47Skamil	case SIGTTOU:
8261.40Skamil		validate_status_exited(status, exitval);
8271.40Skamil		break;
8281.40Skamil	default:
8291.40Skamil		/* NOTREACHED */
8301.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
8311.40Skamil		break;
8321.40Skamil	}
8331.40Skamil
8341.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8351.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8361.40Skamil}
8371.40Skamil
8381.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
8391.61SkreATF_TC(test);								\
8401.61SkreATF_TC_HEAD(test, tc)							\
8411.61Skre{									\
8421.61Skre	atf_tc_set_md_var(tc, "descr",					\
8431.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
8441.61Skre	    "vfork(2)ed child");					\
8451.61Skre}									\
8461.61Skre									\
8471.61SkreATF_TC_BODY(test, tc)							\
8481.61Skre{									\
8491.61Skre									\
8501.61Skre	traceme_vfork_raise(sig);					\
8511.40Skamil}
8521.40Skamil
8531.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
8541.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
8551.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
8561.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
8571.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
8581.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
8591.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
8601.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
8611.40Skamil
8621.40Skamil/// ----------------------------------------------------------------------------
8631.40Skamil
8641.52Skamilstatic void
8651.52Skamiltraceme_vfork_crash(int sig)
8661.41Skamil{
8671.41Skamil	pid_t child, wpid;
8681.41Skamil#if defined(TWAIT_HAVE_STATUS)
8691.41Skamil	int status;
8701.41Skamil#endif
8711.41Skamil
8721.63Skamil	if (sig == SIGBUS) {
8731.63Skamil		atf_tc_expect_fail("lib/53343");
8741.63Skamil	}
8751.63Skamil
8761.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8771.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
8781.41Skamil	if (child == 0) {
8791.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8801.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8811.41Skamil
8821.52Skamil		DPRINTF("Before executing a trap\n");
8831.52Skamil		switch (sig) {
8841.52Skamil		case SIGTRAP:
8851.52Skamil			trigger_trap();
8861.52Skamil			break;
8871.52Skamil		case SIGSEGV:
8881.52Skamil			trigger_segv();
8891.52Skamil			break;
8901.52Skamil		case SIGILL:
8911.52Skamil			trigger_ill();
8921.52Skamil			break;
8931.52Skamil		case SIGFPE:
8941.52Skamil			trigger_fpe();
8951.52Skamil			break;
8961.52Skamil		case SIGBUS:
8971.52Skamil			trigger_bus();
8981.52Skamil			break;
8991.52Skamil		default:
9001.52Skamil			/* NOTREACHED */
9011.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
9021.52Skamil		}
9031.41Skamil
9041.41Skamil		/* NOTREACHED */
9051.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
9061.41Skamil	}
9071.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9081.41Skamil
9091.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9101.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9111.41Skamil
9121.52Skamil	validate_status_signaled(status, sig, 1);
9131.41Skamil
9141.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9151.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9161.41Skamil}
9171.41Skamil
9181.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
9191.61SkreATF_TC(test);								\
9201.61SkreATF_TC_HEAD(test, tc)							\
9211.61Skre{									\
9221.61Skre	atf_tc_set_md_var(tc, "descr",					\
9231.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
9241.61Skre	    "vfork(2)ed child");					\
9251.61Skre}									\
9261.61Skre									\
9271.61SkreATF_TC_BODY(test, tc)							\
9281.61Skre{									\
9291.61Skre									\
9301.61Skre	traceme_vfork_crash(sig);					\
9311.52Skamil}
9321.52Skamil
9331.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
9341.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
9351.52Skamil//TRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
9361.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
9371.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
9381.52Skamil
9391.41Skamil/// ----------------------------------------------------------------------------
9401.41Skamil
9411.43SkamilATF_TC(traceme_vfork_exec);
9421.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
9431.43Skamil{
9441.43Skamil	atf_tc_set_md_var(tc, "descr",
9451.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
9461.43Skamil}
9471.43Skamil
9481.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
9491.43Skamil{
9501.43Skamil	const int sigval = SIGTRAP;
9511.43Skamil	pid_t child, wpid;
9521.43Skamil#if defined(TWAIT_HAVE_STATUS)
9531.43Skamil	int status;
9541.43Skamil#endif
9551.61Skre	struct ptrace_siginfo info;
9561.43Skamil
9571.43Skamil	memset(&info, 0, sizeof(info));
9581.43Skamil
9591.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9601.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
9611.43Skamil	if (child == 0) {
9621.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9631.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9641.43Skamil
9651.43Skamil		DPRINTF("Before calling execve(2) from child\n");
9661.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
9671.43Skamil
9681.43Skamil		/* NOTREACHED */
9691.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
9701.43Skamil	}
9711.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9721.43Skamil
9731.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9741.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9751.43Skamil
9761.43Skamil	validate_status_stopped(status, sigval);
9771.43Skamil
9781.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9791.61Skre	SYSCALL_REQUIRE(
9801.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9811.43Skamil
9821.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9831.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9841.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9851.43Skamil	    info.psi_siginfo.si_errno);
9861.43Skamil
9871.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9881.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
9891.43Skamil
9901.43Skamil	DPRINTF("Before resuming the child process where it left off and "
9911.43Skamil	    "without signal to be sent\n");
9921.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
9931.43Skamil
9941.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9951.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9961.43Skamil
9971.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9981.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9991.43Skamil}
10001.43Skamil
10011.43Skamil/// ----------------------------------------------------------------------------
10021.43Skamil
10031.1Skamil#if defined(TWAIT_HAVE_PID)
10041.51Skamilstatic void
10051.59Skamilunrelated_tracer_sees_crash(int sig)
10061.59Skamil{
10071.59Skamil	struct msg_fds parent_tracee, parent_tracer;
10081.59Skamil	const int exitval = 10;
10091.59Skamil	pid_t tracee, tracer, wpid;
10101.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10111.59Skamil#if defined(TWAIT_HAVE_STATUS)
10121.59Skamil	int status;
10131.59Skamil#endif
10141.59Skamil	struct ptrace_siginfo info;
10151.61Skre
10161.59Skamil	memset(&info, 0, sizeof(info));
10171.59Skamil
10181.59Skamil	DPRINTF("Spawn tracee\n");
10191.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10201.59Skamil	tracee = atf_utils_fork();
10211.59Skamil	if (tracee == 0) {
10221.59Skamil		// Wait for parent to let us crash
10231.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
10241.61Skre
10251.59Skamil		DPRINTF("Before executing a trap\n");
10261.59Skamil		switch (sig) {
10271.59Skamil		case SIGTRAP:
10281.59Skamil			trigger_trap();
10291.59Skamil			break;
10301.59Skamil		case SIGSEGV:
10311.59Skamil			trigger_segv();
10321.59Skamil			break;
10331.59Skamil		case SIGILL:
10341.59Skamil			trigger_ill();
10351.59Skamil			break;
10361.59Skamil		case SIGFPE:
10371.59Skamil			trigger_fpe();
10381.59Skamil			break;
10391.59Skamil		case SIGBUS:
10401.59Skamil			trigger_bus();
10411.59Skamil			break;
10421.59Skamil		default:
10431.59Skamil			/* NOTREACHED */
10441.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
10451.59Skamil		}
10461.59Skamil
10471.59Skamil		/* NOTREACHED */
10481.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
10491.59Skamil	}
10501.59Skamil
10511.59Skamil	DPRINTF("Spawn debugger\n");
10521.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10531.59Skamil	tracer = atf_utils_fork();
10541.59Skamil	if (tracer == 0) {
10551.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
10561.59Skamil		tracer = atf_utils_fork();
10571.59Skamil		if (tracer != 0)
10581.61Skre			_exit(exitval);
10591.59Skamil
10601.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10611.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10621.59Skamil
10631.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10641.59Skamil		FORKEE_REQUIRE_SUCCESS(
10651.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10661.59Skamil
10671.59Skamil		forkee_status_stopped(status, SIGSTOP);
10681.59Skamil
10691.59Skamil		/* Resume tracee with PT_CONTINUE */
10701.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10711.59Skamil
10721.59Skamil		/* Inform parent that tracer has attached to tracee */
10731.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
10741.59Skamil
10751.59Skamil		/* Wait for parent to tell use that tracee should have exited */
10761.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
10771.59Skamil
10781.59Skamil		/* Wait for tracee and assert that it exited */
10791.59Skamil		FORKEE_REQUIRE_SUCCESS(
10801.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10811.59Skamil
10821.59Skamil		validate_status_stopped(status, sig);
10831.59Skamil
10841.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
10851.61Skre		    "traced process\n");
10861.61Skre		SYSCALL_REQUIRE(
10871.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
10881.59Skamil
10891.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10901.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
10911.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
10921.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
10931.59Skamil
10941.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
10951.59Skamil		switch (sig) {
10961.59Skamil		case SIGTRAP:
10971.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
10981.59Skamil			break;
10991.59Skamil		case SIGSEGV:
11001.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
11011.59Skamil			break;
11021.59Skamil//		case SIGILL:
11031.59Skamil//			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_ILLOP);
11041.59Skamil//			break;
11051.59Skamil		case SIGFPE:
11061.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
11071.59Skamil			break;
11081.59Skamil		case SIGBUS:
11091.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
11101.59Skamil			break;
11111.59Skamil		}
11121.59Skamil
11131.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
11141.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
11151.61Skre		TWAIT_REQUIRE_SUCCESS(
11161.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11171.59Skamil
11181.59Skamil		validate_status_signaled(status, SIGKILL, 0);
11191.59Skamil
11201.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
11211.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
11221.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
11231.59Skamil
11241.59Skamil		DPRINTF("Before exiting of the tracer process\n");
11251.59Skamil		_exit(0 /* collect by initproc */);
11261.59Skamil	}
11271.59Skamil
11281.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
11291.59Skamil	    "calling %s()\n", TWAIT_FNAME);
11301.59Skamil	TWAIT_REQUIRE_SUCCESS(
11311.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
11321.59Skamil
11331.59Skamil	validate_status_exited(status, exitval);
11341.59Skamil
11351.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
11361.59Skamil	    TWAIT_FNAME);
11371.59Skamil	TWAIT_REQUIRE_SUCCESS(
11381.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
11391.59Skamil
11401.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
11411.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
11421.59Skamil
11431.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
11441.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
11451.59Skamil
11461.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
11471.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11481.59Skamil
11491.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11501.59Skamil	    TWAIT_FNAME);
11511.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11521.59Skamil
11531.59Skamil	validate_status_signaled(status, SIGKILL, 0);
11541.59Skamil
11551.59Skamil	msg_close(&parent_tracer);
11561.59Skamil	msg_close(&parent_tracee);
11571.59Skamil}
11581.59Skamil
11591.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
11601.61SkreATF_TC(test);								\
11611.61SkreATF_TC_HEAD(test, tc)							\
11621.61Skre{									\
11631.61Skre	atf_tc_set_md_var(tc, "descr",					\
11641.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
11651.61Skre	    "debuggee");						\
11661.61Skre}									\
11671.61Skre									\
11681.61SkreATF_TC_BODY(test, tc)							\
11691.61Skre{									\
11701.61Skre									\
11711.61Skre	unrelated_tracer_sees_crash(sig);				\
11721.59Skamil}
11731.59Skamil
11741.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
11751.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
11761.59Skamil//UNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
11771.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
11781.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
11791.59Skamil#endif
11801.59Skamil
11811.59Skamil/// ----------------------------------------------------------------------------
11821.59Skamil
11831.59Skamil#if defined(TWAIT_HAVE_PID)
11841.59Skamilstatic void
11851.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
11861.67Skamil                                             bool stopped)
11871.1Skamil{
11881.51Skamil	/*
11891.51Skamil	 * notimeout - disable timeout in await zombie function
11901.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
11911.67Skamil	 * stopped - attach to a stopped process
11921.51Skamil	 */
11931.1Skamil
11941.1Skamil	struct msg_fds parent_tracee, parent_tracer;
11951.1Skamil	const int exitval_tracee = 5;
11961.1Skamil	const int exitval_tracer = 10;
11971.1Skamil	pid_t tracee, tracer, wpid;
11981.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11991.1Skamil#if defined(TWAIT_HAVE_STATUS)
12001.1Skamil	int status;
12011.1Skamil#endif
12021.1Skamil
12031.67Skamil	/*
12041.67Skamil	 * Only a subset of options are supported.
12051.67Skamil	 */
12061.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
12071.67Skamil	            (!notimeout && unrelated && !stopped) ||
12081.67Skamil	            (notimeout && !unrelated && !stopped) ||
12091.67Skamil	            (!notimeout && unrelated && stopped));
12101.67Skamil
12111.13Schristos	DPRINTF("Spawn tracee\n");
12121.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
12131.1Skamil	tracee = atf_utils_fork();
12141.1Skamil	if (tracee == 0) {
12151.67Skamil		if (stopped) {
12161.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
12171.67Skamil			raise(SIGSTOP);
12181.67Skamil		}
12191.67Skamil
12201.1Skamil		// Wait for parent to let us exit
12211.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
12221.1Skamil		_exit(exitval_tracee);
12231.1Skamil	}
12241.1Skamil
12251.13Schristos	DPRINTF("Spawn debugger\n");
12261.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
12271.1Skamil	tracer = atf_utils_fork();
12281.1Skamil	if (tracer == 0) {
12291.51Skamil		if(unrelated) {
12301.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
12311.51Skamil			tracer = atf_utils_fork();
12321.51Skamil			if (tracer != 0)
12331.51Skamil				_exit(exitval_tracer);
12341.51Skamil		}
12351.51Skamil
12361.67Skamil		if (stopped) {
12371.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
12381.67Skamil			await_stopped(tracee);
12391.67Skamil		}
12401.67Skamil
12411.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12421.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12431.1Skamil
12441.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12451.1Skamil		FORKEE_REQUIRE_SUCCESS(
12461.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12471.1Skamil
12481.1Skamil		forkee_status_stopped(status, SIGSTOP);
12491.1Skamil
12501.1Skamil		/* Resume tracee with PT_CONTINUE */
12511.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
12521.1Skamil
12531.1Skamil		/* Inform parent that tracer has attached to tracee */
12541.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12551.1Skamil
12561.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12571.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12581.1Skamil
12591.1Skamil		/* Wait for tracee and assert that it exited */
12601.1Skamil		FORKEE_REQUIRE_SUCCESS(
12611.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12621.1Skamil
12631.1Skamil		forkee_status_exited(status, exitval_tracee);
12641.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
12651.1Skamil
12661.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12671.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
12681.51Skamil	}
12691.51Skamil
12701.51Skamil	if (unrelated) {
12711.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
12721.51Skamil		    "calling %s()\n", TWAIT_FNAME);
12731.51Skamil		TWAIT_REQUIRE_SUCCESS(
12741.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
12751.51Skamil
12761.51Skamil		validate_status_exited(status, exitval_tracer);
12771.51Skamil
12781.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
12791.51Skamil		    TWAIT_FNAME);
12801.51Skamil		TWAIT_REQUIRE_SUCCESS(
12811.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
12821.1Skamil	}
12831.1Skamil
12841.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
12851.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
12861.1Skamil
12871.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
12881.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
12891.1Skamil
12901.13Schristos	DPRINTF("Detect that tracee is zombie\n");
12911.51Skamil	if (notimeout)
12921.26Skamil		await_zombie_raw(tracee, 0);
12931.26Skamil	else
12941.26Skamil		await_zombie(tracee);
12951.1Skamil
12961.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
12971.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
12981.1Skamil	    TWAIT_FNAME);
12991.1Skamil	TWAIT_REQUIRE_SUCCESS(
13001.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
13011.1Skamil
13021.51Skamil	if (unrelated) {
13031.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
13041.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
13051.51Skamil	} else {
13061.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
13071.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
13081.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
13091.59Skamil			"%s()\n", TWAIT_FNAME);
13101.51Skamil
13111.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
13121.59Skamil			"tracee\n");
13131.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
13141.51Skamil		    tracer);
13151.1Skamil
13161.51Skamil		validate_status_exited(status, exitval_tracer);
13171.51Skamil	}
13181.1Skamil
13191.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
13201.1Skamil	    TWAIT_FNAME);
13211.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13221.1Skamil
13231.1Skamil	validate_status_exited(status, exitval_tracee);
13241.1Skamil
13251.1Skamil	msg_close(&parent_tracer);
13261.1Skamil	msg_close(&parent_tracee);
13271.1Skamil}
13281.26Skamil
13291.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
13301.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
13311.51Skamil{
13321.51Skamil	atf_tc_set_md_var(tc, "descr",
13331.51Skamil	    "Assert that tracer sees process termination before the parent");
13341.51Skamil}
13351.51Skamil
13361.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
13371.26Skamil{
13381.26Skamil
13391.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
13401.26Skamil}
13411.26Skamil
13421.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
13431.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
13441.1Skamil{
13451.1Skamil	atf_tc_set_md_var(tc, "descr",
13461.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
13471.51Skamil	    "process and no other error is reported");
13481.1Skamil}
13491.1Skamil
13501.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
13511.1Skamil{
13521.51Skamil	time_t start, end;
13531.51Skamil	double diff;
13541.51Skamil	unsigned long N = 0;
13551.1Skamil
13561.51Skamil	/*
13571.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
13581.51Skamil	 * This test body isn't specific to this race, however it's just good
13591.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
13601.51Skamil	 */
13611.1Skamil
13621.51Skamil	start = time(NULL);
13631.51Skamil	while (true) {
13641.51Skamil		DPRINTF("Step: %lu\n", N);
13651.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
13661.67Skamil		                                             false);
13671.51Skamil		end = time(NULL);
13681.51Skamil		diff = difftime(end, start);
13691.51Skamil		if (diff >= 5.0)
13701.51Skamil			break;
13711.51Skamil		++N;
13721.1Skamil	}
13731.51Skamil	DPRINTF("Iterations: %lu\n", N);
13741.51Skamil}
13751.1Skamil
13761.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
13771.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13781.51Skamil{
13791.51Skamil	atf_tc_set_md_var(tc, "descr",
13801.51Skamil	    "Assert that tracer sees process termination before the parent");
13811.51Skamil}
13821.1Skamil
13831.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13841.51Skamil{
13851.1Skamil
13861.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
13871.67Skamil}
13881.67Skamil
13891.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
13901.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
13911.67Skamil{
13921.67Skamil	atf_tc_set_md_var(tc, "descr",
13931.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
13941.67Skamil}
13951.67Skamil
13961.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
13971.67Skamil{
13981.67Skamil
13991.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
14001.1Skamil}
14011.1Skamil#endif
14021.1Skamil
14031.51Skamil/// ----------------------------------------------------------------------------
14041.51Skamil
14051.66Skamilstatic void
14061.66Skamilparent_attach_to_its_child(bool stopped)
14071.1Skamil{
14081.1Skamil	struct msg_fds parent_tracee;
14091.1Skamil	const int exitval_tracee = 5;
14101.1Skamil	pid_t tracee, wpid;
14111.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
14121.1Skamil#if defined(TWAIT_HAVE_STATUS)
14131.1Skamil	int status;
14141.1Skamil#endif
14151.1Skamil
14161.13Schristos	DPRINTF("Spawn tracee\n");
14171.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
14181.1Skamil	tracee = atf_utils_fork();
14191.1Skamil	if (tracee == 0) {
14201.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
14211.13Schristos		DPRINTF("Parent should now attach to tracee\n");
14221.1Skamil
14231.66Skamil		if (stopped) {
14241.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
14251.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
14261.66Skamil		}
14271.66Skamil
14281.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
14291.1Skamil		/* Wait for message from the parent */
14301.1Skamil		_exit(exitval_tracee);
14311.1Skamil	}
14321.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
14331.57Skamil
14341.66Skamil	if (stopped) {
14351.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
14361.66Skamil		await_stopped(tracee);
14371.66Skamil	}
14381.66Skamil
14391.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
14401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
14411.1Skamil
14421.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
14431.1Skamil	    TWAIT_FNAME);
14441.1Skamil	TWAIT_REQUIRE_SUCCESS(
14451.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14461.1Skamil
14471.1Skamil	validate_status_stopped(status, SIGSTOP);
14481.1Skamil
14491.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
14501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
14511.1Skamil
14521.13Schristos	DPRINTF("Let the tracee exit now\n");
14531.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
14541.1Skamil
14551.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
14561.1Skamil	TWAIT_REQUIRE_SUCCESS(
14571.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14581.1Skamil
14591.1Skamil	validate_status_exited(status, exitval_tracee);
14601.1Skamil
14611.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
14621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
14631.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
14641.1Skamil
14651.1Skamil	msg_close(&parent_tracee);
14661.1Skamil}
14671.1Skamil
14681.66SkamilATF_TC(parent_attach_to_its_child);
14691.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
14701.66Skamil{
14711.66Skamil	atf_tc_set_md_var(tc, "descr",
14721.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
14731.66Skamil}
14741.66Skamil
14751.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
14761.66Skamil{
14771.66Skamil
14781.66Skamil	parent_attach_to_its_child(false);
14791.66Skamil}
14801.66Skamil
14811.66SkamilATF_TC(parent_attach_to_its_stopped_child);
14821.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
14831.66Skamil{
14841.66Skamil	atf_tc_set_md_var(tc, "descr",
14851.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
14861.66Skamil}
14871.66Skamil
14881.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
14891.66Skamil{
14901.66Skamil
14911.66Skamil	parent_attach_to_its_child(true);
14921.66Skamil}
14931.66Skamil
14941.51Skamil/// ----------------------------------------------------------------------------
14951.51Skamil
14961.65Skamilstatic void
14971.65Skamilchild_attach_to_its_parent(bool stopped)
14981.1Skamil{
14991.1Skamil	struct msg_fds parent_tracee;
15001.1Skamil	const int exitval_tracer = 5;
15011.1Skamil	pid_t tracer, wpid;
15021.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15031.1Skamil#if defined(TWAIT_HAVE_STATUS)
15041.1Skamil	int status;
15051.1Skamil#endif
15061.1Skamil
15071.13Schristos	DPRINTF("Spawn tracer\n");
15081.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15091.1Skamil	tracer = atf_utils_fork();
15101.1Skamil	if (tracer == 0) {
15111.1Skamil		/* Wait for message from the parent */
15121.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
15131.1Skamil
15141.65Skamil		if (stopped) {
15151.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
15161.65Skamil			        getppid());
15171.65Skamil			await_stopped(getppid());
15181.65Skamil		}
15191.65Skamil
15201.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
15211.1Skamil		    getppid());
15221.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
15231.1Skamil
15241.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
15251.1Skamil		    TWAIT_FNAME);
15261.1Skamil		FORKEE_REQUIRE_SUCCESS(
15271.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
15281.1Skamil
15291.1Skamil		forkee_status_stopped(status, SIGSTOP);
15301.1Skamil
15311.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
15321.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
15331.1Skamil		    != -1);
15341.1Skamil
15351.1Skamil		/* Tell parent we are ready */
15361.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
15371.1Skamil
15381.1Skamil		_exit(exitval_tracer);
15391.1Skamil	}
15401.1Skamil
15411.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
15421.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
15431.65Skamil
15441.65Skamil	if (stopped) {
15451.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
15461.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
15471.65Skamil	}
15481.65Skamil
15491.13Schristos	DPRINTF("Allow the tracer to exit now\n");
15501.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
15511.1Skamil
15521.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
15531.1Skamil	TWAIT_REQUIRE_SUCCESS(
15541.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
15551.1Skamil
15561.1Skamil	validate_status_exited(status, exitval_tracer);
15571.1Skamil
15581.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
15591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
15601.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
15611.1Skamil
15621.1Skamil	msg_close(&parent_tracee);
15631.1Skamil}
15641.1Skamil
15651.65SkamilATF_TC(child_attach_to_its_parent);
15661.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
15671.65Skamil{
15681.65Skamil	atf_tc_set_md_var(tc, "descr",
15691.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
15701.65Skamil}
15711.65Skamil
15721.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
15731.65Skamil{
15741.65Skamil
15751.65Skamil	child_attach_to_its_parent(false);
15761.65Skamil}
15771.65Skamil
15781.65SkamilATF_TC(child_attach_to_its_stopped_parent);
15791.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
15801.65Skamil{
15811.65Skamil	atf_tc_set_md_var(tc, "descr",
15821.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
15831.65Skamil}
15841.65Skamil
15851.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
15861.65Skamil{
15871.65Skamil	/*
15881.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
15891.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
15901.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
15911.65Skamil	 *
15921.65Skamil	 * As a workaround spawn this test as a subprocess.
15931.65Skamil	 */
15941.65Skamil
15951.65Skamil	const int exitval = 15;
15961.65Skamil	pid_t child, wpid;
15971.65Skamil#if defined(TWAIT_HAVE_STATUS)
15981.65Skamil	int status;
15991.65Skamil#endif
16001.65Skamil
16011.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
16021.65Skamil	if (child == 0) {
16031.65Skamil		child_attach_to_its_parent(true);
16041.65Skamil		_exit(exitval);
16051.65Skamil	} else {
16061.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16071.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16081.65Skamil
16091.65Skamil		validate_status_exited(status, exitval);
16101.65Skamil
16111.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
16121.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16131.65Skamil	}
16141.65Skamil}
16151.65Skamil
16161.51Skamil/// ----------------------------------------------------------------------------
16171.51Skamil
16181.1Skamil#if defined(TWAIT_HAVE_PID)
16191.1Skamil
16201.51Skamilenum tracee_sees_its_original_parent_type {
16211.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
16221.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
16231.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
16241.51Skamil};
16251.51Skamil
16261.51Skamilstatic void
16271.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
16281.1Skamil{
16291.1Skamil	struct msg_fds parent_tracer, parent_tracee;
16301.1Skamil	const int exitval_tracee = 5;
16311.1Skamil	const int exitval_tracer = 10;
16321.1Skamil	pid_t parent, tracee, tracer, wpid;
16331.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
16341.1Skamil#if defined(TWAIT_HAVE_STATUS)
16351.1Skamil	int status;
16361.1Skamil#endif
16371.51Skamil	/* sysctl(3) - kinfo_proc2 */
16381.51Skamil	int name[CTL_MAXNAME];
16391.51Skamil	struct kinfo_proc2 kp;
16401.51Skamil	size_t len = sizeof(kp);
16411.51Skamil	unsigned int namelen;
16421.51Skamil
16431.51Skamil	/* procfs - status  */
16441.51Skamil	FILE *fp;
16451.51Skamil	struct stat st;
16461.51Skamil	const char *fname = "/proc/curproc/status";
16471.51Skamil	char s_executable[MAXPATHLEN];
16481.51Skamil	int s_pid, s_ppid;
16491.51Skamil	int rv;
16501.51Skamil
16511.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
16521.61Skre		SYSCALL_REQUIRE(
16531.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
16541.61Skre		if (rv != 0)
16551.51Skamil			atf_tc_skip("/proc/curproc/status not found");
16561.51Skamil	}
16571.1Skamil
16581.13Schristos	DPRINTF("Spawn tracee\n");
16591.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
16601.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
16611.1Skamil	tracee = atf_utils_fork();
16621.1Skamil	if (tracee == 0) {
16631.1Skamil		parent = getppid();
16641.1Skamil
16651.1Skamil		/* Emit message to the parent */
16661.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
16671.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
16681.1Skamil
16691.51Skamil		switch (type) {
16701.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
16711.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
16721.51Skamil			break;
16731.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
16741.51Skamil			namelen = 0;
16751.51Skamil			name[namelen++] = CTL_KERN;
16761.51Skamil			name[namelen++] = KERN_PROC2;
16771.51Skamil			name[namelen++] = KERN_PROC_PID;
16781.51Skamil			name[namelen++] = getpid();
16791.51Skamil			name[namelen++] = len;
16801.51Skamil			name[namelen++] = 1;
16811.51Skamil
16821.61Skre			FORKEE_ASSERT_EQ(
16831.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
16841.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
16851.51Skamil			break;
16861.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
16871.51Skamil			/*
16881.51Skamil			 * Format:
16891.51Skamil			 *  EXECUTABLE PID PPID ...
16901.51Skamil			 */
16911.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
16921.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
16931.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
16941.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
16951.51Skamil			break;
16961.51Skamil		}
16971.1Skamil
16981.1Skamil		_exit(exitval_tracee);
16991.1Skamil	}
17001.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
17011.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
17021.1Skamil
17031.13Schristos	DPRINTF("Spawn debugger\n");
17041.1Skamil	tracer = atf_utils_fork();
17051.1Skamil	if (tracer == 0) {
17061.1Skamil		/* No IPC to communicate with the child */
17071.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
17081.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
17091.1Skamil
17101.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
17111.1Skamil		FORKEE_REQUIRE_SUCCESS(
17121.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17131.1Skamil
17141.1Skamil		forkee_status_stopped(status, SIGSTOP);
17151.1Skamil
17161.1Skamil		/* Resume tracee with PT_CONTINUE */
17171.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
17181.1Skamil
17191.1Skamil		/* Inform parent that tracer has attached to tracee */
17201.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
17211.1Skamil
17221.1Skamil		/* Wait for parent to tell use that tracee should have exited */
17231.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
17241.1Skamil
17251.1Skamil		/* Wait for tracee and assert that it exited */
17261.1Skamil		FORKEE_REQUIRE_SUCCESS(
17271.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17281.1Skamil
17291.1Skamil		forkee_status_exited(status, exitval_tracee);
17301.1Skamil
17311.13Schristos		DPRINTF("Before exiting of the tracer process\n");
17321.1Skamil		_exit(exitval_tracer);
17331.1Skamil	}
17341.1Skamil
17351.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
17361.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
17371.1Skamil
17381.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
17391.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
17401.1Skamil
17411.13Schristos	DPRINTF("Detect that tracee is zombie\n");
17421.1Skamil	await_zombie(tracee);
17431.1Skamil
17441.13Schristos	DPRINTF("Assert that there is no status about tracee - "
17451.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
17461.1Skamil	TWAIT_REQUIRE_SUCCESS(
17471.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
17481.1Skamil
17491.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
17501.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
17511.1Skamil
17521.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
17531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
17541.1Skamil	    tracer);
17551.1Skamil
17561.1Skamil	validate_status_exited(status, exitval_tracer);
17571.1Skamil
17581.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
17591.1Skamil	    TWAIT_FNAME);
17601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
17611.1Skamil	    tracee);
17621.1Skamil
17631.1Skamil	validate_status_exited(status, exitval_tracee);
17641.1Skamil
17651.1Skamil	msg_close(&parent_tracer);
17661.1Skamil	msg_close(&parent_tracee);
17671.1Skamil}
17681.1Skamil
17691.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
17701.61SkreATF_TC(test);								\
17711.61SkreATF_TC_HEAD(test, tc)							\
17721.61Skre{									\
17731.61Skre	atf_tc_set_md_var(tc, "descr",					\
17741.61Skre	    "Assert that tracee sees its original parent when being traced " \
17751.61Skre	    "(check " descr ")");					\
17761.61Skre}									\
17771.61Skre									\
17781.61SkreATF_TC_BODY(test, tc)							\
17791.61Skre{									\
17801.61Skre									\
17811.61Skre	tracee_sees_its_original_parent(type);				\
17821.1Skamil}
17831.1Skamil
17841.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
17851.51Skamil	tracee_sees_its_original_parent_getppid,
17861.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
17871.51Skamil	"getppid(2)");
17881.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
17891.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
17901.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
17911.51Skamil	"sysctl(3) and kinfo_proc2");
17921.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
17931.51Skamil	tracee_sees_its_original_parent_procfs_status,
17941.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
17951.51Skamil	"the status file in procfs");
17961.1Skamil#endif
17971.1Skamil
17981.51Skamil/// ----------------------------------------------------------------------------
17991.1Skamil
18001.53Skamilstatic void
18011.53Skamileventmask_preserved(int event)
18021.1Skamil{
18031.1Skamil	const int exitval = 5;
18041.1Skamil	const int sigval = SIGSTOP;
18051.1Skamil	pid_t child, wpid;
18061.1Skamil#if defined(TWAIT_HAVE_STATUS)
18071.1Skamil	int status;
18081.1Skamil#endif
18091.1Skamil	ptrace_event_t set_event, get_event;
18101.1Skamil	const int len = sizeof(ptrace_event_t);
18111.1Skamil
18121.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18131.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18141.1Skamil	if (child == 0) {
18151.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18161.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18171.1Skamil
18181.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18191.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18201.1Skamil
18211.13Schristos		DPRINTF("Before exiting of the child process\n");
18221.1Skamil		_exit(exitval);
18231.1Skamil	}
18241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18251.1Skamil
18261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18281.1Skamil
18291.1Skamil	validate_status_stopped(status, sigval);
18301.1Skamil
18311.53Skamil	set_event.pe_set_event = event;
18321.61Skre	SYSCALL_REQUIRE(
18331.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
18341.61Skre	SYSCALL_REQUIRE(
18351.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
18361.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
18371.1Skamil
18381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18391.1Skamil	    "without signal to be sent\n");
18401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18411.1Skamil
18421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18441.1Skamil
18451.1Skamil	validate_status_exited(status, exitval);
18461.1Skamil
18471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18491.1Skamil}
18501.1Skamil
18511.61Skre#define EVENTMASK_PRESERVED(test, event)				\
18521.61SkreATF_TC(test);								\
18531.61SkreATF_TC_HEAD(test, tc)							\
18541.61Skre{									\
18551.61Skre	atf_tc_set_md_var(tc, "descr",					\
18561.61Skre	    "Verify that eventmask " #event " is preserved");		\
18571.61Skre}									\
18581.61Skre									\
18591.61SkreATF_TC_BODY(test, tc)							\
18601.61Skre{									\
18611.61Skre									\
18621.61Skre	eventmask_preserved(event);					\
18631.1Skamil}
18641.1Skamil
18651.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
18661.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
18671.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
18681.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
18691.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
18701.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
18711.1Skamil
18721.53Skamil/// ----------------------------------------------------------------------------
18731.1Skamil
18741.28Skamilstatic void
18751.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
18761.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
18771.1Skamil{
18781.1Skamil	const int exitval = 5;
18791.1Skamil	const int exitval2 = 15;
18801.1Skamil	const int sigval = SIGSTOP;
18811.31Skamil	pid_t child, child2 = 0, wpid;
18821.1Skamil#if defined(TWAIT_HAVE_STATUS)
18831.1Skamil	int status;
18841.1Skamil#endif
18851.1Skamil	ptrace_state_t state;
18861.1Skamil	const int slen = sizeof(state);
18871.1Skamil	ptrace_event_t event;
18881.1Skamil	const int elen = sizeof(event);
18891.1Skamil
18901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18921.1Skamil	if (child == 0) {
18931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18951.1Skamil
18961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18981.1Skamil
18991.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
19001.1Skamil
19011.1Skamil		if (child2 == 0)
19021.1Skamil			_exit(exitval2);
19031.1Skamil
19041.1Skamil		FORKEE_REQUIRE_SUCCESS
19051.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
19061.1Skamil
19071.1Skamil		forkee_status_exited(status, exitval2);
19081.1Skamil
19091.13Schristos		DPRINTF("Before exiting of the child process\n");
19101.1Skamil		_exit(exitval);
19111.1Skamil	}
19121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19131.1Skamil
19141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19161.1Skamil
19171.1Skamil	validate_status_stopped(status, sigval);
19181.1Skamil
19191.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
19201.61Skre	    trackfork ? "|PTRACE_FORK" : "",
19211.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
19221.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
19231.30Skamil	event.pe_set_event = 0;
19241.30Skamil	if (trackfork)
19251.30Skamil		event.pe_set_event |= PTRACE_FORK;
19261.30Skamil	if (trackvfork)
19271.30Skamil		event.pe_set_event |= PTRACE_VFORK;
19281.30Skamil	if (trackvforkdone)
19291.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
19301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
19311.1Skamil
19321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19331.1Skamil	    "without signal to be sent\n");
19341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19351.1Skamil
19361.29Skamil#if defined(TWAIT_HAVE_PID)
19371.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
19381.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
19391.61Skre		    child);
19401.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
19411.61Skre		    child);
19421.1Skamil
19431.29Skamil		validate_status_stopped(status, SIGTRAP);
19441.1Skamil
19451.61Skre		SYSCALL_REQUIRE(
19461.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
19471.31Skamil		if (trackfork && fn == fork) {
19481.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
19491.30Skamil			       PTRACE_FORK);
19501.30Skamil		}
19511.31Skamil		if (trackvfork && fn == vfork) {
19521.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
19531.30Skamil			       PTRACE_VFORK);
19541.30Skamil		}
19551.29Skamil
19561.29Skamil		child2 = state.pe_other_pid;
19571.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
19581.29Skamil
19591.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
19601.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
19611.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
19621.29Skamil		    child2);
19631.1Skamil
19641.29Skamil		validate_status_stopped(status, SIGTRAP);
19651.1Skamil
19661.61Skre		SYSCALL_REQUIRE(
19671.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
19681.31Skamil		if (trackfork && fn == fork) {
19691.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
19701.30Skamil			       PTRACE_FORK);
19711.30Skamil		}
19721.31Skamil		if (trackvfork && fn == vfork) {
19731.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
19741.30Skamil			       PTRACE_VFORK);
19751.30Skamil		}
19761.30Skamil
19771.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
19781.29Skamil
19791.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
19801.29Skamil		    "and without signal to be sent\n");
19811.61Skre		SYSCALL_REQUIRE(
19821.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
19831.29Skamil
19841.29Skamil		DPRINTF("Before resuming the child process where it left off "
19851.61Skre		    "and without signal to be sent\n");
19861.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19871.30Skamil	}
19881.30Skamil#endif
19891.30Skamil
19901.31Skamil	if (trackvforkdone && fn == vfork) {
19911.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
19921.61Skre		    child);
19931.61Skre		TWAIT_REQUIRE_SUCCESS(
19941.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
19951.30Skamil
19961.30Skamil		validate_status_stopped(status, SIGTRAP);
19971.30Skamil
19981.61Skre		SYSCALL_REQUIRE(
19991.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
20001.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
20011.30Skamil
20021.30Skamil		child2 = state.pe_other_pid;
20031.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
20041.61Skre		    child2);
20051.30Skamil
20061.30Skamil		DPRINTF("Before resuming the child process where it left off "
20071.61Skre		    "and without signal to be sent\n");
20081.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20091.30Skamil	}
20101.29Skamil
20111.30Skamil#if defined(TWAIT_HAVE_PID)
20121.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
20131.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
20141.61Skre		    "\n", TWAIT_FNAME);
20151.61Skre		TWAIT_REQUIRE_SUCCESS(
20161.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
20171.29Skamil
20181.29Skamil		validate_status_exited(status, exitval2);
20191.29Skamil
20201.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
20211.61Skre		    "process\n", TWAIT_FNAME);
20221.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
20231.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
20241.29Skamil	}
20251.29Skamil#endif
20261.1Skamil
20271.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
20281.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
20291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20301.1Skamil
20311.1Skamil	validate_status_stopped(status, SIGCHLD);
20321.1Skamil
20331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20341.1Skamil	    "without signal to be sent\n");
20351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20361.1Skamil
20371.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
20381.1Skamil	    TWAIT_FNAME);
20391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20401.1Skamil
20411.1Skamil	validate_status_exited(status, exitval);
20421.1Skamil
20431.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
20441.1Skamil	    TWAIT_FNAME);
20451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20461.1Skamil}
20471.28Skamil
20481.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
20491.61SkreATF_TC(name);								\
20501.61SkreATF_TC_HEAD(name, tc)							\
20511.61Skre{									\
20521.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
20531.61Skre}									\
20541.61Skre									\
20551.61SkreATF_TC_BODY(name, tc)							\
20561.61Skre{									\
20571.61Skre									\
20581.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
20591.32Skamil}
20601.32Skamil
20611.32Skamil#define F false
20621.32Skamil#define T true
20631.32Skamil
20641.32Skamil#define F_IF__0(x)
20651.32Skamil#define F_IF__1(x) x
20661.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
20671.32Skamil#define F_IF_(x,y) F_IF__(x,y)
20681.32Skamil#define F_IF(x,y) F_IF_(x,y)
20691.32Skamil
20701.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
20711.61Skre	"Verify " #function "(2) called with 0"				\
20721.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
20731.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
20741.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
20751.61Skre	" in EVENT_MASK."						\
20761.61Skre	F_IF(dchildbit," Detach child in this test.")			\
20771.61Skre	F_IF(dparentbit," Detach parent in this test.")
20781.1Skamil
20791.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
20801.31Skamil#if defined(TWAIT_HAVE_PID)
20811.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
20821.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
20831.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
20841.31Skamil#endif
20851.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
20861.31Skamil#if defined(TWAIT_HAVE_PID)
20871.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
20881.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
20891.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
20901.31Skamil#endif
20911.1Skamil
20921.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
20931.31Skamil#if defined(TWAIT_HAVE_PID)
20941.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
20951.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
20961.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
20971.31Skamil#endif
20981.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
20991.31Skamil#if defined(TWAIT_HAVE_PID)
21001.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
21011.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
21021.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
21031.31Skamil#endif
21041.31Skamil
21051.54Skamil/// ----------------------------------------------------------------------------
21061.31Skamil
21071.54Skamilenum bytes_transfer_type {
21081.54Skamil	BYTES_TRANSFER_DATA,
21091.54Skamil	BYTES_TRANSFER_DATAIO,
21101.54Skamil	BYTES_TRANSFER_TEXT,
21111.54Skamil	BYTES_TRANSFER_TEXTIO,
21121.54Skamil	BYTES_TRANSFER_AUXV
21131.54Skamil};
21141.31Skamil
21151.54Skamilstatic int __used
21161.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
21171.54Skamil{
21181.54Skamil	int e, f, g, h;
21191.1Skamil
21201.54Skamil	a *= 4;
21211.54Skamil	b += 3;
21221.54Skamil	c -= 2;
21231.54Skamil	d /= 1;
21241.1Skamil
21251.54Skamil	e = strtol("10", NULL, 10);
21261.54Skamil	f = strtol("20", NULL, 10);
21271.54Skamil	g = strtol("30", NULL, 10);
21281.54Skamil	h = strtol("40", NULL, 10);
21291.1Skamil
21301.54Skamil	return (a + b * c - d) + (e * f - g / h);
21311.1Skamil}
21321.1Skamil
21331.54Skamilstatic void
21341.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
21351.1Skamil{
21361.1Skamil	const int exitval = 5;
21371.1Skamil	const int sigval = SIGSTOP;
21381.1Skamil	pid_t child, wpid;
21391.54Skamil	bool skip = false;
21401.1Skamil
21411.54Skamil	int lookup_me = 0;
21421.54Skamil	uint8_t lookup_me8 = 0;
21431.54Skamil	uint16_t lookup_me16 = 0;
21441.54Skamil	uint32_t lookup_me32 = 0;
21451.54Skamil	uint64_t lookup_me64 = 0;
21461.1Skamil
21471.54Skamil	int magic = 0x13579246;
21481.54Skamil	uint8_t magic8 = 0xab;
21491.54Skamil	uint16_t magic16 = 0x1234;
21501.54Skamil	uint32_t magic32 = 0x98765432;
21511.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
21521.1Skamil
21531.54Skamil	struct ptrace_io_desc io;
21541.1Skamil#if defined(TWAIT_HAVE_STATUS)
21551.1Skamil	int status;
21561.1Skamil#endif
21571.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
21581.60Skre	AuxInfo ai[513], *aip;
21591.55Schristos
21601.55Schristos	ATF_REQUIRE(size < sizeof(ai));
21611.1Skamil
21621.54Skamil	/* Prepare variables for .TEXT transfers */
21631.54Skamil	switch (type) {
21641.54Skamil	case BYTES_TRANSFER_TEXT:
21651.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
21661.54Skamil		break;
21671.54Skamil	case BYTES_TRANSFER_TEXTIO:
21681.54Skamil		switch (size) {
21691.54Skamil		case 8:
21701.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
21711.54Skamil			break;
21721.54Skamil		case 16:
21731.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
21741.54Skamil			break;
21751.54Skamil		case 32:
21761.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
21771.54Skamil			break;
21781.54Skamil		case 64:
21791.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
21801.54Skamil			break;
21811.54Skamil		}
21821.54Skamil		break;
21831.54Skamil	default:
21841.54Skamil		break;
21851.54Skamil	}
21861.1Skamil
21871.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
21881.54Skamil	switch (type) {
21891.54Skamil	case BYTES_TRANSFER_TEXTIO:
21901.54Skamil	case BYTES_TRANSFER_DATAIO:
21911.54Skamil		io.piod_op = operation;
21921.54Skamil		switch (size) {
21931.54Skamil		case 8:
21941.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
21951.54Skamil			               (void *)bytes_transfer_dummy :
21961.54Skamil			               &lookup_me8;
21971.54Skamil			io.piod_addr = &lookup_me8;
21981.54Skamil			io.piod_len = sizeof(lookup_me8);
21991.54Skamil			break;
22001.54Skamil		case 16:
22011.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22021.54Skamil			               (void *)bytes_transfer_dummy :
22031.54Skamil			               &lookup_me16;
22041.54Skamil			io.piod_addr = &lookup_me16;
22051.54Skamil			io.piod_len = sizeof(lookup_me16);
22061.54Skamil			break;
22071.54Skamil		case 32:
22081.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22091.54Skamil			               (void *)bytes_transfer_dummy :
22101.54Skamil			               &lookup_me32;
22111.54Skamil			io.piod_addr = &lookup_me32;
22121.54Skamil			io.piod_len = sizeof(lookup_me32);
22131.54Skamil			break;
22141.54Skamil		case 64:
22151.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22161.54Skamil			               (void *)bytes_transfer_dummy :
22171.54Skamil			               &lookup_me64;
22181.54Skamil			io.piod_addr = &lookup_me64;
22191.54Skamil			io.piod_len = sizeof(lookup_me64);
22201.54Skamil			break;
22211.54Skamil		default:
22221.54Skamil			break;
22231.54Skamil		}
22241.54Skamil		break;
22251.54Skamil	case BYTES_TRANSFER_AUXV:
22261.54Skamil		io.piod_op = operation;
22271.54Skamil		io.piod_offs = 0;
22281.54Skamil		io.piod_addr = ai;
22291.54Skamil		io.piod_len = size;
22301.54Skamil		break;
22311.54Skamil	default:
22321.54Skamil		break;
22331.1Skamil	}
22341.1Skamil
22351.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22361.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22371.1Skamil	if (child == 0) {
22381.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22391.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22401.1Skamil
22411.54Skamil		switch (type) {
22421.54Skamil		case BYTES_TRANSFER_DATA:
22431.54Skamil			switch (operation) {
22441.54Skamil			case PT_READ_D:
22451.54Skamil			case PT_READ_I:
22461.54Skamil				lookup_me = magic;
22471.54Skamil				break;
22481.54Skamil			default:
22491.54Skamil				break;
22501.54Skamil			}
22511.54Skamil			break;
22521.54Skamil		case BYTES_TRANSFER_DATAIO:
22531.54Skamil			switch (operation) {
22541.54Skamil			case PIOD_READ_D:
22551.54Skamil			case PIOD_READ_I:
22561.54Skamil				switch (size) {
22571.54Skamil				case 8:
22581.54Skamil					lookup_me8 = magic8;
22591.54Skamil					break;
22601.54Skamil				case 16:
22611.54Skamil					lookup_me16 = magic16;
22621.54Skamil					break;
22631.54Skamil				case 32:
22641.54Skamil					lookup_me32 = magic32;
22651.54Skamil					break;
22661.54Skamil				case 64:
22671.54Skamil					lookup_me64 = magic64;
22681.54Skamil					break;
22691.54Skamil				default:
22701.54Skamil					break;
22711.54Skamil				}
22721.54Skamil				break;
22731.54Skamil			default:
22741.54Skamil				break;
22751.54Skamil			}
22761.54Skamil		default:
22771.54Skamil			break;
22781.54Skamil		}
22791.54Skamil
22801.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22811.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22821.1Skamil
22831.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
22841.54Skamil		switch (type) {
22851.54Skamil		case BYTES_TRANSFER_DATA:
22861.54Skamil			switch (operation) {
22871.54Skamil			case PT_WRITE_D:
22881.54Skamil			case PT_WRITE_I:
22891.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
22901.54Skamil				break;
22911.54Skamil			default:
22921.54Skamil				break;
22931.54Skamil			}
22941.54Skamil			break;
22951.54Skamil		case BYTES_TRANSFER_DATAIO:
22961.54Skamil			switch (operation) {
22971.54Skamil			case PIOD_WRITE_D:
22981.54Skamil			case PIOD_WRITE_I:
22991.54Skamil				switch (size) {
23001.54Skamil				case 8:
23011.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
23021.54Skamil					break;
23031.54Skamil				case 16:
23041.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
23051.54Skamil					break;
23061.54Skamil				case 32:
23071.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
23081.54Skamil					break;
23091.54Skamil				case 64:
23101.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
23111.54Skamil					break;
23121.54Skamil				default:
23131.54Skamil					break;
23141.54Skamil				}
23151.54Skamil				break;
23161.54Skamil			default:
23171.54Skamil				break;
23181.54Skamil			}
23191.54Skamil			break;
23201.54Skamil		case BYTES_TRANSFER_TEXT:
23211.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
23221.54Skamil			                     sizeof(magic)) == 0);
23231.54Skamil			break;
23241.54Skamil		case BYTES_TRANSFER_TEXTIO:
23251.54Skamil			switch (size) {
23261.54Skamil			case 8:
23271.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
23281.54Skamil				                     bytes_transfer_dummy,
23291.54Skamil				                     sizeof(magic8)) == 0);
23301.54Skamil				break;
23311.54Skamil			case 16:
23321.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
23331.54Skamil				                     bytes_transfer_dummy,
23341.54Skamil				                     sizeof(magic16)) == 0);
23351.54Skamil				break;
23361.54Skamil			case 32:
23371.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
23381.54Skamil				                     bytes_transfer_dummy,
23391.54Skamil				                     sizeof(magic32)) == 0);
23401.54Skamil				break;
23411.54Skamil			case 64:
23421.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
23431.54Skamil				                     bytes_transfer_dummy,
23441.54Skamil				                     sizeof(magic64)) == 0);
23451.54Skamil				break;
23461.54Skamil			}
23471.54Skamil			break;
23481.54Skamil		default:
23491.54Skamil			break;
23501.54Skamil		}
23511.54Skamil
23521.13Schristos		DPRINTF("Before exiting of the child process\n");
23531.1Skamil		_exit(exitval);
23541.1Skamil	}
23551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23561.1Skamil
23571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23591.1Skamil
23601.1Skamil	validate_status_stopped(status, sigval);
23611.1Skamil
23621.54Skamil	/* Check PaX MPROTECT */
23631.54Skamil	if (!can_we_write_to_text(child)) {
23641.54Skamil		switch (type) {
23651.54Skamil		case BYTES_TRANSFER_TEXTIO:
23661.54Skamil			switch (operation) {
23671.54Skamil			case PIOD_WRITE_D:
23681.54Skamil			case PIOD_WRITE_I:
23691.54Skamil				skip = true;
23701.54Skamil				break;
23711.54Skamil			default:
23721.54Skamil				break;
23731.54Skamil			}
23741.54Skamil			break;
23751.54Skamil		case BYTES_TRANSFER_TEXT:
23761.54Skamil			switch (operation) {
23771.54Skamil			case PT_WRITE_D:
23781.54Skamil			case PT_WRITE_I:
23791.54Skamil				skip = true;
23801.54Skamil				break;
23811.54Skamil			default:
23821.54Skamil				break;
23831.54Skamil			}
23841.54Skamil			break;
23851.54Skamil		default:
23861.54Skamil			break;
23871.54Skamil		}
23881.54Skamil	}
23891.1Skamil
23901.54Skamil	/* Bailout cleanly killing the child process */
23911.54Skamil	if (skip) {
23921.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
23931.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23941.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
23951.54Skamil		                      child);
23961.1Skamil
23971.54Skamil		validate_status_signaled(status, SIGKILL, 0);
23981.1Skamil
23991.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
24001.54Skamil	}
24011.1Skamil
24021.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
24031.54Skamil	       "parent=%d\n", child, getpid());
24041.1Skamil
24051.54Skamil	switch (type) {
24061.54Skamil	case BYTES_TRANSFER_TEXTIO:
24071.54Skamil	case BYTES_TRANSFER_DATAIO:
24081.54Skamil	case BYTES_TRANSFER_AUXV:
24091.54Skamil		switch (operation) {
24101.54Skamil		case PIOD_WRITE_D:
24111.54Skamil		case PIOD_WRITE_I:
24121.54Skamil			switch (size) {
24131.54Skamil			case 8:
24141.54Skamil				lookup_me8 = magic8;
24151.54Skamil				break;
24161.54Skamil			case 16:
24171.54Skamil				lookup_me16 = magic16;
24181.54Skamil				break;
24191.54Skamil			case 32:
24201.54Skamil				lookup_me32 = magic32;
24211.54Skamil				break;
24221.54Skamil			case 64:
24231.54Skamil				lookup_me64 = magic64;
24241.54Skamil				break;
24251.54Skamil			default:
24261.54Skamil				break;
24271.54Skamil			}
24281.54Skamil			break;
24291.54Skamil		default:
24301.54Skamil			break;
24311.54Skamil		}
24321.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
24331.54Skamil		switch (operation) {
24341.54Skamil		case PIOD_READ_D:
24351.54Skamil		case PIOD_READ_I:
24361.54Skamil			switch (size) {
24371.54Skamil			case 8:
24381.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
24391.54Skamil				break;
24401.54Skamil			case 16:
24411.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
24421.54Skamil				break;
24431.54Skamil			case 32:
24441.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
24451.54Skamil				break;
24461.54Skamil			case 64:
24471.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
24481.54Skamil				break;
24491.54Skamil			default:
24501.54Skamil				break;
24511.54Skamil			}
24521.54Skamil			break;
24531.54Skamil		case PIOD_READ_AUXV:
24541.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
24551.54Skamil			        io.piod_len);
24561.54Skamil			ATF_REQUIRE(io.piod_len > 0);
24571.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
24581.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
24591.54Skamil				    (long long int)aip->a_type,
24601.54Skamil				    (long long int)aip->a_v);
24611.54Skamil			break;
24621.54Skamil		default:
24631.54Skamil			break;
24641.54Skamil		}
24651.54Skamil		break;
24661.54Skamil	case BYTES_TRANSFER_TEXT:
24671.54Skamil		switch (operation) {
24681.54Skamil		case PT_READ_D:
24691.54Skamil		case PT_READ_I:
24701.54Skamil			errno = 0;
24711.54Skamil			lookup_me = ptrace(operation, child,
24721.54Skamil			                   bytes_transfer_dummy, 0);
24731.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
24741.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
24751.54Skamil			break;
24761.54Skamil		case PT_WRITE_D:
24771.54Skamil		case PT_WRITE_I:
24781.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
24791.54Skamil			                       bytes_transfer_dummy, magic)
24801.54Skamil			                != -1);
24811.54Skamil			break;
24821.54Skamil		default:
24831.54Skamil			break;
24841.54Skamil		}
24851.54Skamil		break;
24861.54Skamil	case BYTES_TRANSFER_DATA:
24871.54Skamil		switch (operation) {
24881.54Skamil		case PT_READ_D:
24891.54Skamil		case PT_READ_I:
24901.54Skamil			errno = 0;
24911.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
24921.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
24931.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
24941.54Skamil			break;
24951.54Skamil		case PT_WRITE_D:
24961.54Skamil		case PT_WRITE_I:
24971.54Skamil			lookup_me = magic;
24981.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
24991.54Skamil			                       magic) != -1);
25001.54Skamil			break;
25011.54Skamil		default:
25021.54Skamil			break;
25031.54Skamil		}
25041.54Skamil		break;
25051.54Skamil	default:
25061.54Skamil		break;
25071.54Skamil	}
25081.1Skamil
25091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25101.1Skamil	    "without signal to be sent\n");
25111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25121.1Skamil
25131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25151.1Skamil
25161.1Skamil	validate_status_exited(status, exitval);
25171.1Skamil
25181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25201.1Skamil}
25211.1Skamil
25221.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
25231.61SkreATF_TC(test);								\
25241.61SkreATF_TC_HEAD(test, tc)							\
25251.61Skre{									\
25261.61Skre	atf_tc_set_md_var(tc, "descr",					\
25271.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
25281.61Skre	    " of type " #type);						\
25291.61Skre}									\
25301.61Skre									\
25311.61SkreATF_TC_BODY(test, tc)							\
25321.61Skre{									\
25331.61Skre									\
25341.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
25351.1Skamil}
25361.1Skamil
25371.54Skamil// DATA
25381.1Skamil
25391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
25401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
25411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
25421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
25431.54Skamil
25441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
25451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
25461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
25471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
25481.54Skamil
25491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
25501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
25511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
25521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
25531.54Skamil
25541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
25551.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
25561.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
25571.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
25581.54Skamil
25591.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
25601.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
25611.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
25621.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
25631.54Skamil
25641.54Skamil// TEXT
25651.54Skamil
25661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
25671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
25681.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
25691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
25701.54Skamil
25711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
25721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
25731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
25741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
25751.54Skamil
25761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
25771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
25781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
25791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
25801.54Skamil
25811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
25821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
25831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
25841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
25851.54Skamil
25861.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
25871.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
25881.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
25891.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
25901.1Skamil
25911.54Skamil// AUXV
25921.1Skamil
25931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
25941.1Skamil
25951.54Skamil/// ----------------------------------------------------------------------------
25961.1Skamil
25971.1Skamil#if defined(HAVE_GPREGS)
25981.1SkamilATF_TC(regs1);
25991.1SkamilATF_TC_HEAD(regs1, tc)
26001.1Skamil{
26011.1Skamil	atf_tc_set_md_var(tc, "descr",
26021.1Skamil	    "Verify plain PT_GETREGS call without further steps");
26031.1Skamil}
26041.1Skamil
26051.1SkamilATF_TC_BODY(regs1, tc)
26061.1Skamil{
26071.1Skamil	const int exitval = 5;
26081.1Skamil	const int sigval = SIGSTOP;
26091.1Skamil	pid_t child, wpid;
26101.1Skamil#if defined(TWAIT_HAVE_STATUS)
26111.1Skamil	int status;
26121.1Skamil#endif
26131.1Skamil	struct reg r;
26141.1Skamil
26151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26171.1Skamil	if (child == 0) {
26181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26201.1Skamil
26211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26231.1Skamil
26241.13Schristos		DPRINTF("Before exiting of the child process\n");
26251.1Skamil		_exit(exitval);
26261.1Skamil	}
26271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26281.1Skamil
26291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26311.1Skamil
26321.1Skamil	validate_status_stopped(status, sigval);
26331.1Skamil
26341.13Schristos	DPRINTF("Call GETREGS for the child process\n");
26351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
26361.1Skamil
26371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26381.1Skamil	    "without signal to be sent\n");
26391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26401.1Skamil
26411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26431.1Skamil
26441.1Skamil	validate_status_exited(status, exitval);
26451.1Skamil
26461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26471.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26481.1Skamil}
26491.1Skamil#endif
26501.1Skamil
26511.1Skamil#if defined(HAVE_GPREGS)
26521.1SkamilATF_TC(regs2);
26531.1SkamilATF_TC_HEAD(regs2, tc)
26541.1Skamil{
26551.1Skamil	atf_tc_set_md_var(tc, "descr",
26561.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
26571.1Skamil}
26581.1Skamil
26591.1SkamilATF_TC_BODY(regs2, tc)
26601.1Skamil{
26611.1Skamil	const int exitval = 5;
26621.1Skamil	const int sigval = SIGSTOP;
26631.1Skamil	pid_t child, wpid;
26641.1Skamil#if defined(TWAIT_HAVE_STATUS)
26651.1Skamil	int status;
26661.1Skamil#endif
26671.1Skamil	struct reg r;
26681.1Skamil
26691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26711.1Skamil	if (child == 0) {
26721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26741.1Skamil
26751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26771.1Skamil
26781.13Schristos		DPRINTF("Before exiting of the child process\n");
26791.1Skamil		_exit(exitval);
26801.1Skamil	}
26811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26821.1Skamil
26831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26851.1Skamil
26861.1Skamil	validate_status_stopped(status, sigval);
26871.1Skamil
26881.13Schristos	DPRINTF("Call GETREGS for the child process\n");
26891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
26901.1Skamil
26911.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
26921.1Skamil
26931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26941.1Skamil	    "without signal to be sent\n");
26951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26961.1Skamil
26971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26991.1Skamil
27001.1Skamil	validate_status_exited(status, exitval);
27011.1Skamil
27021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27041.1Skamil}
27051.1Skamil#endif
27061.1Skamil
27071.1Skamil#if defined(HAVE_GPREGS)
27081.1SkamilATF_TC(regs3);
27091.1SkamilATF_TC_HEAD(regs3, tc)
27101.1Skamil{
27111.1Skamil	atf_tc_set_md_var(tc, "descr",
27121.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
27131.1Skamil}
27141.1Skamil
27151.1SkamilATF_TC_BODY(regs3, tc)
27161.1Skamil{
27171.1Skamil	const int exitval = 5;
27181.1Skamil	const int sigval = SIGSTOP;
27191.1Skamil	pid_t child, wpid;
27201.1Skamil#if defined(TWAIT_HAVE_STATUS)
27211.1Skamil	int status;
27221.1Skamil#endif
27231.1Skamil	struct reg r;
27241.1Skamil
27251.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27261.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27271.1Skamil	if (child == 0) {
27281.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27291.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27301.1Skamil
27311.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27321.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27331.1Skamil
27341.13Schristos		DPRINTF("Before exiting of the child process\n");
27351.1Skamil		_exit(exitval);
27361.1Skamil	}
27371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27381.1Skamil
27391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27411.1Skamil
27421.1Skamil	validate_status_stopped(status, sigval);
27431.1Skamil
27441.13Schristos	DPRINTF("Call GETREGS for the child process\n");
27451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
27461.1Skamil
27471.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
27481.1Skamil
27491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27501.1Skamil	    "without signal to be sent\n");
27511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27521.1Skamil
27531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27551.1Skamil
27561.1Skamil	validate_status_exited(status, exitval);
27571.1Skamil
27581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27601.1Skamil}
27611.1Skamil#endif
27621.1Skamil
27631.1Skamil#if defined(HAVE_GPREGS)
27641.1SkamilATF_TC(regs4);
27651.1SkamilATF_TC_HEAD(regs4, tc)
27661.1Skamil{
27671.1Skamil	atf_tc_set_md_var(tc, "descr",
27681.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
27691.1Skamil}
27701.1Skamil
27711.1SkamilATF_TC_BODY(regs4, tc)
27721.1Skamil{
27731.1Skamil	const int exitval = 5;
27741.1Skamil	const int sigval = SIGSTOP;
27751.1Skamil	pid_t child, wpid;
27761.1Skamil#if defined(TWAIT_HAVE_STATUS)
27771.1Skamil	int status;
27781.1Skamil#endif
27791.1Skamil	struct reg r;
27801.1Skamil
27811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27831.1Skamil	if (child == 0) {
27841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27861.1Skamil
27871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27891.1Skamil
27901.13Schristos		DPRINTF("Before exiting of the child process\n");
27911.1Skamil		_exit(exitval);
27921.1Skamil	}
27931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27941.1Skamil
27951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27971.1Skamil
27981.1Skamil	validate_status_stopped(status, sigval);
27991.1Skamil
28001.13Schristos	DPRINTF("Call GETREGS for the child process\n");
28011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28021.1Skamil
28031.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
28041.1Skamil
28051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28061.1Skamil	    "without signal to be sent\n");
28071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28081.1Skamil
28091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28111.1Skamil
28121.1Skamil	validate_status_exited(status, exitval);
28131.1Skamil
28141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28161.1Skamil}
28171.1Skamil#endif
28181.1Skamil
28191.1Skamil#if defined(HAVE_GPREGS)
28201.1SkamilATF_TC(regs5);
28211.1SkamilATF_TC_HEAD(regs5, tc)
28221.1Skamil{
28231.1Skamil	atf_tc_set_md_var(tc, "descr",
28241.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
28251.1Skamil}
28261.1Skamil
28271.1SkamilATF_TC_BODY(regs5, tc)
28281.1Skamil{
28291.1Skamil	const int exitval = 5;
28301.1Skamil	const int sigval = SIGSTOP;
28311.1Skamil	pid_t child, wpid;
28321.1Skamil#if defined(TWAIT_HAVE_STATUS)
28331.1Skamil	int status;
28341.1Skamil#endif
28351.1Skamil	struct reg r;
28361.1Skamil
28371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28391.1Skamil	if (child == 0) {
28401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28421.1Skamil
28431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28451.1Skamil
28461.13Schristos		DPRINTF("Before exiting of the child process\n");
28471.1Skamil		_exit(exitval);
28481.1Skamil	}
28491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28501.1Skamil
28511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28531.1Skamil
28541.1Skamil	validate_status_stopped(status, sigval);
28551.1Skamil
28561.13Schristos	DPRINTF("Call GETREGS for the child process\n");
28571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28581.1Skamil
28591.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
28601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28611.1Skamil
28621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28631.1Skamil	    "without signal to be sent\n");
28641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28651.1Skamil
28661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28681.1Skamil
28691.1Skamil	validate_status_exited(status, exitval);
28701.1Skamil
28711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28721.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28731.1Skamil}
28741.1Skamil#endif
28751.1Skamil
28761.1Skamil#if defined(HAVE_FPREGS)
28771.1SkamilATF_TC(fpregs1);
28781.1SkamilATF_TC_HEAD(fpregs1, tc)
28791.1Skamil{
28801.1Skamil	atf_tc_set_md_var(tc, "descr",
28811.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
28821.1Skamil}
28831.1Skamil
28841.1SkamilATF_TC_BODY(fpregs1, tc)
28851.1Skamil{
28861.1Skamil	const int exitval = 5;
28871.1Skamil	const int sigval = SIGSTOP;
28881.1Skamil	pid_t child, wpid;
28891.1Skamil#if defined(TWAIT_HAVE_STATUS)
28901.1Skamil	int status;
28911.1Skamil#endif
28921.1Skamil	struct fpreg r;
28931.1Skamil
28941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28961.1Skamil	if (child == 0) {
28971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28991.1Skamil
29001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29021.1Skamil
29031.13Schristos		DPRINTF("Before exiting of the child process\n");
29041.1Skamil		_exit(exitval);
29051.1Skamil	}
29061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29071.1Skamil
29081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29101.1Skamil
29111.1Skamil	validate_status_stopped(status, sigval);
29121.1Skamil
29131.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
29141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
29151.1Skamil
29161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29171.1Skamil	    "without signal to be sent\n");
29181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29191.1Skamil
29201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29221.1Skamil
29231.1Skamil	validate_status_exited(status, exitval);
29241.1Skamil
29251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29271.1Skamil}
29281.1Skamil#endif
29291.1Skamil
29301.1Skamil#if defined(HAVE_FPREGS)
29311.1SkamilATF_TC(fpregs2);
29321.1SkamilATF_TC_HEAD(fpregs2, tc)
29331.1Skamil{
29341.1Skamil	atf_tc_set_md_var(tc, "descr",
29351.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
29361.1Skamil	    "regs");
29371.1Skamil}
29381.1Skamil
29391.1SkamilATF_TC_BODY(fpregs2, tc)
29401.1Skamil{
29411.1Skamil	const int exitval = 5;
29421.1Skamil	const int sigval = SIGSTOP;
29431.1Skamil	pid_t child, wpid;
29441.1Skamil#if defined(TWAIT_HAVE_STATUS)
29451.1Skamil	int status;
29461.1Skamil#endif
29471.1Skamil	struct fpreg r;
29481.1Skamil
29491.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29501.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29511.1Skamil	if (child == 0) {
29521.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29531.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29541.1Skamil
29551.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29561.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29571.1Skamil
29581.13Schristos		DPRINTF("Before exiting of the child process\n");
29591.1Skamil		_exit(exitval);
29601.1Skamil	}
29611.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29621.1Skamil
29631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29651.1Skamil
29661.1Skamil	validate_status_stopped(status, sigval);
29671.1Skamil
29681.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
29691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
29701.1Skamil
29711.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
29721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
29731.1Skamil
29741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29751.1Skamil	    "without signal to be sent\n");
29761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29771.1Skamil
29781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29801.1Skamil
29811.1Skamil	validate_status_exited(status, exitval);
29821.1Skamil
29831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29851.1Skamil}
29861.1Skamil#endif
29871.1Skamil
29881.1Skamil#if defined(PT_STEP)
29891.1Skamilstatic void
29901.2Skamilptrace_step(int N, int setstep)
29911.1Skamil{
29921.1Skamil	const int exitval = 5;
29931.1Skamil	const int sigval = SIGSTOP;
29941.1Skamil	pid_t child, wpid;
29951.1Skamil#if defined(TWAIT_HAVE_STATUS)
29961.1Skamil	int status;
29971.1Skamil#endif
29981.1Skamil	int happy;
29991.1Skamil
30001.1Skamil#if defined(__arm__)
30011.1Skamil	/* PT_STEP not supported on arm 32-bit */
30021.1Skamil	atf_tc_expect_fail("PR kern/52119");
30031.1Skamil#endif
30041.1Skamil
30051.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30061.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30071.1Skamil	if (child == 0) {
30081.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30091.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30101.1Skamil
30111.1Skamil		happy = check_happy(999);
30121.1Skamil
30131.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30141.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30151.1Skamil
30161.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
30171.1Skamil
30181.13Schristos		DPRINTF("Before exiting of the child process\n");
30191.1Skamil		_exit(exitval);
30201.1Skamil	}
30211.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30221.1Skamil
30231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30251.1Skamil
30261.1Skamil	validate_status_stopped(status, sigval);
30271.1Skamil
30281.1Skamil	while (N --> 0) {
30291.2Skamil		if (setstep) {
30301.13Schristos			DPRINTF("Before resuming the child process where it "
30311.2Skamil			    "left off and without signal to be sent (use "
30321.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
30331.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
30341.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
30351.2Skamil			    != -1);
30361.2Skamil		} else {
30371.13Schristos			DPRINTF("Before resuming the child process where it "
30381.2Skamil			    "left off and without signal to be sent (use "
30391.2Skamil			    "PT_STEP)\n");
30401.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
30411.2Skamil			    != -1);
30421.2Skamil		}
30431.1Skamil
30441.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30451.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30461.1Skamil		    child);
30471.1Skamil
30481.1Skamil		validate_status_stopped(status, SIGTRAP);
30491.2Skamil
30501.2Skamil		if (setstep) {
30511.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
30521.2Skamil		}
30531.1Skamil	}
30541.1Skamil
30551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30561.1Skamil	    "without signal to be sent\n");
30571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30581.1Skamil
30591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30611.1Skamil
30621.1Skamil	validate_status_exited(status, exitval);
30631.1Skamil
30641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30651.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30661.1Skamil}
30671.1Skamil#endif
30681.1Skamil
30691.1Skamil#if defined(PT_STEP)
30701.1SkamilATF_TC(step1);
30711.1SkamilATF_TC_HEAD(step1, tc)
30721.1Skamil{
30731.1Skamil	atf_tc_set_md_var(tc, "descr",
30741.1Skamil	    "Verify single PT_STEP call");
30751.1Skamil}
30761.1Skamil
30771.1SkamilATF_TC_BODY(step1, tc)
30781.1Skamil{
30791.2Skamil	ptrace_step(1, 0);
30801.1Skamil}
30811.1Skamil#endif
30821.1Skamil
30831.1Skamil#if defined(PT_STEP)
30841.1SkamilATF_TC(step2);
30851.1SkamilATF_TC_HEAD(step2, tc)
30861.1Skamil{
30871.1Skamil	atf_tc_set_md_var(tc, "descr",
30881.1Skamil	    "Verify PT_STEP called twice");
30891.1Skamil}
30901.1Skamil
30911.1SkamilATF_TC_BODY(step2, tc)
30921.1Skamil{
30931.2Skamil	ptrace_step(2, 0);
30941.1Skamil}
30951.1Skamil#endif
30961.1Skamil
30971.1Skamil#if defined(PT_STEP)
30981.1SkamilATF_TC(step3);
30991.1SkamilATF_TC_HEAD(step3, tc)
31001.1Skamil{
31011.1Skamil	atf_tc_set_md_var(tc, "descr",
31021.1Skamil	    "Verify PT_STEP called three times");
31031.1Skamil}
31041.1Skamil
31051.1SkamilATF_TC_BODY(step3, tc)
31061.1Skamil{
31071.2Skamil	ptrace_step(3, 0);
31081.1Skamil}
31091.1Skamil#endif
31101.1Skamil
31111.1Skamil#if defined(PT_STEP)
31121.1SkamilATF_TC(step4);
31131.1SkamilATF_TC_HEAD(step4, tc)
31141.1Skamil{
31151.1Skamil	atf_tc_set_md_var(tc, "descr",
31161.1Skamil	    "Verify PT_STEP called four times");
31171.1Skamil}
31181.1Skamil
31191.1SkamilATF_TC_BODY(step4, tc)
31201.1Skamil{
31211.2Skamil	ptrace_step(4, 0);
31221.2Skamil}
31231.2Skamil#endif
31241.2Skamil
31251.2Skamil#if defined(PT_STEP)
31261.2SkamilATF_TC(setstep1);
31271.2SkamilATF_TC_HEAD(setstep1, tc)
31281.2Skamil{
31291.2Skamil	atf_tc_set_md_var(tc, "descr",
31301.2Skamil	    "Verify single PT_SETSTEP call");
31311.2Skamil}
31321.2Skamil
31331.2SkamilATF_TC_BODY(setstep1, tc)
31341.2Skamil{
31351.2Skamil	ptrace_step(1, 1);
31361.2Skamil}
31371.2Skamil#endif
31381.2Skamil
31391.2Skamil#if defined(PT_STEP)
31401.2SkamilATF_TC(setstep2);
31411.2SkamilATF_TC_HEAD(setstep2, tc)
31421.2Skamil{
31431.2Skamil	atf_tc_set_md_var(tc, "descr",
31441.2Skamil	    "Verify PT_SETSTEP called twice");
31451.2Skamil}
31461.2Skamil
31471.2SkamilATF_TC_BODY(setstep2, tc)
31481.2Skamil{
31491.2Skamil	ptrace_step(2, 1);
31501.2Skamil}
31511.2Skamil#endif
31521.2Skamil
31531.2Skamil#if defined(PT_STEP)
31541.2SkamilATF_TC(setstep3);
31551.2SkamilATF_TC_HEAD(setstep3, tc)
31561.2Skamil{
31571.2Skamil	atf_tc_set_md_var(tc, "descr",
31581.2Skamil	    "Verify PT_SETSTEP called three times");
31591.2Skamil}
31601.2Skamil
31611.2SkamilATF_TC_BODY(setstep3, tc)
31621.2Skamil{
31631.2Skamil	ptrace_step(3, 1);
31641.2Skamil}
31651.2Skamil#endif
31661.2Skamil
31671.2Skamil#if defined(PT_STEP)
31681.2SkamilATF_TC(setstep4);
31691.2SkamilATF_TC_HEAD(setstep4, tc)
31701.2Skamil{
31711.2Skamil	atf_tc_set_md_var(tc, "descr",
31721.2Skamil	    "Verify PT_SETSTEP called four times");
31731.2Skamil}
31741.2Skamil
31751.2SkamilATF_TC_BODY(setstep4, tc)
31761.2Skamil{
31771.2Skamil	ptrace_step(4, 1);
31781.1Skamil}
31791.1Skamil#endif
31801.1Skamil
31811.1SkamilATF_TC(kill1);
31821.1SkamilATF_TC_HEAD(kill1, tc)
31831.1Skamil{
31841.1Skamil	atf_tc_set_md_var(tc, "descr",
31851.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
31861.1Skamil}
31871.1Skamil
31881.1SkamilATF_TC_BODY(kill1, tc)
31891.1Skamil{
31901.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
31911.1Skamil	pid_t child, wpid;
31921.1Skamil#if defined(TWAIT_HAVE_STATUS)
31931.1Skamil	int status;
31941.1Skamil#endif
31951.1Skamil
31961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31981.1Skamil	if (child == 0) {
31991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32011.1Skamil
32021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32041.1Skamil
32051.1Skamil		/* NOTREACHED */
32061.1Skamil		FORKEE_ASSERTX(0 &&
32071.1Skamil		    "Child should be terminated by a signal from its parent");
32081.1Skamil	}
32091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32101.1Skamil
32111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32131.1Skamil
32141.1Skamil	validate_status_stopped(status, sigval);
32151.1Skamil
32161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32171.1Skamil	    "without signal to be sent\n");
32181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
32191.1Skamil
32201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32221.1Skamil
32231.1Skamil	validate_status_signaled(status, sigsent, 0);
32241.1Skamil
32251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32271.1Skamil}
32281.1Skamil
32291.1SkamilATF_TC(kill2);
32301.1SkamilATF_TC_HEAD(kill2, tc)
32311.1Skamil{
32321.1Skamil	atf_tc_set_md_var(tc, "descr",
32331.1Skamil	    "Verify that PT_KILL terminates child");
32341.1Skamil}
32351.1Skamil
32361.1SkamilATF_TC_BODY(kill2, tc)
32371.1Skamil{
32381.1Skamil	const int sigval = SIGSTOP;
32391.1Skamil	pid_t child, wpid;
32401.1Skamil#if defined(TWAIT_HAVE_STATUS)
32411.1Skamil	int status;
32421.1Skamil#endif
32431.1Skamil
32441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32461.1Skamil	if (child == 0) {
32471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32491.1Skamil
32501.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32511.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32521.1Skamil
32531.1Skamil		/* NOTREACHED */
32541.1Skamil		FORKEE_ASSERTX(0 &&
32551.1Skamil		    "Child should be terminated by a signal from its parent");
32561.1Skamil	}
32571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32581.1Skamil
32591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32611.1Skamil
32621.1Skamil	validate_status_stopped(status, sigval);
32631.1Skamil
32641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32651.1Skamil	    "without signal to be sent\n");
32661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
32671.1Skamil
32681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32701.1Skamil
32711.1Skamil	validate_status_signaled(status, SIGKILL, 0);
32721.1Skamil
32731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32751.1Skamil}
32761.1Skamil
32771.1SkamilATF_TC(lwpinfo1);
32781.1SkamilATF_TC_HEAD(lwpinfo1, tc)
32791.1Skamil{
32801.1Skamil	atf_tc_set_md_var(tc, "descr",
32811.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
32821.1Skamil}
32831.1Skamil
32841.1SkamilATF_TC_BODY(lwpinfo1, tc)
32851.1Skamil{
32861.1Skamil	const int exitval = 5;
32871.1Skamil	const int sigval = SIGSTOP;
32881.1Skamil	pid_t child, wpid;
32891.1Skamil#if defined(TWAIT_HAVE_STATUS)
32901.1Skamil	int status;
32911.1Skamil#endif
32921.1Skamil	struct ptrace_lwpinfo info = {0, 0};
32931.1Skamil
32941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32961.1Skamil	if (child == 0) {
32971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32991.1Skamil
33001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33021.1Skamil
33031.13Schristos		DPRINTF("Before exiting of the child process\n");
33041.1Skamil		_exit(exitval);
33051.1Skamil	}
33061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33071.1Skamil
33081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33101.1Skamil
33111.1Skamil	validate_status_stopped(status, sigval);
33121.1Skamil
33131.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
33151.1Skamil
33161.13Schristos	DPRINTF("Assert that there exists a thread\n");
33171.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
33181.1Skamil
33191.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
33201.1Skamil	    info.pl_lwpid);
33211.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
33221.1Skamil	    "Received event %d != expected event %d",
33231.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
33241.1Skamil
33251.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
33271.1Skamil
33281.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
33291.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
33301.1Skamil
33311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33321.1Skamil	    "without signal to be sent\n");
33331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33341.1Skamil
33351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33371.1Skamil
33381.1Skamil	validate_status_exited(status, exitval);
33391.1Skamil
33401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33411.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33421.1Skamil}
33431.1Skamil
33441.1Skamil#if defined(TWAIT_HAVE_PID)
33451.1SkamilATF_TC(lwpinfo2);
33461.1SkamilATF_TC_HEAD(lwpinfo2, tc)
33471.1Skamil{
33481.1Skamil	atf_tc_set_md_var(tc, "descr",
33491.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
33501.1Skamil	    "tracer)");
33511.1Skamil}
33521.1Skamil
33531.1SkamilATF_TC_BODY(lwpinfo2, tc)
33541.1Skamil{
33551.1Skamil	struct msg_fds parent_tracee, parent_tracer;
33561.1Skamil	const int exitval_tracee = 5;
33571.1Skamil	const int exitval_tracer = 10;
33581.1Skamil	pid_t tracee, tracer, wpid;
33591.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
33601.1Skamil#if defined(TWAIT_HAVE_STATUS)
33611.1Skamil	int status;
33621.1Skamil#endif
33631.1Skamil	struct ptrace_lwpinfo info = {0, 0};
33641.1Skamil
33651.13Schristos	DPRINTF("Spawn tracee\n");
33661.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
33671.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
33681.1Skamil	tracee = atf_utils_fork();
33691.1Skamil	if (tracee == 0) {
33701.1Skamil
33711.1Skamil		/* Wait for message from the parent */
33721.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
33731.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
33741.1Skamil
33751.1Skamil		_exit(exitval_tracee);
33761.1Skamil	}
33771.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
33781.1Skamil
33791.13Schristos	DPRINTF("Spawn debugger\n");
33801.1Skamil	tracer = atf_utils_fork();
33811.1Skamil	if (tracer == 0) {
33821.1Skamil		/* No IPC to communicate with the child */
33831.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
33841.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
33851.1Skamil
33861.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
33871.1Skamil		FORKEE_REQUIRE_SUCCESS(
33881.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
33891.1Skamil
33901.1Skamil		forkee_status_stopped(status, SIGSTOP);
33911.1Skamil
33921.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33931.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
33941.1Skamil		    != -1);
33951.1Skamil
33961.13Schristos		DPRINTF("Assert that there exists a thread\n");
33971.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
33981.1Skamil
33991.13Schristos		DPRINTF("Assert that lwp thread %d received event "
34001.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
34011.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
34021.1Skamil
34031.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
34041.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
34051.1Skamil		    != -1);
34061.1Skamil
34071.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
34081.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
34091.1Skamil
34101.1Skamil		/* Resume tracee with PT_CONTINUE */
34111.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
34121.1Skamil
34131.1Skamil		/* Inform parent that tracer has attached to tracee */
34141.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
34151.1Skamil		/* Wait for parent */
34161.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
34171.1Skamil
34181.1Skamil		/* Wait for tracee and assert that it exited */
34191.1Skamil		FORKEE_REQUIRE_SUCCESS(
34201.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
34211.1Skamil
34221.1Skamil		forkee_status_exited(status, exitval_tracee);
34231.1Skamil
34241.13Schristos		DPRINTF("Before exiting of the tracer process\n");
34251.1Skamil		_exit(exitval_tracer);
34261.1Skamil	}
34271.1Skamil
34281.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
34291.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
34301.1Skamil
34311.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
34321.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
34331.1Skamil
34341.13Schristos	DPRINTF("Detect that tracee is zombie\n");
34351.1Skamil	await_zombie(tracee);
34361.1Skamil
34371.13Schristos	DPRINTF("Assert that there is no status about tracee - "
34381.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
34391.1Skamil	TWAIT_REQUIRE_SUCCESS(
34401.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
34411.1Skamil
34421.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
34431.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
34441.1Skamil
34451.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
34461.1Skamil	    TWAIT_FNAME);
34471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
34481.1Skamil	    tracer);
34491.1Skamil
34501.1Skamil	validate_status_exited(status, exitval_tracer);
34511.1Skamil
34521.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
34531.1Skamil	    TWAIT_FNAME);
34541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
34551.1Skamil	    tracee);
34561.1Skamil
34571.1Skamil	validate_status_exited(status, exitval_tracee);
34581.1Skamil
34591.1Skamil	msg_close(&parent_tracer);
34601.1Skamil	msg_close(&parent_tracee);
34611.1Skamil}
34621.1Skamil#endif
34631.1Skamil
34641.1SkamilATF_TC(siginfo1);
34651.1SkamilATF_TC_HEAD(siginfo1, tc)
34661.1Skamil{
34671.1Skamil	atf_tc_set_md_var(tc, "descr",
34681.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
34691.1Skamil}
34701.1Skamil
34711.1SkamilATF_TC_BODY(siginfo1, tc)
34721.1Skamil{
34731.1Skamil	const int exitval = 5;
34741.1Skamil	const int sigval = SIGTRAP;
34751.1Skamil	pid_t child, wpid;
34761.1Skamil#if defined(TWAIT_HAVE_STATUS)
34771.1Skamil	int status;
34781.1Skamil#endif
34791.1Skamil	struct ptrace_siginfo info;
34801.1Skamil	memset(&info, 0, sizeof(info));
34811.1Skamil
34821.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34831.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34841.1Skamil	if (child == 0) {
34851.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34861.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34871.1Skamil
34881.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34891.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34901.1Skamil
34911.13Schristos		DPRINTF("Before exiting of the child process\n");
34921.1Skamil		_exit(exitval);
34931.1Skamil	}
34941.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34951.1Skamil
34961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34981.1Skamil
34991.1Skamil	validate_status_stopped(status, sigval);
35001.1Skamil
35011.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35031.1Skamil
35041.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35051.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35061.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35071.1Skamil	    info.psi_siginfo.si_errno);
35081.1Skamil
35091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35101.1Skamil	    "without signal to be sent\n");
35111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35121.1Skamil
35131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35151.1Skamil
35161.1Skamil	validate_status_exited(status, exitval);
35171.1Skamil
35181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35191.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35201.1Skamil}
35211.1Skamil
35221.1SkamilATF_TC(siginfo2);
35231.1SkamilATF_TC_HEAD(siginfo2, tc)
35241.1Skamil{
35251.1Skamil	atf_tc_set_md_var(tc, "descr",
35261.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
35271.1Skamil	    "modification of SIGINT from tracee");
35281.1Skamil}
35291.1Skamil
35301.1Skamilstatic int siginfo2_caught = 0;
35311.1Skamil
35321.1Skamilstatic void
35331.1Skamilsiginfo2_sighandler(int sig)
35341.1Skamil{
35351.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
35361.1Skamil
35371.1Skamil	++siginfo2_caught;
35381.1Skamil}
35391.1Skamil
35401.1SkamilATF_TC_BODY(siginfo2, tc)
35411.1Skamil{
35421.1Skamil	const int exitval = 5;
35431.1Skamil	const int sigval = SIGINT;
35441.1Skamil	pid_t child, wpid;
35451.1Skamil	struct sigaction sa;
35461.1Skamil#if defined(TWAIT_HAVE_STATUS)
35471.1Skamil	int status;
35481.1Skamil#endif
35491.1Skamil	struct ptrace_siginfo info;
35501.1Skamil	memset(&info, 0, sizeof(info));
35511.1Skamil
35521.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35531.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35541.1Skamil	if (child == 0) {
35551.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35561.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35571.1Skamil
35581.1Skamil		sa.sa_handler = siginfo2_sighandler;
35591.1Skamil		sa.sa_flags = SA_SIGINFO;
35601.1Skamil		sigemptyset(&sa.sa_mask);
35611.1Skamil
35621.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
35631.1Skamil
35641.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35651.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35661.1Skamil
35671.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
35681.1Skamil
35691.13Schristos		DPRINTF("Before exiting of the child process\n");
35701.1Skamil		_exit(exitval);
35711.1Skamil	}
35721.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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_stopped(status, sigval);
35781.1Skamil
35791.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35811.1Skamil
35821.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35831.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35841.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35851.1Skamil	    info.psi_siginfo.si_errno);
35861.1Skamil
35871.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
35881.61Skre	SYSCALL_REQUIRE(
35891.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
35901.1Skamil
35911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35921.1Skamil	    "without signal to be sent\n");
35931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
35941.1Skamil
35951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35971.1Skamil
35981.1Skamil	validate_status_exited(status, exitval);
35991.1Skamil
36001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36011.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36021.1Skamil}
36031.1Skamil
36041.1SkamilATF_TC(siginfo3);
36051.1SkamilATF_TC_HEAD(siginfo3, tc)
36061.1Skamil{
36071.1Skamil	atf_tc_set_md_var(tc, "descr",
36081.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
36091.1Skamil	    "setting signal to new value");
36101.1Skamil}
36111.1Skamil
36121.1Skamilstatic int siginfo3_caught = 0;
36131.1Skamil
36141.1Skamilstatic void
36151.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
36161.1Skamil{
36171.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
36181.1Skamil
36191.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
36201.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
36211.1Skamil
36221.1Skamil	++siginfo3_caught;
36231.1Skamil}
36241.1Skamil
36251.1SkamilATF_TC_BODY(siginfo3, tc)
36261.1Skamil{
36271.1Skamil	const int exitval = 5;
36281.1Skamil	const int sigval = SIGINT;
36291.1Skamil	const int sigfaked = SIGTRAP;
36301.1Skamil	const int sicodefaked = TRAP_BRKPT;
36311.1Skamil	pid_t child, wpid;
36321.1Skamil	struct sigaction sa;
36331.1Skamil#if defined(TWAIT_HAVE_STATUS)
36341.1Skamil	int status;
36351.1Skamil#endif
36361.1Skamil	struct ptrace_siginfo info;
36371.1Skamil	memset(&info, 0, sizeof(info));
36381.1Skamil
36391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36411.1Skamil	if (child == 0) {
36421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36441.1Skamil
36451.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
36461.1Skamil		sa.sa_flags = SA_SIGINFO;
36471.1Skamil		sigemptyset(&sa.sa_mask);
36481.1Skamil
36491.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
36501.1Skamil
36511.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36521.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36531.1Skamil
36541.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
36551.1Skamil
36561.13Schristos		DPRINTF("Before exiting of the child process\n");
36571.1Skamil		_exit(exitval);
36581.1Skamil	}
36591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36601.1Skamil
36611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36631.1Skamil
36641.1Skamil	validate_status_stopped(status, sigval);
36651.1Skamil
36661.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36671.61Skre	SYSCALL_REQUIRE(
36681.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36691.1Skamil
36701.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36711.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
36721.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36731.1Skamil	    info.psi_siginfo.si_errno);
36741.1Skamil
36751.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
36761.1Skamil	    sigfaked, sicodefaked);
36771.1Skamil	info.psi_siginfo.si_signo = sigfaked;
36781.1Skamil	info.psi_siginfo.si_code = sicodefaked;
36791.1Skamil
36801.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
36811.61Skre	SYSCALL_REQUIRE(
36821.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
36831.1Skamil
36841.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36851.61Skre	SYSCALL_REQUIRE(
36861.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36871.1Skamil
36881.13Schristos	DPRINTF("Before checking siginfo_t\n");
36891.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
36901.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
36911.1Skamil
36921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36931.1Skamil	    "without signal to be sent\n");
36941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
36951.1Skamil
36961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36981.1Skamil
36991.1Skamil	validate_status_exited(status, exitval);
37001.1Skamil
37011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37021.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37031.1Skamil}
37041.1Skamil
37051.1SkamilATF_TC(siginfo4);
37061.1SkamilATF_TC_HEAD(siginfo4, tc)
37071.1Skamil{
37081.1Skamil	atf_tc_set_md_var(tc, "descr",
37091.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
37101.1Skamil}
37111.1Skamil
37121.1SkamilATF_TC_BODY(siginfo4, tc)
37131.1Skamil{
37141.1Skamil	const int sigval = SIGTRAP;
37151.1Skamil	pid_t child, wpid;
37161.1Skamil#if defined(TWAIT_HAVE_STATUS)
37171.1Skamil	int status;
37181.1Skamil#endif
37191.1Skamil
37201.1Skamil	struct ptrace_siginfo info;
37211.1Skamil	memset(&info, 0, sizeof(info));
37221.1Skamil
37231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37251.1Skamil	if (child == 0) {
37261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37281.1Skamil
37291.13Schristos		DPRINTF("Before calling execve(2) from child\n");
37301.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
37311.1Skamil
37321.1Skamil		FORKEE_ASSERT(0 && "Not reached");
37331.1Skamil	}
37341.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37351.1Skamil
37361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37381.1Skamil
37391.1Skamil	validate_status_stopped(status, sigval);
37401.1Skamil
37411.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37421.61Skre	SYSCALL_REQUIRE(
37431.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37441.1Skamil
37451.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37461.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
37471.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37481.1Skamil	    info.psi_siginfo.si_errno);
37491.1Skamil
37501.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
37511.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
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\n", TWAIT_FNAME);
37581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37591.1Skamil
37601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37621.1Skamil}
37631.1Skamil
37641.1Skamil#if defined(TWAIT_HAVE_PID)
37651.1SkamilATF_TC(siginfo5);
37661.1SkamilATF_TC_HEAD(siginfo5, tc)
37671.1Skamil{
37681.1Skamil	atf_tc_set_md_var(tc, "descr",
37691.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
37701.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
37711.1Skamil}
37721.1Skamil
37731.1SkamilATF_TC_BODY(siginfo5, tc)
37741.1Skamil{
37751.1Skamil	const int exitval = 5;
37761.1Skamil	const int exitval2 = 15;
37771.1Skamil	const int sigval = SIGSTOP;
37781.1Skamil	pid_t child, child2, wpid;
37791.1Skamil#if defined(TWAIT_HAVE_STATUS)
37801.1Skamil	int status;
37811.1Skamil#endif
37821.1Skamil	ptrace_state_t state;
37831.1Skamil	const int slen = sizeof(state);
37841.1Skamil	ptrace_event_t event;
37851.1Skamil	const int elen = sizeof(event);
37861.1Skamil	struct ptrace_siginfo info;
37871.1Skamil
37881.1Skamil	memset(&info, 0, sizeof(info));
37891.1Skamil
37901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37921.1Skamil	if (child == 0) {
37931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37951.1Skamil
37961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37981.1Skamil
37991.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
38001.1Skamil
38011.1Skamil		if (child2 == 0)
38021.1Skamil			_exit(exitval2);
38031.1Skamil
38041.1Skamil		FORKEE_REQUIRE_SUCCESS
38051.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
38061.1Skamil
38071.1Skamil		forkee_status_exited(status, exitval2);
38081.1Skamil
38091.13Schristos		DPRINTF("Before exiting of the child process\n");
38101.1Skamil		_exit(exitval);
38111.1Skamil	}
38121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38131.1Skamil
38141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38161.1Skamil
38171.1Skamil	validate_status_stopped(status, sigval);
38181.1Skamil
38191.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38201.61Skre	SYSCALL_REQUIRE(
38211.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38221.1Skamil
38231.13Schristos	DPRINTF("Before checking siginfo_t\n");
38241.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
38251.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38261.1Skamil
38271.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
38281.1Skamil	event.pe_set_event = PTRACE_FORK;
38291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
38301.1Skamil
38311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38321.1Skamil	    "without signal to be sent\n");
38331.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
38341.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
38351.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
38361.1Skamil                "state.pe_other_pid=child)\n", child);
38371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38381.1Skamil
38391.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
38401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38411.1Skamil
38421.1Skamil	validate_status_stopped(status, SIGTRAP);
38431.1Skamil
38441.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38451.61Skre	SYSCALL_REQUIRE(
38461.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38471.1Skamil
38481.13Schristos	DPRINTF("Before checking siginfo_t\n");
38491.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38501.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
38511.1Skamil
38521.61Skre	SYSCALL_REQUIRE(
38531.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
38541.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
38551.1Skamil
38561.1Skamil	child2 = state.pe_other_pid;
38571.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
38581.1Skamil
38591.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
38601.1Skamil	    TWAIT_FNAME, child2, child);
38611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
38621.1Skamil	    child2);
38631.1Skamil
38641.1Skamil	validate_status_stopped(status, SIGTRAP);
38651.1Skamil
38661.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38671.61Skre	SYSCALL_REQUIRE(
38681.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38691.1Skamil
38701.13Schristos	DPRINTF("Before checking siginfo_t\n");
38711.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38721.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
38731.1Skamil
38741.61Skre	SYSCALL_REQUIRE(
38751.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
38761.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
38771.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
38781.1Skamil
38791.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
38801.1Skamil	    "without signal to be sent\n");
38811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
38821.1Skamil
38831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38841.1Skamil	    "without signal to be sent\n");
38851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38861.1Skamil
38871.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
38881.1Skamil	    TWAIT_FNAME);
38891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
38901.1Skamil	    child2);
38911.1Skamil
38921.1Skamil	validate_status_exited(status, exitval2);
38931.1Skamil
38941.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
38951.1Skamil	    TWAIT_FNAME);
38961.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
38971.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
38981.1Skamil
38991.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
39001.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
39011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39021.1Skamil
39031.1Skamil	validate_status_stopped(status, SIGCHLD);
39041.1Skamil
39051.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39061.61Skre	SYSCALL_REQUIRE(
39071.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39081.1Skamil
39091.13Schristos	DPRINTF("Before checking siginfo_t\n");
39101.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
39111.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
39121.1Skamil
39131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39141.1Skamil	    "without signal to be sent\n");
39151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39161.1Skamil
39171.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
39181.1Skamil	    TWAIT_FNAME);
39191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39201.1Skamil
39211.1Skamil	validate_status_exited(status, exitval);
39221.1Skamil
39231.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
39241.1Skamil	    TWAIT_FNAME);
39251.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39261.1Skamil}
39271.1Skamil#endif
39281.1Skamil
39291.1Skamil#if defined(PT_STEP)
39301.1SkamilATF_TC(siginfo6);
39311.1SkamilATF_TC_HEAD(siginfo6, tc)
39321.1Skamil{
39331.1Skamil	atf_tc_set_md_var(tc, "descr",
39341.1Skamil	    "Verify single PT_STEP call with signal information check");
39351.1Skamil}
39361.1Skamil
39371.1SkamilATF_TC_BODY(siginfo6, tc)
39381.1Skamil{
39391.1Skamil	const int exitval = 5;
39401.1Skamil	const int sigval = SIGSTOP;
39411.1Skamil	pid_t child, wpid;
39421.1Skamil#if defined(TWAIT_HAVE_STATUS)
39431.1Skamil	int status;
39441.1Skamil#endif
39451.1Skamil	int happy;
39461.1Skamil	struct ptrace_siginfo info;
39471.1Skamil
39481.1Skamil#if defined(__arm__)
39491.1Skamil	/* PT_STEP not supported on arm 32-bit */
39501.1Skamil	atf_tc_expect_fail("PR kern/52119");
39511.1Skamil#endif
39521.1Skamil
39531.1Skamil	memset(&info, 0, sizeof(info));
39541.1Skamil
39551.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39561.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39571.1Skamil	if (child == 0) {
39581.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39591.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39601.1Skamil
39611.1Skamil		happy = check_happy(100);
39621.1Skamil
39631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39651.1Skamil
39661.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
39671.1Skamil
39681.13Schristos		DPRINTF("Before exiting of the child process\n");
39691.1Skamil		_exit(exitval);
39701.1Skamil	}
39711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39721.1Skamil
39731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39751.1Skamil
39761.1Skamil	validate_status_stopped(status, sigval);
39771.1Skamil
39781.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39791.61Skre	SYSCALL_REQUIRE(
39801.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39811.1Skamil
39821.13Schristos	DPRINTF("Before checking siginfo_t\n");
39831.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
39841.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
39851.1Skamil
39861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39871.1Skamil	    "without signal to be sent (use PT_STEP)\n");
39881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
39891.1Skamil
39901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39921.1Skamil
39931.1Skamil	validate_status_stopped(status, SIGTRAP);
39941.1Skamil
39951.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39961.61Skre	SYSCALL_REQUIRE(
39971.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39981.1Skamil
39991.13Schristos	DPRINTF("Before checking siginfo_t\n");
40001.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
40011.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
40021.1Skamil
40031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40041.1Skamil	    "without signal to be sent\n");
40051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40061.1Skamil
40071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40091.1Skamil
40101.1Skamil	validate_status_exited(status, exitval);
40111.1Skamil
40121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40141.1Skamil}
40151.1Skamil#endif
40161.1Skamil
40171.1Skamilvolatile lwpid_t the_lwp_id = 0;
40181.1Skamil
40191.1Skamilstatic void
40201.1Skamillwp_main_func(void *arg)
40211.1Skamil{
40221.1Skamil	the_lwp_id = _lwp_self();
40231.1Skamil	_lwp_exit();
40241.1Skamil}
40251.1Skamil
40261.1SkamilATF_TC(lwp_create1);
40271.1SkamilATF_TC_HEAD(lwp_create1, tc)
40281.1Skamil{
40291.1Skamil	atf_tc_set_md_var(tc, "descr",
40301.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
40311.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
40321.1Skamil}
40331.1Skamil
40341.1SkamilATF_TC_BODY(lwp_create1, tc)
40351.1Skamil{
40361.1Skamil	const int exitval = 5;
40371.1Skamil	const int sigval = SIGSTOP;
40381.1Skamil	pid_t child, wpid;
40391.1Skamil#if defined(TWAIT_HAVE_STATUS)
40401.1Skamil	int status;
40411.1Skamil#endif
40421.1Skamil	ptrace_state_t state;
40431.1Skamil	const int slen = sizeof(state);
40441.1Skamil	ptrace_event_t event;
40451.1Skamil	const int elen = sizeof(event);
40461.1Skamil	ucontext_t uc;
40471.1Skamil	lwpid_t lid;
40481.1Skamil	static const size_t ssize = 16*1024;
40491.1Skamil	void *stack;
40501.1Skamil
40511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40531.1Skamil	if (child == 0) {
40541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40561.1Skamil
40571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40591.1Skamil
40601.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
40611.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
40621.1Skamil
40631.13Schristos		DPRINTF("Before making context for new lwp in child\n");
40641.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
40651.1Skamil
40661.13Schristos		DPRINTF("Before creating new in child\n");
40671.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
40681.1Skamil
40691.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
40701.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
40711.1Skamil
40721.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
40731.1Skamil		    "are the same\n", lid, the_lwp_id);
40741.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
40751.1Skamil
40761.13Schristos		DPRINTF("Before exiting of the child process\n");
40771.1Skamil		_exit(exitval);
40781.1Skamil	}
40791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40801.1Skamil
40811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40831.1Skamil
40841.1Skamil	validate_status_stopped(status, sigval);
40851.1Skamil
40861.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
40871.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
40881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
40891.1Skamil
40901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40911.1Skamil	    "without signal to be sent\n");
40921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40931.1Skamil
40941.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
40951.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
40961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40971.1Skamil
40981.1Skamil	validate_status_stopped(status, SIGTRAP);
40991.1Skamil
41001.61Skre	SYSCALL_REQUIRE(
41011.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41021.1Skamil
41031.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
41041.1Skamil
41051.1Skamil	lid = state.pe_lwp;
41061.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
41071.1Skamil
41081.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41091.1Skamil	    "without signal to be sent\n");
41101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41111.1Skamil
41121.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
41131.1Skamil	    TWAIT_FNAME);
41141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41151.1Skamil
41161.1Skamil	validate_status_exited(status, exitval);
41171.1Skamil
41181.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
41191.1Skamil	    TWAIT_FNAME);
41201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41211.1Skamil}
41221.1Skamil
41231.1SkamilATF_TC(lwp_exit1);
41241.1SkamilATF_TC_HEAD(lwp_exit1, tc)
41251.1Skamil{
41261.1Skamil	atf_tc_set_md_var(tc, "descr",
41271.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
41281.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
41291.1Skamil}
41301.1Skamil
41311.1SkamilATF_TC_BODY(lwp_exit1, tc)
41321.1Skamil{
41331.1Skamil	const int exitval = 5;
41341.1Skamil	const int sigval = SIGSTOP;
41351.1Skamil	pid_t child, wpid;
41361.1Skamil#if defined(TWAIT_HAVE_STATUS)
41371.1Skamil	int status;
41381.1Skamil#endif
41391.1Skamil	ptrace_state_t state;
41401.1Skamil	const int slen = sizeof(state);
41411.1Skamil	ptrace_event_t event;
41421.1Skamil	const int elen = sizeof(event);
41431.1Skamil	ucontext_t uc;
41441.1Skamil	lwpid_t lid;
41451.1Skamil	static const size_t ssize = 16*1024;
41461.1Skamil	void *stack;
41471.1Skamil
41481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41501.1Skamil	if (child == 0) {
41511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41531.1Skamil
41541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41561.1Skamil
41571.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
41581.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
41591.1Skamil
41601.13Schristos		DPRINTF("Before making context for new lwp in child\n");
41611.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
41621.1Skamil
41631.13Schristos		DPRINTF("Before creating new in child\n");
41641.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
41651.1Skamil
41661.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
41671.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
41681.1Skamil
41691.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
41701.1Skamil		    "are the same\n", lid, the_lwp_id);
41711.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
41721.1Skamil
41731.13Schristos		DPRINTF("Before exiting of the child process\n");
41741.1Skamil		_exit(exitval);
41751.1Skamil	}
41761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41771.1Skamil
41781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41801.1Skamil
41811.1Skamil	validate_status_stopped(status, sigval);
41821.1Skamil
41831.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
41841.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
41851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
41861.1Skamil
41871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41881.1Skamil	    "without signal to be sent\n");
41891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41901.1Skamil
41911.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
41921.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
41931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41941.1Skamil
41951.1Skamil	validate_status_stopped(status, SIGTRAP);
41961.1Skamil
41971.61Skre	SYSCALL_REQUIRE(
41981.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41991.1Skamil
42001.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
42011.1Skamil
42021.1Skamil	lid = state.pe_lwp;
42031.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
42041.1Skamil
42051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42061.1Skamil	    "without signal to be sent\n");
42071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42081.1Skamil
42091.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
42101.1Skamil	    TWAIT_FNAME);
42111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42121.1Skamil
42131.1Skamil	validate_status_exited(status, exitval);
42141.1Skamil
42151.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
42161.1Skamil	    TWAIT_FNAME);
42171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42181.1Skamil}
42191.1Skamil
42201.1SkamilATF_TC(signal1);
42211.1SkamilATF_TC_HEAD(signal1, tc)
42221.1Skamil{
42231.1Skamil	atf_tc_set_md_var(tc, "descr",
42241.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
42251.1Skamil	    "from catching other signals");
42261.1Skamil}
42271.1Skamil
42281.1SkamilATF_TC_BODY(signal1, tc)
42291.1Skamil{
42301.1Skamil	const int exitval = 5;
42311.1Skamil	const int sigval = SIGSTOP;
42321.1Skamil	const int sigmasked = SIGTRAP;
42331.1Skamil	const int signotmasked = SIGINT;
42341.1Skamil	pid_t child, wpid;
42351.1Skamil#if defined(TWAIT_HAVE_STATUS)
42361.1Skamil	int status;
42371.1Skamil#endif
42381.1Skamil	sigset_t intmask;
42391.1Skamil
42401.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42411.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42421.1Skamil	if (child == 0) {
42431.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42441.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42451.1Skamil
42461.1Skamil		sigemptyset(&intmask);
42471.1Skamil		sigaddset(&intmask, sigmasked);
42481.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42491.1Skamil
42501.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42511.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42521.1Skamil
42531.13Schristos		DPRINTF("Before raising %s from child\n",
42541.1Skamil		    strsignal(signotmasked));
42551.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
42561.1Skamil
42571.13Schristos		DPRINTF("Before exiting of the child process\n");
42581.1Skamil		_exit(exitval);
42591.1Skamil	}
42601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42611.1Skamil
42621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42641.1Skamil
42651.1Skamil	validate_status_stopped(status, sigval);
42661.1Skamil
42671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42681.1Skamil	    "without signal to be sent\n");
42691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42701.1Skamil
42711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42731.1Skamil
42741.1Skamil	validate_status_stopped(status, signotmasked);
42751.1Skamil
42761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42771.1Skamil	    "without signal to be sent\n");
42781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42791.1Skamil
42801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42821.1Skamil
42831.1Skamil	validate_status_exited(status, exitval);
42841.1Skamil
42851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42871.1Skamil}
42881.1Skamil
42891.1SkamilATF_TC(signal2);
42901.1SkamilATF_TC_HEAD(signal2, tc)
42911.1Skamil{
42921.1Skamil	atf_tc_set_md_var(tc, "descr",
42931.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
42941.1Skamil	    "catching this raised signal");
42951.1Skamil}
42961.1Skamil
42971.1SkamilATF_TC_BODY(signal2, tc)
42981.1Skamil{
42991.1Skamil	const int exitval = 5;
43001.1Skamil	const int sigval = SIGSTOP;
43011.1Skamil	const int sigmasked = SIGTRAP;
43021.1Skamil	pid_t child, wpid;
43031.1Skamil#if defined(TWAIT_HAVE_STATUS)
43041.1Skamil	int status;
43051.1Skamil#endif
43061.1Skamil	sigset_t intmask;
43071.1Skamil
43081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43101.1Skamil	if (child == 0) {
43111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43131.1Skamil
43141.1Skamil		sigemptyset(&intmask);
43151.1Skamil		sigaddset(&intmask, sigmasked);
43161.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43171.1Skamil
43181.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43191.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43201.1Skamil
43211.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
43221.1Skamil		    strsignal(sigmasked));
43231.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
43241.1Skamil
43251.13Schristos		DPRINTF("Before exiting of the child process\n");
43261.1Skamil		_exit(exitval);
43271.1Skamil	}
43281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43291.1Skamil
43301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43321.1Skamil
43331.1Skamil	validate_status_stopped(status, sigval);
43341.1Skamil
43351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43361.1Skamil	    "without signal to be sent\n");
43371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43381.1Skamil
43391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43411.1Skamil
43421.1Skamil	validate_status_exited(status, exitval);
43431.1Skamil
43441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43461.1Skamil}
43471.1Skamil
43481.1SkamilATF_TC(signal3);
43491.1SkamilATF_TC_HEAD(signal3, tc)
43501.1Skamil{
43511.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
43521.1Skamil	atf_tc_set_md_var(tc, "descr",
43531.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43541.1Skamil	    "catching software breakpoints");
43551.1Skamil}
43561.1Skamil
43571.1SkamilATF_TC_BODY(signal3, tc)
43581.1Skamil{
43591.1Skamil	const int exitval = 5;
43601.1Skamil	const int sigval = SIGSTOP;
43611.1Skamil	const int sigmasked = SIGTRAP;
43621.1Skamil	pid_t child, wpid;
43631.1Skamil#if defined(TWAIT_HAVE_STATUS)
43641.1Skamil	int status;
43651.1Skamil#endif
43661.1Skamil	sigset_t intmask;
43671.1Skamil
43681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43701.1Skamil	if (child == 0) {
43711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43731.1Skamil
43741.1Skamil		sigemptyset(&intmask);
43751.1Skamil		sigaddset(&intmask, sigmasked);
43761.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43771.1Skamil
43781.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43791.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43801.1Skamil
43811.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
43821.52Skamil		trigger_trap();
43831.1Skamil
43841.13Schristos		DPRINTF("Before exiting of the child process\n");
43851.1Skamil		_exit(exitval);
43861.1Skamil	}
43871.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43881.1Skamil
43891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43911.1Skamil
43921.1Skamil	validate_status_stopped(status, sigval);
43931.1Skamil
43941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43951.1Skamil	    "without signal to be sent\n");
43961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43971.1Skamil
43981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44001.1Skamil
44011.1Skamil	validate_status_stopped(status, sigmasked);
44021.1Skamil
44031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44041.1Skamil	    "without signal to be sent\n");
44051.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
44061.1Skamil
44071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44091.1Skamil
44101.49Skamil	validate_status_signaled(status, SIGKILL, 0);
44111.1Skamil
44121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44141.1Skamil}
44151.1Skamil
44161.1Skamil#if defined(PT_STEP)
44171.1SkamilATF_TC(signal4);
44181.1SkamilATF_TC_HEAD(signal4, tc)
44191.1Skamil{
44201.1Skamil	atf_tc_set_md_var(tc, "descr",
44211.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44221.1Skamil	    "catching single step trap");
44231.1Skamil}
44241.1Skamil
44251.1SkamilATF_TC_BODY(signal4, tc)
44261.1Skamil{
44271.1Skamil	const int exitval = 5;
44281.1Skamil	const int sigval = SIGSTOP;
44291.1Skamil	const int sigmasked = SIGTRAP;
44301.1Skamil	pid_t child, wpid;
44311.1Skamil#if defined(TWAIT_HAVE_STATUS)
44321.1Skamil	int status;
44331.1Skamil#endif
44341.1Skamil	sigset_t intmask;
44351.1Skamil	int happy;
44361.1Skamil
44371.1Skamil#if defined(__arm__)
44381.5Skamil	/* PT_STEP not supported on arm 32-bit */
44391.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
44401.1Skamil#endif
44411.1Skamil
44421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44441.1Skamil	if (child == 0) {
44451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44471.1Skamil
44481.1Skamil		happy = check_happy(100);
44491.1Skamil
44501.1Skamil		sigemptyset(&intmask);
44511.1Skamil		sigaddset(&intmask, sigmasked);
44521.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44531.1Skamil
44541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44561.1Skamil
44571.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
44581.1Skamil
44591.13Schristos		DPRINTF("Before exiting of the child process\n");
44601.1Skamil		_exit(exitval);
44611.1Skamil	}
44621.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44631.1Skamil
44641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44661.1Skamil
44671.1Skamil	validate_status_stopped(status, sigval);
44681.1Skamil
44691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44701.1Skamil	    "without signal to be sent\n");
44711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
44721.1Skamil
44731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44751.1Skamil
44761.1Skamil	validate_status_stopped(status, sigmasked);
44771.1Skamil
44781.13Schristos	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\n", TWAIT_FNAME);
44831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44841.1Skamil
44851.1Skamil	validate_status_exited(status, exitval);
44861.1Skamil
44871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44891.1Skamil}
44901.1Skamil#endif
44911.1Skamil
44921.1SkamilATF_TC(signal5);
44931.1SkamilATF_TC_HEAD(signal5, tc)
44941.1Skamil{
44951.1Skamil	atf_tc_set_md_var(tc, "descr",
44961.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44971.1Skamil	    "catching exec() breakpoint");
44981.1Skamil}
44991.1Skamil
45001.1SkamilATF_TC_BODY(signal5, tc)
45011.1Skamil{
45021.1Skamil	const int sigval = SIGSTOP;
45031.1Skamil	const int sigmasked = SIGTRAP;
45041.1Skamil	pid_t child, wpid;
45051.1Skamil#if defined(TWAIT_HAVE_STATUS)
45061.1Skamil	int status;
45071.1Skamil#endif
45081.58Skamil	struct ptrace_siginfo info;
45091.1Skamil	sigset_t intmask;
45101.1Skamil
45111.58Skamil	memset(&info, 0, sizeof(info));
45121.14Schristos
45131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45151.1Skamil	if (child == 0) {
45161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45181.1Skamil
45191.1Skamil		sigemptyset(&intmask);
45201.1Skamil		sigaddset(&intmask, sigmasked);
45211.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45221.1Skamil
45231.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45241.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45251.1Skamil
45261.13Schristos		DPRINTF("Before calling execve(2) from child\n");
45271.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
45281.1Skamil
45291.58Skamil		/* NOTREACHED */
45301.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
45311.1Skamil	}
45321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45331.1Skamil
45341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45361.1Skamil
45371.1Skamil	validate_status_stopped(status, sigval);
45381.1Skamil
45391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45401.1Skamil	    "without signal to be sent\n");
45411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45421.1Skamil
45431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45451.1Skamil
45461.1Skamil	validate_status_stopped(status, sigmasked);
45471.1Skamil
45481.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45491.61Skre	SYSCALL_REQUIRE(
45501.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45511.58Skamil
45521.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45531.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
45541.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45551.58Skamil	    info.psi_siginfo.si_errno);
45561.58Skamil
45571.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
45581.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
45591.58Skamil
45601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45611.1Skamil	    "without signal to be sent\n");
45621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45631.1Skamil
45641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45661.1Skamil
45671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45681.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45691.1Skamil}
45701.1Skamil
45711.1Skamil#if defined(TWAIT_HAVE_PID)
45721.1SkamilATF_TC(signal6);
45731.1SkamilATF_TC_HEAD(signal6, tc)
45741.1Skamil{
45751.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
45761.1Skamil	atf_tc_set_md_var(tc, "descr",
45771.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45781.1Skamil	    "catching PTRACE_FORK breakpoint");
45791.1Skamil}
45801.1Skamil
45811.1SkamilATF_TC_BODY(signal6, tc)
45821.1Skamil{
45831.1Skamil	const int exitval = 5;
45841.1Skamil	const int exitval2 = 15;
45851.1Skamil	const int sigval = SIGSTOP;
45861.1Skamil	const int sigmasked = SIGTRAP;
45871.1Skamil	pid_t child, child2, wpid;
45881.1Skamil#if defined(TWAIT_HAVE_STATUS)
45891.1Skamil	int status;
45901.1Skamil#endif
45911.1Skamil	sigset_t intmask;
45921.1Skamil	ptrace_state_t state;
45931.1Skamil	const int slen = sizeof(state);
45941.1Skamil	ptrace_event_t event;
45951.1Skamil	const int elen = sizeof(event);
45961.1Skamil
45971.38Skamil	atf_tc_expect_fail("PR kern/51918");
45981.14Schristos
45991.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46001.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46011.1Skamil	if (child == 0) {
46021.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46031.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46041.1Skamil
46051.1Skamil		sigemptyset(&intmask);
46061.1Skamil		sigaddset(&intmask, sigmasked);
46071.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46081.1Skamil
46091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46111.1Skamil
46121.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
46131.1Skamil
46141.1Skamil		if (child2 == 0)
46151.1Skamil			_exit(exitval2);
46161.1Skamil
46171.1Skamil		FORKEE_REQUIRE_SUCCESS
46181.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
46191.1Skamil
46201.1Skamil		forkee_status_exited(status, exitval2);
46211.1Skamil
46221.13Schristos		DPRINTF("Before exiting of the child process\n");
46231.1Skamil		_exit(exitval);
46241.1Skamil	}
46251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46261.1Skamil
46271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46291.1Skamil
46301.1Skamil	validate_status_stopped(status, sigval);
46311.1Skamil
46321.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
46331.1Skamil	event.pe_set_event = PTRACE_FORK;
46341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
46351.1Skamil
46361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46371.1Skamil	    "without signal to be sent\n");
46381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46391.1Skamil
46401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46421.1Skamil
46431.1Skamil	validate_status_stopped(status, sigmasked);
46441.1Skamil
46451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
46461.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46471.1Skamil
46481.1Skamil	child2 = state.pe_other_pid;
46491.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
46501.1Skamil
46511.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
46521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46531.1Skamil	    child2);
46541.1Skamil
46551.1Skamil	validate_status_stopped(status, SIGTRAP);
46561.1Skamil
46571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
46581.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46591.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
46601.1Skamil
46611.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
46621.1Skamil	    "without signal to be sent\n");
46631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
46641.1Skamil
46651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46661.1Skamil	    "without signal to be sent\n");
46671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46681.1Skamil
46691.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
46701.1Skamil	    TWAIT_FNAME);
46711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46721.57Skamil	    child2);
46731.1Skamil
46741.1Skamil	validate_status_exited(status, exitval2);
46751.1Skamil
46761.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
46771.1Skamil	    TWAIT_FNAME);
46781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
46791.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
46801.1Skamil
46811.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
46821.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
46831.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46841.1Skamil
46851.1Skamil	validate_status_stopped(status, SIGCHLD);
46861.1Skamil
46871.57Skamil	DPRINTF("Before resuming the child process where it left off and "
46881.1Skamil	    "without signal to be sent\n");
46891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46901.1Skamil
46911.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
46921.1Skamil	    TWAIT_FNAME);
46931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46941.1Skamil
46951.1Skamil	validate_status_exited(status, exitval);
46961.1Skamil
46971.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
46981.57Skamil	    TWAIT_FNAME);
46991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47001.1Skamil}
47011.1Skamil#endif
47021.1Skamil
47031.1Skamil#if defined(TWAIT_HAVE_PID)
47041.1SkamilATF_TC(signal7);
47051.1SkamilATF_TC_HEAD(signal7, tc)
47061.1Skamil{
47071.1Skamil	atf_tc_set_md_var(tc, "descr",
47081.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
47091.1Skamil	    "catching PTRACE_VFORK breakpoint");
47101.1Skamil}
47111.1Skamil
47121.1SkamilATF_TC_BODY(signal7, tc)
47131.1Skamil{
47141.1Skamil	const int exitval = 5;
47151.1Skamil	const int exitval2 = 15;
47161.1Skamil	const int sigval = SIGSTOP;
47171.1Skamil	const int sigmasked = SIGTRAP;
47181.1Skamil	pid_t child, child2, wpid;
47191.1Skamil#if defined(TWAIT_HAVE_STATUS)
47201.1Skamil	int status;
47211.1Skamil#endif
47221.1Skamil	sigset_t intmask;
47231.1Skamil	ptrace_state_t state;
47241.1Skamil	const int slen = sizeof(state);
47251.1Skamil	ptrace_event_t event;
47261.1Skamil	const int elen = sizeof(event);
47271.1Skamil
47281.38Skamil	atf_tc_expect_fail("PR kern/51918");
47291.14Schristos
47301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47321.1Skamil	if (child == 0) {
47331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47351.1Skamil
47361.1Skamil		sigemptyset(&intmask);
47371.1Skamil		sigaddset(&intmask, sigmasked);
47381.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
47391.1Skamil
47401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47421.1Skamil
47431.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
47441.1Skamil
47451.1Skamil		if (child2 == 0)
47461.1Skamil			_exit(exitval2);
47471.1Skamil
47481.1Skamil		FORKEE_REQUIRE_SUCCESS
47491.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
47501.1Skamil
47511.1Skamil		forkee_status_exited(status, exitval2);
47521.1Skamil
47531.13Schristos		DPRINTF("Before exiting of the child process\n");
47541.1Skamil		_exit(exitval);
47551.1Skamil	}
47561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47571.1Skamil
47581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47601.1Skamil
47611.1Skamil	validate_status_stopped(status, sigval);
47621.1Skamil
47631.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
47641.1Skamil	event.pe_set_event = PTRACE_VFORK;
47651.61Skre	SYSCALL_REQUIRE(
47661.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
47671.61Skre	    errno == ENOTSUP);
47681.1Skamil
47691.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47701.1Skamil	    "without signal to be sent\n");
47711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47721.1Skamil
47731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47751.1Skamil
47761.1Skamil	validate_status_stopped(status, sigmasked);
47771.1Skamil
47781.61Skre	SYSCALL_REQUIRE(
47791.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
47801.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
47811.1Skamil
47821.1Skamil	child2 = state.pe_other_pid;
47831.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
47841.1Skamil
47851.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
47861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
47871.1Skamil	    child2);
47881.1Skamil
47891.1Skamil	validate_status_stopped(status, SIGTRAP);
47901.1Skamil
47911.61Skre	SYSCALL_REQUIRE(
47921.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
47931.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
47941.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
47951.1Skamil
47961.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
47971.1Skamil	    "without signal to be sent\n");
47981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
47991.1Skamil
48001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48011.1Skamil	    "without signal to be sent\n");
48021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48031.1Skamil
48041.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
48051.1Skamil	    TWAIT_FNAME);
48061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
48071.57Skamil	    child2);
48081.1Skamil
48091.1Skamil	validate_status_exited(status, exitval2);
48101.1Skamil
48111.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
48121.1Skamil	    TWAIT_FNAME);
48131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
48141.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
48151.1Skamil
48161.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48171.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
48181.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48191.1Skamil
48201.1Skamil	validate_status_stopped(status, SIGCHLD);
48211.1Skamil
48221.57Skamil	DPRINTF("Before resuming the child process where it left off and "
48231.1Skamil	    "without signal to be sent\n");
48241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48251.1Skamil
48261.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48271.1Skamil	    TWAIT_FNAME);
48281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48291.1Skamil
48301.1Skamil	validate_status_exited(status, exitval);
48311.1Skamil
48321.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48331.57Skamil	    TWAIT_FNAME);
48341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48351.1Skamil}
48361.1Skamil#endif
48371.1Skamil
48381.1SkamilATF_TC(signal8);
48391.1SkamilATF_TC_HEAD(signal8, tc)
48401.1Skamil{
48411.1Skamil	atf_tc_set_md_var(tc, "descr",
48421.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
48431.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
48441.1Skamil}
48451.1Skamil
48461.1SkamilATF_TC_BODY(signal8, tc)
48471.1Skamil{
48481.1Skamil	const int exitval = 5;
48491.1Skamil	const int exitval2 = 15;
48501.1Skamil	const int sigval = SIGSTOP;
48511.1Skamil	const int sigmasked = SIGTRAP;
48521.1Skamil	pid_t child, child2, wpid;
48531.1Skamil#if defined(TWAIT_HAVE_STATUS)
48541.1Skamil	int status;
48551.1Skamil#endif
48561.1Skamil	sigset_t intmask;
48571.1Skamil	ptrace_state_t state;
48581.1Skamil	const int slen = sizeof(state);
48591.1Skamil	ptrace_event_t event;
48601.1Skamil	const int elen = sizeof(event);
48611.1Skamil
48621.14Schristos	atf_tc_expect_fail("PR kern/51918");
48631.14Schristos
48641.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48651.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48661.1Skamil	if (child == 0) {
48671.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48681.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48691.1Skamil
48701.1Skamil		sigemptyset(&intmask);
48711.1Skamil		sigaddset(&intmask, sigmasked);
48721.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
48731.1Skamil
48741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48761.1Skamil
48771.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
48781.1Skamil
48791.1Skamil		if (child2 == 0)
48801.1Skamil			_exit(exitval2);
48811.1Skamil
48821.1Skamil		FORKEE_REQUIRE_SUCCESS
48831.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
48841.1Skamil
48851.1Skamil		forkee_status_exited(status, exitval2);
48861.1Skamil
48871.13Schristos		DPRINTF("Before exiting of the child process\n");
48881.1Skamil		_exit(exitval);
48891.1Skamil	}
48901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48911.1Skamil
48921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48941.1Skamil
48951.1Skamil	validate_status_stopped(status, sigval);
48961.1Skamil
48971.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
48981.1Skamil	    child);
48991.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
49001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
49011.1Skamil
49021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49031.1Skamil	    "without signal to be sent\n");
49041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49051.1Skamil
49061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49081.1Skamil
49091.1Skamil	validate_status_stopped(status, sigmasked);
49101.1Skamil
49111.61Skre	SYSCALL_REQUIRE(
49121.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
49131.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
49141.1Skamil
49151.1Skamil	child2 = state.pe_other_pid;
49161.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
49171.1Skamil
49181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49191.1Skamil	    "without signal to be sent\n");
49201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49211.1Skamil
49221.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49231.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
49241.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49251.1Skamil
49261.1Skamil	validate_status_stopped(status, SIGCHLD);
49271.1Skamil
49281.57Skamil	DPRINTF("Before resuming the child process where it left off and "
49291.1Skamil	    "without signal to be sent\n");
49301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49311.1Skamil
49321.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49331.1Skamil	    TWAIT_FNAME);
49341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49351.1Skamil
49361.1Skamil	validate_status_exited(status, exitval);
49371.1Skamil
49381.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49391.57Skamil	    TWAIT_FNAME);
49401.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49411.1Skamil}
49421.1Skamil
49431.1SkamilATF_TC(signal9);
49441.1SkamilATF_TC_HEAD(signal9, tc)
49451.1Skamil{
49461.1Skamil	atf_tc_set_md_var(tc, "descr",
49471.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
49481.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
49491.1Skamil}
49501.1Skamil
49511.1SkamilATF_TC_BODY(signal9, tc)
49521.1Skamil{
49531.1Skamil	const int exitval = 5;
49541.1Skamil	const int sigval = SIGSTOP;
49551.1Skamil	const int sigmasked = SIGTRAP;
49561.1Skamil	pid_t child, wpid;
49571.1Skamil#if defined(TWAIT_HAVE_STATUS)
49581.1Skamil	int status;
49591.1Skamil#endif
49601.1Skamil	sigset_t intmask;
49611.1Skamil	ptrace_state_t state;
49621.1Skamil	const int slen = sizeof(state);
49631.1Skamil	ptrace_event_t event;
49641.1Skamil	const int elen = sizeof(event);
49651.1Skamil	ucontext_t uc;
49661.1Skamil	lwpid_t lid;
49671.1Skamil	static const size_t ssize = 16*1024;
49681.1Skamil	void *stack;
49691.1Skamil
49701.14Schristos	atf_tc_expect_fail("PR kern/51918");
49711.14Schristos
49721.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49731.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49741.1Skamil	if (child == 0) {
49751.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49761.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49771.1Skamil
49781.1Skamil		sigemptyset(&intmask);
49791.1Skamil		sigaddset(&intmask, sigmasked);
49801.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
49811.1Skamil
49821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49841.1Skamil
49851.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
49861.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
49871.1Skamil
49881.13Schristos		DPRINTF("Before making context for new lwp in child\n");
49891.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
49901.1Skamil
49911.13Schristos		DPRINTF("Before creating new in child\n");
49921.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
49931.1Skamil
49941.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
49951.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
49961.1Skamil
49971.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
49981.1Skamil		    "are the same\n", lid, the_lwp_id);
49991.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
50001.1Skamil
50011.13Schristos		DPRINTF("Before exiting of the child process\n");
50021.1Skamil		_exit(exitval);
50031.1Skamil	}
50041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50051.1Skamil
50061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50081.1Skamil
50091.1Skamil	validate_status_stopped(status, sigval);
50101.1Skamil
50111.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
50121.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
50131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50141.1Skamil
50151.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50161.1Skamil	    "without signal to be sent\n");
50171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50181.1Skamil
50191.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50201.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
50211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50221.1Skamil
50231.1Skamil	validate_status_stopped(status, sigmasked);
50241.1Skamil
50251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50261.1Skamil
50271.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
50281.1Skamil
50291.1Skamil	lid = state.pe_lwp;
50301.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
50311.1Skamil
50321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50331.1Skamil	    "without signal to be sent\n");
50341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50351.1Skamil
50361.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50371.1Skamil	    TWAIT_FNAME);
50381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50391.1Skamil
50401.1Skamil	validate_status_exited(status, exitval);
50411.1Skamil
50421.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
50431.1Skamil	    TWAIT_FNAME);
50441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50451.1Skamil}
50461.1Skamil
50471.1SkamilATF_TC(signal10);
50481.1SkamilATF_TC_HEAD(signal10, tc)
50491.1Skamil{
50501.1Skamil	atf_tc_set_md_var(tc, "descr",
50511.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
50521.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
50531.1Skamil}
50541.1Skamil
50551.1SkamilATF_TC_BODY(signal10, tc)
50561.1Skamil{
50571.1Skamil	const int exitval = 5;
50581.1Skamil	const int sigval = SIGSTOP;
50591.1Skamil	const int sigmasked = SIGTRAP;
50601.1Skamil	pid_t child, wpid;
50611.1Skamil#if defined(TWAIT_HAVE_STATUS)
50621.1Skamil	int status;
50631.1Skamil#endif
50641.1Skamil	sigset_t intmask;
50651.1Skamil	ptrace_state_t state;
50661.1Skamil	const int slen = sizeof(state);
50671.1Skamil	ptrace_event_t event;
50681.1Skamil	const int elen = sizeof(event);
50691.1Skamil	ucontext_t uc;
50701.1Skamil	lwpid_t lid;
50711.1Skamil	static const size_t ssize = 16*1024;
50721.1Skamil	void *stack;
50731.1Skamil
50741.14Schristos	atf_tc_expect_fail("PR kern/51918");
50751.14Schristos
50761.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50771.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50781.1Skamil	if (child == 0) {
50791.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50801.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50811.1Skamil
50821.1Skamil		sigemptyset(&intmask);
50831.1Skamil		sigaddset(&intmask, sigmasked);
50841.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
50851.1Skamil
50861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50881.1Skamil
50891.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
50901.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
50911.1Skamil
50921.13Schristos		DPRINTF("Before making context for new lwp in child\n");
50931.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
50941.1Skamil
50951.13Schristos		DPRINTF("Before creating new in child\n");
50961.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
50971.1Skamil
50981.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
50991.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
51001.1Skamil
51011.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
51021.1Skamil		    "are the same\n", lid, the_lwp_id);
51031.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
51041.1Skamil
51051.13Schristos		DPRINTF("Before exiting of the child process\n");
51061.1Skamil		_exit(exitval);
51071.1Skamil	}
51081.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51091.1Skamil
51101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51111.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51121.1Skamil
51131.1Skamil	validate_status_stopped(status, sigval);
51141.1Skamil
51151.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
51161.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
51171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
51181.1Skamil
51191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51201.1Skamil	    "without signal to be sent\n");
51211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51221.1Skamil
51231.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
51241.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
51251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51261.1Skamil
51271.1Skamil	validate_status_stopped(status, sigmasked);
51281.1Skamil
51291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51301.1Skamil
51311.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
51321.1Skamil
51331.1Skamil	lid = state.pe_lwp;
51341.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
51351.1Skamil
51361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51371.1Skamil	    "without signal to be sent\n");
51381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51391.1Skamil
51401.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51411.1Skamil	    TWAIT_FNAME);
51421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51431.1Skamil
51441.1Skamil	validate_status_exited(status, exitval);
51451.1Skamil
51461.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51471.1Skamil	    TWAIT_FNAME);
51481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51491.1Skamil}
51501.1Skamil
51511.1Skamilstatic void
51521.1Skamillwp_main_stop(void *arg)
51531.1Skamil{
51541.1Skamil	the_lwp_id = _lwp_self();
51551.1Skamil
51561.1Skamil	raise(SIGTRAP);
51571.1Skamil
51581.1Skamil	_lwp_exit();
51591.1Skamil}
51601.1Skamil
51611.1SkamilATF_TC(suspend1);
51621.1SkamilATF_TC_HEAD(suspend1, tc)
51631.1Skamil{
51641.1Skamil	atf_tc_set_md_var(tc, "descr",
51651.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
51661.1Skamil	    "resumed by a tracee");
51671.1Skamil}
51681.1Skamil
51691.1SkamilATF_TC_BODY(suspend1, tc)
51701.1Skamil{
51711.1Skamil	const int exitval = 5;
51721.1Skamil	const int sigval = SIGSTOP;
51731.1Skamil	pid_t child, wpid;
51741.1Skamil#if defined(TWAIT_HAVE_STATUS)
51751.1Skamil	int status;
51761.1Skamil#endif
51771.1Skamil	ucontext_t uc;
51781.1Skamil	lwpid_t lid;
51791.1Skamil	static const size_t ssize = 16*1024;
51801.1Skamil	void *stack;
51811.1Skamil	struct ptrace_lwpinfo pl;
51821.1Skamil	struct ptrace_siginfo psi;
51831.1Skamil	volatile int go = 0;
51841.1Skamil
51851.17Skamil	// Feature pending for refactoring
51861.17Skamil	atf_tc_expect_fail("PR kern/51995");
51871.17Skamil
51881.16Skamil	// Hangs with qemu
51891.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
51901.16Skamil
51911.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51921.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51931.1Skamil	if (child == 0) {
51941.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51951.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51961.1Skamil
51971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51991.1Skamil
52001.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
52011.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
52021.1Skamil
52031.13Schristos		DPRINTF("Before making context for new lwp in child\n");
52041.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
52051.1Skamil
52061.13Schristos		DPRINTF("Before creating new in child\n");
52071.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
52081.1Skamil
52091.1Skamil		while (go == 0)
52101.1Skamil			continue;
52111.1Skamil
52121.1Skamil		raise(SIGINT);
52131.1Skamil
52141.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
52151.1Skamil
52161.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
52171.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
52181.1Skamil
52191.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
52201.1Skamil		    "are the same\n", lid, the_lwp_id);
52211.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
52221.1Skamil
52231.13Schristos		DPRINTF("Before exiting of the child process\n");
52241.1Skamil		_exit(exitval);
52251.1Skamil	}
52261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52271.1Skamil
52281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52301.1Skamil
52311.1Skamil	validate_status_stopped(status, sigval);
52321.1Skamil
52331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52341.1Skamil	    "without signal to be sent\n");
52351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52361.1Skamil
52371.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52381.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
52391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52401.1Skamil
52411.1Skamil	validate_status_stopped(status, SIGTRAP);
52421.1Skamil
52431.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
52441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
52451.1Skamil
52461.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
52471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
52481.1Skamil
52491.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
52501.1Skamil	    child, getpid());
52511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
52521.1Skamil
52531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52541.1Skamil	    "without signal to be sent\n");
52551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52561.1Skamil
52571.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52581.1Skamil	    "SIGINT\n", TWAIT_FNAME);
52591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52601.1Skamil
52611.1Skamil	validate_status_stopped(status, SIGINT);
52621.1Skamil
52631.1Skamil	pl.pl_lwpid = 0;
52641.1Skamil
52651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52661.1Skamil	while (pl.pl_lwpid != 0) {
52671.1Skamil
52681.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52691.1Skamil		switch (pl.pl_lwpid) {
52701.1Skamil		case 1:
52711.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
52721.1Skamil			break;
52731.1Skamil		case 2:
52741.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
52751.1Skamil			break;
52761.1Skamil		}
52771.1Skamil	}
52781.1Skamil
52791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52801.1Skamil	    "without signal to be sent\n");
52811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52821.1Skamil
52831.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52841.1Skamil	    TWAIT_FNAME);
52851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52861.1Skamil
52871.1Skamil	validate_status_exited(status, exitval);
52881.1Skamil
52891.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52901.1Skamil	    TWAIT_FNAME);
52911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52921.1Skamil}
52931.1Skamil
52941.1SkamilATF_TC(suspend2);
52951.1SkamilATF_TC_HEAD(suspend2, tc)
52961.1Skamil{
52971.1Skamil	atf_tc_set_md_var(tc, "descr",
52981.1Skamil	    "Verify that the while the only thread within a process is "
52991.1Skamil	    "suspended, the whole process cannot be unstopped");
53001.1Skamil}
53011.1Skamil
53021.1SkamilATF_TC_BODY(suspend2, tc)
53031.1Skamil{
53041.1Skamil	const int exitval = 5;
53051.1Skamil	const int sigval = SIGSTOP;
53061.1Skamil	pid_t child, wpid;
53071.1Skamil#if defined(TWAIT_HAVE_STATUS)
53081.1Skamil	int status;
53091.1Skamil#endif
53101.1Skamil	struct ptrace_siginfo psi;
53111.1Skamil
53121.17Skamil	// Feature pending for refactoring
53131.17Skamil	atf_tc_expect_fail("PR kern/51995");
53141.17Skamil
53151.16Skamil	// Hangs with qemu
53161.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
53171.16Skamil
53181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53201.1Skamil	if (child == 0) {
53211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53231.1Skamil
53241.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53251.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53261.1Skamil
53271.13Schristos		DPRINTF("Before exiting of the child process\n");
53281.1Skamil		_exit(exitval);
53291.1Skamil	}
53301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53311.1Skamil
53321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53341.1Skamil
53351.1Skamil	validate_status_stopped(status, sigval);
53361.1Skamil
53371.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
53381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
53391.1Skamil
53401.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
53411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
53421.1Skamil
53431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53441.1Skamil	    "without signal to be sent\n");
53451.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
53461.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
53471.1Skamil
53481.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
53491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
53501.1Skamil
53511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53521.1Skamil	    "without signal to be sent\n");
53531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53541.1Skamil
53551.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53561.1Skamil	    TWAIT_FNAME);
53571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53581.1Skamil
53591.1Skamil	validate_status_exited(status, exitval);
53601.1Skamil
53611.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53621.1Skamil	    TWAIT_FNAME);
53631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53641.1Skamil}
53651.1Skamil
53661.1SkamilATF_TC(resume1);
53671.1SkamilATF_TC_HEAD(resume1, tc)
53681.1Skamil{
53691.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
53701.1Skamil	atf_tc_set_md_var(tc, "descr",
53711.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
53721.1Skamil	    "resumed by the debugger");
53731.1Skamil}
53741.1Skamil
53751.1SkamilATF_TC_BODY(resume1, tc)
53761.1Skamil{
53771.1Skamil	struct msg_fds fds;
53781.1Skamil	const int exitval = 5;
53791.1Skamil	const int sigval = SIGSTOP;
53801.1Skamil	pid_t child, wpid;
53811.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
53821.1Skamil#if defined(TWAIT_HAVE_STATUS)
53831.1Skamil	int status;
53841.1Skamil#endif
53851.1Skamil	ucontext_t uc;
53861.1Skamil	lwpid_t lid;
53871.1Skamil	static const size_t ssize = 16*1024;
53881.1Skamil	void *stack;
53891.1Skamil	struct ptrace_lwpinfo pl;
53901.1Skamil	struct ptrace_siginfo psi;
53911.1Skamil
53921.17Skamil	// Feature pending for refactoring
53931.17Skamil	atf_tc_expect_fail("PR kern/51995");
53941.17Skamil
53951.15Schristos	// Hangs with qemu
53961.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
53971.1Skamil
53981.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
53991.1Skamil
54001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54021.1Skamil	if (child == 0) {
54031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54051.1Skamil
54061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54081.1Skamil
54091.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54101.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54111.1Skamil
54121.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54131.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
54141.1Skamil
54151.13Schristos		DPRINTF("Before creating new in child\n");
54161.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54171.1Skamil
54181.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
54191.1Skamil
54201.1Skamil		raise(SIGINT);
54211.1Skamil
54221.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54231.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54241.1Skamil
54251.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54261.1Skamil		    "are the same\n", lid, the_lwp_id);
54271.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54281.1Skamil
54291.13Schristos		DPRINTF("Before exiting of the child process\n");
54301.1Skamil		_exit(exitval);
54311.1Skamil	}
54321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54331.1Skamil
54341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54361.1Skamil
54371.1Skamil	validate_status_stopped(status, sigval);
54381.1Skamil
54391.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54401.1Skamil	    "without signal to be sent\n");
54411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54421.1Skamil
54431.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54441.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54461.1Skamil
54471.1Skamil	validate_status_stopped(status, SIGTRAP);
54481.1Skamil
54491.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
54501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
54511.1Skamil
54521.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
54531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
54541.1Skamil
54551.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
54561.1Skamil
54571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54581.1Skamil	    "without signal to be sent\n");
54591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54601.1Skamil
54611.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54621.1Skamil	    "SIGINT\n", TWAIT_FNAME);
54631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54641.1Skamil
54651.1Skamil	validate_status_stopped(status, SIGINT);
54661.1Skamil
54671.1Skamil	pl.pl_lwpid = 0;
54681.1Skamil
54691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54701.1Skamil	while (pl.pl_lwpid != 0) {
54711.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54721.1Skamil		switch (pl.pl_lwpid) {
54731.1Skamil		case 1:
54741.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
54751.1Skamil			break;
54761.1Skamil		case 2:
54771.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
54781.1Skamil			break;
54791.1Skamil		}
54801.1Skamil	}
54811.1Skamil
54821.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
54831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
54841.1Skamil
54851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54861.1Skamil	    "without signal to be sent\n");
54871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54881.1Skamil
54891.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54901.1Skamil	    TWAIT_FNAME);
54911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54921.1Skamil
54931.1Skamil	validate_status_exited(status, exitval);
54941.1Skamil
54951.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54961.1Skamil	    TWAIT_FNAME);
54971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54981.1Skamil
54991.1Skamil	msg_close(&fds);
55001.1Skamil
55011.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
55021.1Skamil	sleep(10);
55031.1Skamil}
55041.1Skamil
55051.1SkamilATF_TC(syscall1);
55061.1SkamilATF_TC_HEAD(syscall1, tc)
55071.1Skamil{
55081.1Skamil	atf_tc_set_md_var(tc, "descr",
55091.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
55101.1Skamil}
55111.1Skamil
55121.1SkamilATF_TC_BODY(syscall1, tc)
55131.1Skamil{
55141.1Skamil	const int exitval = 5;
55151.1Skamil	const int sigval = SIGSTOP;
55161.1Skamil	pid_t child, wpid;
55171.1Skamil#if defined(TWAIT_HAVE_STATUS)
55181.1Skamil	int status;
55191.1Skamil#endif
55201.1Skamil	struct ptrace_siginfo info;
55211.1Skamil	memset(&info, 0, sizeof(info));
55221.1Skamil
55231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55251.1Skamil	if (child == 0) {
55261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55281.1Skamil
55291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55311.1Skamil
55321.1Skamil		syscall(SYS_getpid);
55331.1Skamil
55341.13Schristos		DPRINTF("Before exiting of the child process\n");
55351.1Skamil		_exit(exitval);
55361.1Skamil	}
55371.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55381.1Skamil
55391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55411.1Skamil
55421.1Skamil	validate_status_stopped(status, sigval);
55431.1Skamil
55441.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55451.1Skamil	    "without signal to be sent\n");
55461.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55471.1Skamil
55481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55501.1Skamil
55511.1Skamil	validate_status_stopped(status, SIGTRAP);
55521.1Skamil
55531.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55551.1Skamil
55561.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55571.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55581.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55591.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
55601.1Skamil
55611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55621.1Skamil	    "without signal to be sent\n");
55631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55641.1Skamil
55651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55671.1Skamil
55681.1Skamil	validate_status_stopped(status, SIGTRAP);
55691.1Skamil
55701.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55721.1Skamil
55731.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55741.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55751.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55761.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
55771.1Skamil
55781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55791.1Skamil	    "without signal to be sent\n");
55801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55811.1Skamil
55821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55841.1Skamil
55851.1Skamil	validate_status_exited(status, exitval);
55861.1Skamil
55871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55881.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55891.1Skamil}
55901.1Skamil
55911.1SkamilATF_TC(syscallemu1);
55921.1SkamilATF_TC_HEAD(syscallemu1, tc)
55931.1Skamil{
55941.1Skamil	atf_tc_set_md_var(tc, "descr",
55951.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
55961.1Skamil}
55971.1Skamil
55981.1SkamilATF_TC_BODY(syscallemu1, tc)
55991.1Skamil{
56001.1Skamil	const int exitval = 5;
56011.1Skamil	const int sigval = SIGSTOP;
56021.1Skamil	pid_t child, wpid;
56031.1Skamil#if defined(TWAIT_HAVE_STATUS)
56041.1Skamil	int status;
56051.1Skamil#endif
56061.1Skamil
56071.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
56081.6Skamil	/* syscallemu does not work on sparc (32-bit) */
56091.6Skamil	atf_tc_expect_fail("PR kern/52166");
56101.6Skamil#endif
56111.6Skamil
56121.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56131.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56141.1Skamil	if (child == 0) {
56151.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56161.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56171.1Skamil
56181.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56191.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56201.1Skamil
56211.1Skamil		syscall(SYS_exit, 100);
56221.1Skamil
56231.13Schristos		DPRINTF("Before exiting of the child process\n");
56241.1Skamil		_exit(exitval);
56251.1Skamil	}
56261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56271.1Skamil
56281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56301.1Skamil
56311.1Skamil	validate_status_stopped(status, sigval);
56321.1Skamil
56331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56341.1Skamil	    "without signal to be sent\n");
56351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
56361.1Skamil
56371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56391.1Skamil
56401.1Skamil	validate_status_stopped(status, SIGTRAP);
56411.1Skamil
56421.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
56431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
56441.1Skamil
56451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56461.1Skamil	    "without signal to be sent\n");
56471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
56481.1Skamil
56491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56511.1Skamil
56521.1Skamil	validate_status_stopped(status, SIGTRAP);
56531.1Skamil
56541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56551.1Skamil	    "without signal to be sent\n");
56561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56571.1Skamil
56581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56601.1Skamil
56611.1Skamil	validate_status_exited(status, exitval);
56621.1Skamil
56631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56651.1Skamil}
56661.1Skamil
56671.1Skamil#include "t_ptrace_amd64_wait.h"
56681.1Skamil#include "t_ptrace_i386_wait.h"
56691.1Skamil#include "t_ptrace_x86_wait.h"
56701.1Skamil
56711.1SkamilATF_TP_ADD_TCS(tp)
56721.1Skamil{
56731.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
56741.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
56751.33Skamil
56761.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
56771.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
56781.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
56791.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
56801.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
56811.33Skamil
56821.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
56831.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
56841.59Skamil//	ATF_TP_ADD_TC(tp, traceme_crash_ill);
56851.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
56861.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
56871.59Skamil
56881.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
56891.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
56901.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
56911.50Skamil
56921.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
56931.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
56941.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
56951.50Skamil
56961.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
56971.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
56981.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
56991.50Skamil
57001.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
57011.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
57021.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
57031.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
57041.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
57051.1Skamil
57061.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
57071.37Skamil
57081.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
57091.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
57101.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
57111.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
57121.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
57131.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
57141.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
57151.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
57161.40Skamil
57171.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
57181.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
57191.52Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
57201.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
57211.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
57221.41Skamil
57231.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
57241.43Skamil
57251.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
57261.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
57271.59Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
57281.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
57291.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
57301.59Skamil
57311.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
57321.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
57331.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
57341.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
57351.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
57361.51Skamil
57371.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
57381.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
57391.51Skamil
57401.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
57411.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
57421.51Skamil
57431.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57441.51Skamil		tracee_sees_its_original_parent_getppid);
57451.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57461.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
57471.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57481.51Skamil		tracee_sees_its_original_parent_procfs_status);
57491.1Skamil
57501.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
57511.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
57521.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
57531.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
57541.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
57551.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
57561.1Skamil
57571.31Skamil	ATF_TP_ADD_TC(tp, fork1);
57581.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
57591.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
57601.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
57611.31Skamil	ATF_TP_ADD_TC(tp, fork5);
57621.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
57631.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
57641.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
57651.31Skamil
57661.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
57671.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
57681.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
57691.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
57701.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
57711.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
57721.64Smartin// thes tests hang on SMP machines, disable them for now
57731.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
57741.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
57751.1Skamil
57761.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
57771.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
57781.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
57791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
57801.54Skamil
57811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
57821.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
57831.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
57841.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
57851.54Skamil
57861.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
57871.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
57881.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
57891.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
57901.54Skamil
57911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
57921.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
57931.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
57941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
57951.54Skamil
57961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
57971.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
57981.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
57991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
58001.54Skamil
58011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
58021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
58031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
58041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
58051.54Skamil
58061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
58071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
58081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
58091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
58101.54Skamil
58111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
58121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
58131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
58141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
58151.54Skamil
58161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
58171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
58181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
58191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
58201.54Skamil
58211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
58221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
58231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
58241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
58251.1Skamil
58261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
58271.1Skamil
58281.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
58291.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
58301.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
58311.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
58321.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
58331.1Skamil
58341.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
58351.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
58361.1Skamil
58371.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
58381.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
58391.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
58401.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
58411.1Skamil
58421.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
58431.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
58441.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
58451.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
58461.2Skamil
58471.1Skamil	ATF_TP_ADD_TC(tp, kill1);
58481.1Skamil	ATF_TP_ADD_TC(tp, kill2);
58491.1Skamil
58501.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
58511.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
58521.1Skamil
58531.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
58541.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
58551.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
58561.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
58571.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
58581.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
58591.1Skamil
58601.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
58611.1Skamil
58621.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
58631.1Skamil
58641.1Skamil	ATF_TP_ADD_TC(tp, signal1);
58651.1Skamil	ATF_TP_ADD_TC(tp, signal2);
58661.1Skamil	ATF_TP_ADD_TC(tp, signal3);
58671.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
58681.1Skamil	ATF_TP_ADD_TC(tp, signal5);
58691.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
58701.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
58711.1Skamil	ATF_TP_ADD_TC(tp, signal8);
58721.1Skamil	ATF_TP_ADD_TC(tp, signal9);
58731.1Skamil	ATF_TP_ADD_TC(tp, signal10);
58741.1Skamil
58751.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
58761.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
58771.1Skamil
58781.1Skamil	ATF_TP_ADD_TC(tp, resume1);
58791.1Skamil
58801.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
58811.1Skamil
58821.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
58831.1Skamil
58841.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
58851.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
58861.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
58871.1Skamil
58881.1Skamil	return atf_no_error();
58891.1Skamil}
5890