t_ptrace_wait.c revision 1.70
11.70Smrg/*	$NetBSD: t_ptrace_wait.c,v 1.70 2019/02/03 03:19:28 mrg 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.70Smrg__RCSID("$NetBSD: t_ptrace_wait.c,v 1.70 2019/02/03 03:19:28 mrg 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.70Smrg			__unreachable();
1171.36Skamil		default:
1181.36Skamil			DPRINTF("Before exiting of the child process\n");
1191.36Skamil			_exit(exitval);
1201.36Skamil		}
1211.1Skamil	}
1221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1231.1Skamil
1241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1261.1Skamil
1271.36Skamil	switch (sigval) {
1281.36Skamil	case SIGKILL:
1291.36Skamil		validate_status_signaled(status, sigval, 0);
1301.36Skamil		break;
1311.36Skamil	default:
1321.36Skamil		validate_status_stopped(status, sigval);
1331.1Skamil
1341.45Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1351.61Skre			"child\n");
1361.45Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1371.61Skre			sizeof(info)) != -1);
1381.45Skamil
1391.45Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1401.45Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1411.61Skre			"si_errno=%#x\n",
1421.61Skre			info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1431.61Skre			info.psi_siginfo.si_errno);
1441.45Skamil
1451.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1461.45Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1471.45Skamil
1481.36Skamil		DPRINTF("Before resuming the child process where it left off "
1491.36Skamil		    "and without signal to be sent\n");
1501.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1511.1Skamil
1521.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1531.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1541.61Skre		    child);
1551.36Skamil		break;
1561.36Skamil	}
1571.1Skamil
1581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1601.1Skamil}
1611.1Skamil
1621.61Skre#define TRACEME_RAISE(test, sig)					\
1631.61SkreATF_TC(test);								\
1641.61SkreATF_TC_HEAD(test, tc)							\
1651.61Skre{									\
1661.61Skre	atf_tc_set_md_var(tc, "descr",					\
1671.61Skre	    "Verify " #sig " followed by _exit(2) in a child");		\
1681.61Skre}									\
1691.61Skre									\
1701.61SkreATF_TC_BODY(test, tc)							\
1711.61Skre{									\
1721.61Skre									\
1731.61Skre	traceme_raise(sig);						\
1741.33Skamil}
1751.33Skamil
1761.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1771.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1781.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1791.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1801.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1811.33Skamil
1821.34Skamil/// ----------------------------------------------------------------------------
1831.1Skamil
1841.1Skamilstatic void
1851.59Skamiltraceme_crash(int sig)
1861.59Skamil{
1871.59Skamil	pid_t child, wpid;
1881.59Skamil#if defined(TWAIT_HAVE_STATUS)
1891.59Skamil	int status;
1901.59Skamil#endif
1911.59Skamil	struct ptrace_siginfo info;
1921.61Skre
1931.59Skamil	memset(&info, 0, sizeof(info));
1941.59Skamil
1951.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
1961.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
1971.59Skamil	if (child == 0) {
1981.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1991.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2001.59Skamil
2011.59Skamil		DPRINTF("Before executing a trap\n");
2021.59Skamil		switch (sig) {
2031.59Skamil		case SIGTRAP:
2041.59Skamil			trigger_trap();
2051.59Skamil			break;
2061.59Skamil		case SIGSEGV:
2071.59Skamil			trigger_segv();
2081.59Skamil			break;
2091.59Skamil		case SIGILL:
2101.59Skamil			trigger_ill();
2111.59Skamil			break;
2121.59Skamil		case SIGFPE:
2131.59Skamil			trigger_fpe();
2141.59Skamil			break;
2151.59Skamil		case SIGBUS:
2161.59Skamil			trigger_bus();
2171.59Skamil			break;
2181.59Skamil		default:
2191.59Skamil			/* NOTREACHED */
2201.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2211.59Skamil		}
2221.59Skamil
2231.59Skamil		/* NOTREACHED */
2241.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
2251.59Skamil	}
2261.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2271.59Skamil
2281.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2291.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2301.59Skamil
2311.59Skamil	validate_status_stopped(status, sig);
2321.59Skamil
2331.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
2341.61Skre	SYSCALL_REQUIRE(
2351.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2361.59Skamil
2371.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2381.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2391.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2401.61Skre	    info.psi_siginfo.si_errno);
2411.59Skamil
2421.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
2431.59Skamil	switch (sig) {
2441.59Skamil	case SIGTRAP:
2451.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
2461.59Skamil		break;
2471.59Skamil	case SIGSEGV:
2481.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
2491.59Skamil		break;
2501.59Skamil//	case SIGILL:
2511.59Skamil//		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_ILLOP);
2521.59Skamil//		break;
2531.59Skamil	case SIGFPE:
2541.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
2551.59Skamil		break;
2561.59Skamil	case SIGBUS:
2571.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
2581.59Skamil		break;
2591.59Skamil	}
2601.59Skamil
2611.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
2621.59Skamil
2631.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2641.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2651.59Skamil
2661.59Skamil	validate_status_signaled(status, SIGKILL, 0);
2671.59Skamil
2681.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2691.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2701.59Skamil}
2711.59Skamil
2721.61Skre#define TRACEME_CRASH(test, sig)					\
2731.61SkreATF_TC(test);								\
2741.61SkreATF_TC_HEAD(test, tc)							\
2751.61Skre{									\
2761.61Skre	atf_tc_set_md_var(tc, "descr",					\
2771.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
2781.61Skre}									\
2791.61Skre									\
2801.61SkreATF_TC_BODY(test, tc)							\
2811.61Skre{									\
2821.61Skre									\
2831.61Skre	traceme_crash(sig);						\
2841.59Skamil}
2851.59Skamil
2861.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
2871.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
2881.59Skamil//TRACEME_CRASH(traceme_crash_ill, SIGILL)
2891.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
2901.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
2911.59Skamil
2921.59Skamil/// ----------------------------------------------------------------------------
2931.59Skamil
2941.59Skamilstatic void
2951.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
2961.1Skamil{
2971.1Skamil	const int exitval = 5;
2981.34Skamil	const int sigval = SIGSTOP;
2991.1Skamil	pid_t child, wpid;
3001.1Skamil	struct sigaction sa;
3011.1Skamil#if defined(TWAIT_HAVE_STATUS)
3021.1Skamil	int status;
3031.1Skamil#endif
3041.61Skre	struct ptrace_siginfo info;
3051.1Skamil
3061.45Skamil	memset(&info, 0, sizeof(info));
3071.45Skamil
3081.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
3091.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
3101.1Skamil	if (child == 0) {
3111.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3121.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3131.1Skamil
3141.34Skamil		sa.sa_handler = sah;
3151.1Skamil		sa.sa_flags = SA_SIGINFO;
3161.1Skamil		sigemptyset(&sa.sa_mask);
3171.1Skamil
3181.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
3191.1Skamil
3201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3221.1Skamil
3231.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
3241.1Skamil
3251.13Schristos		DPRINTF("Before exiting of the child process\n");
3261.1Skamil		_exit(exitval);
3271.1Skamil	}
3281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3291.1Skamil
3301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3321.1Skamil
3331.1Skamil	validate_status_stopped(status, sigval);
3341.1Skamil
3351.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3361.61Skre	SYSCALL_REQUIRE(
3371.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3381.45Skamil
3391.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3401.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3411.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3421.45Skamil	    info.psi_siginfo.si_errno);
3431.45Skamil
3441.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3451.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3461.45Skamil
3471.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
3481.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3501.1Skamil
3511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3531.1Skamil
3541.1Skamil	validate_status_exited(status, exitval);
3551.1Skamil
3561.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3581.1Skamil}
3591.1Skamil
3601.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
3611.61SkreATF_TC(test);								\
3621.61SkreATF_TC_HEAD(test, tc)							\
3631.61Skre{									\
3641.61Skre	atf_tc_set_md_var(tc, "descr",					\
3651.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
3661.61Skre	    "handled correctly and caught by a signal handler");	\
3671.61Skre}									\
3681.61Skre									\
3691.61Skrestatic int test##_caught = 0;						\
3701.61Skre									\
3711.61Skrestatic void								\
3721.61Skretest##_sighandler(int arg)						\
3731.61Skre{									\
3741.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
3751.61Skre									\
3761.61Skre	++ test##_caught;						\
3771.61Skre}									\
3781.61Skre									\
3791.61SkreATF_TC_BODY(test, tc)							\
3801.61Skre{									\
3811.61Skre									\
3821.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
3831.34Skamil}
3841.34Skamil
3851.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
3861.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
3871.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
3881.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
3891.34Skamil
3901.34Skamil/// ----------------------------------------------------------------------------
3911.34Skamil
3921.35Skamilstatic void
3931.50Skamiltraceme_sendsignal_masked(int sigsent)
3941.50Skamil{
3951.50Skamil	const int exitval = 5;
3961.50Skamil	const int sigval = SIGSTOP;
3971.50Skamil	pid_t child, wpid;
3981.50Skamil	sigset_t set;
3991.50Skamil#if defined(TWAIT_HAVE_STATUS)
4001.50Skamil	int status;
4011.50Skamil#endif
4021.61Skre	struct ptrace_siginfo info;
4031.50Skamil
4041.50Skamil	memset(&info, 0, sizeof(info));
4051.50Skamil
4061.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4071.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4081.50Skamil	if (child == 0) {
4091.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4101.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4111.50Skamil
4121.50Skamil		sigemptyset(&set);
4131.50Skamil		sigaddset(&set, sigsent);
4141.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
4151.50Skamil
4161.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4171.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4181.50Skamil
4191.50Skamil		_exit(exitval);
4201.50Skamil	}
4211.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4221.50Skamil
4231.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4241.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4251.50Skamil
4261.50Skamil	validate_status_stopped(status, sigval);
4271.50Skamil
4281.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4291.61Skre	SYSCALL_REQUIRE(
4301.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4311.50Skamil
4321.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4331.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4341.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4351.50Skamil	    info.psi_siginfo.si_errno);
4361.50Skamil
4371.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4381.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4391.50Skamil
4401.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
4411.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4421.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4431.50Skamil
4441.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4451.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4461.50Skamil
4471.50Skamil	validate_status_exited(status, exitval);
4481.50Skamil
4491.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4501.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4511.50Skamil}
4521.50Skamil
4531.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
4541.61SkreATF_TC(test);								\
4551.61SkreATF_TC_HEAD(test, tc)							\
4561.61Skre{									\
4571.61Skre	atf_tc_set_md_var(tc, "descr",					\
4581.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
4591.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
4601.61Skre}									\
4611.61Skre									\
4621.61SkreATF_TC_BODY(test, tc)							\
4631.61Skre{									\
4641.61Skre									\
4651.61Skre	traceme_sendsignal_masked(sig);					\
4661.50Skamil}
4671.50Skamil
4681.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4691.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
4701.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
4711.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
4721.50Skamil
4731.50Skamil/// ----------------------------------------------------------------------------
4741.50Skamil
4751.50Skamilstatic void
4761.50Skamiltraceme_sendsignal_ignored(int sigsent)
4771.50Skamil{
4781.50Skamil	const int exitval = 5;
4791.50Skamil	const int sigval = SIGSTOP;
4801.50Skamil	pid_t child, wpid;
4811.50Skamil	struct sigaction sa;
4821.50Skamil#if defined(TWAIT_HAVE_STATUS)
4831.50Skamil	int status;
4841.50Skamil#endif
4851.61Skre	struct ptrace_siginfo info;
4861.50Skamil
4871.50Skamil	memset(&info, 0, sizeof(info));
4881.50Skamil
4891.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4901.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4911.50Skamil	if (child == 0) {
4921.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4931.61Skre
4941.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4951.50Skamil
4961.50Skamil		memset(&sa, 0, sizeof(sa));
4971.50Skamil		sa.sa_handler = SIG_IGN;
4981.50Skamil		sigemptyset(&sa.sa_mask);
4991.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
5001.50Skamil
5011.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5021.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5031.50Skamil
5041.50Skamil		_exit(exitval);
5051.50Skamil	}
5061.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5071.50Skamil
5081.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5091.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5101.50Skamil
5111.50Skamil	validate_status_stopped(status, sigval);
5121.50Skamil
5131.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5141.61Skre	SYSCALL_REQUIRE(
5151.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5161.50Skamil
5171.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5181.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5191.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5201.50Skamil	    info.psi_siginfo.si_errno);
5211.50Skamil
5221.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5231.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5241.50Skamil
5251.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
5261.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
5271.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5281.50Skamil
5291.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5301.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5311.50Skamil
5321.50Skamil	validate_status_exited(status, exitval);
5331.50Skamil
5341.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5351.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5361.50Skamil}
5371.50Skamil
5381.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
5391.61SkreATF_TC(test);								\
5401.61SkreATF_TC_HEAD(test, tc)							\
5411.61Skre{									\
5421.61Skre	atf_tc_set_md_var(tc, "descr",					\
5431.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
5441.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
5451.61Skre}									\
5461.61Skre									\
5471.61SkreATF_TC_BODY(test, tc)							\
5481.61Skre{									\
5491.61Skre									\
5501.61Skre	traceme_sendsignal_ignored(sig);				\
5511.50Skamil}
5521.50Skamil
5531.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
5541.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
5551.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
5561.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
5571.50Skamil
5581.50Skamil/// ----------------------------------------------------------------------------
5591.50Skamil
5601.50Skamilstatic void
5611.50Skamiltraceme_sendsignal_simple(int sigsent)
5621.1Skamil{
5631.35Skamil	const int sigval = SIGSTOP;
5641.35Skamil	int exitval = 0;
5651.1Skamil	pid_t child, wpid;
5661.1Skamil#if defined(TWAIT_HAVE_STATUS)
5671.1Skamil	int status;
5681.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
5691.1Skamil#endif
5701.61Skre	struct ptrace_siginfo info;
5711.1Skamil
5721.45Skamil	memset(&info, 0, sizeof(info));
5731.45Skamil
5741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
5751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
5761.1Skamil	if (child == 0) {
5771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5791.1Skamil
5801.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5811.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5821.1Skamil
5831.35Skamil		switch (sigsent) {
5841.35Skamil		case SIGCONT:
5851.48Skamil		case SIGSTOP:
5861.35Skamil			_exit(exitval);
5871.35Skamil		default:
5881.35Skamil			/* NOTREACHED */
5891.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5901.35Skamil		}
5911.1Skamil	}
5921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5931.1Skamil
5941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5961.1Skamil
5971.1Skamil	validate_status_stopped(status, sigval);
5981.1Skamil
5991.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6001.61Skre	SYSCALL_REQUIRE(
6011.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6021.45Skamil
6031.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6041.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6051.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6061.45Skamil	    info.psi_siginfo.si_errno);
6071.45Skamil
6081.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6091.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6101.45Skamil
6111.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
6121.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
6131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6141.1Skamil
6151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6171.1Skamil
6181.35Skamil	switch (sigsent) {
6191.48Skamil	case SIGSTOP:
6201.48Skamil		validate_status_stopped(status, sigsent);
6211.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
6221.61Skre		    "child\n");
6231.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
6241.61Skre		    sizeof(info)) != -1);
6251.48Skamil
6261.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6271.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
6281.61Skre		    "si_errno=%#x\n",
6291.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6301.61Skre		    info.psi_siginfo.si_errno);
6311.48Skamil
6321.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6331.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6341.48Skamil
6351.48Skamil		DPRINTF("Before resuming the child process where it left off "
6361.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
6371.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6381.48Skamil
6391.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6401.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
6411.61Skre		    child);
6421.48Skamil		/* FALLTHROUGH */
6431.35Skamil	case SIGCONT:
6441.35Skamil		validate_status_exited(status, exitval);
6451.35Skamil		break;
6461.35Skamil	default:
6471.35Skamil		validate_status_signaled(status, sigsent, expect_core);
6481.35Skamil		break;
6491.35Skamil	}
6501.1Skamil
6511.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6531.1Skamil}
6541.1Skamil
6551.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
6561.61SkreATF_TC(test);								\
6571.61SkreATF_TC_HEAD(test, tc)							\
6581.61Skre{									\
6591.61Skre	atf_tc_set_md_var(tc, "descr",					\
6601.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
6611.61Skre	    "handled correctly in a child without a signal handler");	\
6621.61Skre}									\
6631.61Skre									\
6641.61SkreATF_TC_BODY(test, tc)							\
6651.61Skre{									\
6661.61Skre									\
6671.61Skre	traceme_sendsignal_simple(sig);					\
6681.35Skamil}
6691.35Skamil
6701.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
6711.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
6721.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
6731.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
6741.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
6751.35Skamil
6761.35Skamil/// ----------------------------------------------------------------------------
6771.35Skamil
6781.37SkamilATF_TC(traceme_pid1_parent);
6791.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
6801.37Skamil{
6811.37Skamil	atf_tc_set_md_var(tc, "descr",
6821.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
6831.37Skamil}
6841.37Skamil
6851.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
6861.37Skamil{
6871.37Skamil	struct msg_fds parent_child;
6881.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
6891.37Skamil	pid_t child1, child2, wpid;
6901.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6911.37Skamil#if defined(TWAIT_HAVE_STATUS)
6921.37Skamil	int status;
6931.37Skamil#endif
6941.37Skamil
6951.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
6961.37Skamil
6971.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
6981.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
6991.37Skamil	if (child1 == 0) {
7001.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
7011.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
7021.37Skamil		if (child2 != 0) {
7031.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
7041.61Skre			    getpid(), child2);
7051.37Skamil			_exit(exitval_child1);
7061.37Skamil		}
7071.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
7081.37Skamil
7091.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
7101.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
7111.37Skamil
7121.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7131.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
7141.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
7151.37Skamil
7161.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
7171.37Skamil
7181.37Skamil		_exit(exitval_child2);
7191.37Skamil	}
7201.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
7211.37Skamil
7221.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7231.61Skre	TWAIT_REQUIRE_SUCCESS(
7241.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
7251.37Skamil
7261.37Skamil	validate_status_exited(status, exitval_child1);
7271.37Skamil
7281.37Skamil	DPRINTF("Notify that child1 is dead\n");
7291.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
7301.37Skamil
7311.37Skamil	DPRINTF("Wait for exiting of child2\n");
7321.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
7331.37Skamil}
7341.37Skamil
7351.37Skamil/// ----------------------------------------------------------------------------
7361.37Skamil
7371.40Skamilstatic void
7381.40Skamiltraceme_vfork_raise(int sigval)
7391.40Skamil{
7401.46Skamil	const int exitval = 5, exitval_watcher = 10;
7411.46Skamil	pid_t child, parent, watcher, wpid;
7421.46Skamil	int rv;
7431.40Skamil#if defined(TWAIT_HAVE_STATUS)
7441.40Skamil	int status;
7451.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
7461.40Skamil#endif
7471.40Skamil
7481.46Skamil	/*
7491.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
7501.46Skamil	 * the SIGKILL signal to it.
7511.46Skamil	 *
7521.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
7531.46Skamil	 * simpler to reparent this process to initproc and forget about it.
7541.46Skamil	 */
7551.46Skamil	if (sigval == SIGSTOP) {
7561.46Skamil		parent = getpid();
7571.46Skamil
7581.46Skamil		watcher = fork();
7591.46Skamil		ATF_REQUIRE(watcher != 1);
7601.46Skamil		if (watcher == 0) {
7611.46Skamil			/* Double fork(2) trick to reparent to initproc */
7621.46Skamil			watcher = fork();
7631.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
7641.46Skamil			if (watcher != 0)
7651.46Skamil				_exit(exitval_watcher);
7661.46Skamil
7671.46Skamil			child = await_stopped_child(parent);
7681.46Skamil
7691.46Skamil			errno = 0;
7701.46Skamil			rv = kill(child, SIGKILL);
7711.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
7721.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
7731.46Skamil
7741.46Skamil			/* This exit value will be collected by initproc */
7751.46Skamil			_exit(0);
7761.46Skamil		}
7771.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7781.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
7791.61Skre		    watcher);
7801.46Skamil
7811.46Skamil		validate_status_exited(status, exitval_watcher);
7821.46Skamil
7831.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7841.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
7851.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
7861.46Skamil	}
7871.46Skamil
7881.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7891.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
7901.40Skamil	if (child == 0) {
7911.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7921.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7931.40Skamil
7941.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7951.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7961.40Skamil
7971.40Skamil		switch (sigval) {
7981.46Skamil		case SIGSTOP:
7991.40Skamil		case SIGKILL:
8001.40Skamil		case SIGABRT:
8011.40Skamil		case SIGHUP:
8021.40Skamil			/* NOTREACHED */
8031.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
8041.70Smrg			__unreachable();
8051.40Skamil		default:
8061.40Skamil			DPRINTF("Before exiting of the child process\n");
8071.40Skamil			_exit(exitval);
8081.40Skamil		}
8091.40Skamil	}
8101.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8111.40Skamil
8121.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8131.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8141.40Skamil
8151.40Skamil	switch (sigval) {
8161.40Skamil	case SIGKILL:
8171.40Skamil	case SIGABRT:
8181.40Skamil	case SIGHUP:
8191.40Skamil		validate_status_signaled(status, sigval, expect_core);
8201.40Skamil		break;
8211.40Skamil	case SIGSTOP:
8221.46Skamil		validate_status_signaled(status, SIGKILL, 0);
8231.46Skamil		break;
8241.40Skamil	case SIGCONT:
8251.47Skamil	case SIGTSTP:
8261.47Skamil	case SIGTTIN:
8271.47Skamil	case SIGTTOU:
8281.40Skamil		validate_status_exited(status, exitval);
8291.40Skamil		break;
8301.40Skamil	default:
8311.40Skamil		/* NOTREACHED */
8321.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
8331.40Skamil		break;
8341.40Skamil	}
8351.40Skamil
8361.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8371.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8381.40Skamil}
8391.40Skamil
8401.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
8411.61SkreATF_TC(test);								\
8421.61SkreATF_TC_HEAD(test, tc)							\
8431.61Skre{									\
8441.61Skre	atf_tc_set_md_var(tc, "descr",					\
8451.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
8461.61Skre	    "vfork(2)ed child");					\
8471.61Skre}									\
8481.61Skre									\
8491.61SkreATF_TC_BODY(test, tc)							\
8501.61Skre{									\
8511.61Skre									\
8521.61Skre	traceme_vfork_raise(sig);					\
8531.40Skamil}
8541.40Skamil
8551.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
8561.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
8571.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
8581.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
8591.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
8601.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
8611.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
8621.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
8631.40Skamil
8641.40Skamil/// ----------------------------------------------------------------------------
8651.40Skamil
8661.52Skamilstatic void
8671.52Skamiltraceme_vfork_crash(int sig)
8681.41Skamil{
8691.41Skamil	pid_t child, wpid;
8701.41Skamil#if defined(TWAIT_HAVE_STATUS)
8711.41Skamil	int status;
8721.41Skamil#endif
8731.41Skamil
8741.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8751.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
8761.41Skamil	if (child == 0) {
8771.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8781.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8791.41Skamil
8801.52Skamil		DPRINTF("Before executing a trap\n");
8811.52Skamil		switch (sig) {
8821.52Skamil		case SIGTRAP:
8831.52Skamil			trigger_trap();
8841.52Skamil			break;
8851.52Skamil		case SIGSEGV:
8861.52Skamil			trigger_segv();
8871.52Skamil			break;
8881.52Skamil		case SIGILL:
8891.52Skamil			trigger_ill();
8901.52Skamil			break;
8911.52Skamil		case SIGFPE:
8921.52Skamil			trigger_fpe();
8931.52Skamil			break;
8941.52Skamil		case SIGBUS:
8951.52Skamil			trigger_bus();
8961.52Skamil			break;
8971.52Skamil		default:
8981.52Skamil			/* NOTREACHED */
8991.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
9001.52Skamil		}
9011.41Skamil
9021.41Skamil		/* NOTREACHED */
9031.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
9041.41Skamil	}
9051.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9061.41Skamil
9071.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9081.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9091.41Skamil
9101.52Skamil	validate_status_signaled(status, sig, 1);
9111.41Skamil
9121.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9131.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9141.41Skamil}
9151.41Skamil
9161.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
9171.61SkreATF_TC(test);								\
9181.61SkreATF_TC_HEAD(test, tc)							\
9191.61Skre{									\
9201.61Skre	atf_tc_set_md_var(tc, "descr",					\
9211.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
9221.61Skre	    "vfork(2)ed child");					\
9231.61Skre}									\
9241.61Skre									\
9251.61SkreATF_TC_BODY(test, tc)							\
9261.61Skre{									\
9271.61Skre									\
9281.61Skre	traceme_vfork_crash(sig);					\
9291.52Skamil}
9301.52Skamil
9311.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
9321.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
9331.52Skamil//TRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
9341.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
9351.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
9361.52Skamil
9371.41Skamil/// ----------------------------------------------------------------------------
9381.41Skamil
9391.43SkamilATF_TC(traceme_vfork_exec);
9401.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
9411.43Skamil{
9421.43Skamil	atf_tc_set_md_var(tc, "descr",
9431.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
9441.43Skamil}
9451.43Skamil
9461.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
9471.43Skamil{
9481.43Skamil	const int sigval = SIGTRAP;
9491.43Skamil	pid_t child, wpid;
9501.43Skamil#if defined(TWAIT_HAVE_STATUS)
9511.43Skamil	int status;
9521.43Skamil#endif
9531.61Skre	struct ptrace_siginfo info;
9541.43Skamil
9551.43Skamil	memset(&info, 0, sizeof(info));
9561.43Skamil
9571.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9581.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
9591.43Skamil	if (child == 0) {
9601.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9611.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9621.43Skamil
9631.43Skamil		DPRINTF("Before calling execve(2) from child\n");
9641.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
9651.43Skamil
9661.43Skamil		/* NOTREACHED */
9671.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
9681.43Skamil	}
9691.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9701.43Skamil
9711.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9721.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9731.43Skamil
9741.43Skamil	validate_status_stopped(status, sigval);
9751.43Skamil
9761.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9771.61Skre	SYSCALL_REQUIRE(
9781.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9791.43Skamil
9801.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9811.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9821.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9831.43Skamil	    info.psi_siginfo.si_errno);
9841.43Skamil
9851.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9861.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
9871.43Skamil
9881.43Skamil	DPRINTF("Before resuming the child process where it left off and "
9891.43Skamil	    "without signal to be sent\n");
9901.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
9911.43Skamil
9921.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9931.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9941.43Skamil
9951.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9961.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9971.43Skamil}
9981.43Skamil
9991.43Skamil/// ----------------------------------------------------------------------------
10001.43Skamil
10011.1Skamil#if defined(TWAIT_HAVE_PID)
10021.51Skamilstatic void
10031.59Skamilunrelated_tracer_sees_crash(int sig)
10041.59Skamil{
10051.59Skamil	struct msg_fds parent_tracee, parent_tracer;
10061.59Skamil	const int exitval = 10;
10071.59Skamil	pid_t tracee, tracer, wpid;
10081.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10091.59Skamil#if defined(TWAIT_HAVE_STATUS)
10101.59Skamil	int status;
10111.59Skamil#endif
10121.59Skamil	struct ptrace_siginfo info;
10131.61Skre
10141.59Skamil	memset(&info, 0, sizeof(info));
10151.59Skamil
10161.59Skamil	DPRINTF("Spawn tracee\n");
10171.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10181.59Skamil	tracee = atf_utils_fork();
10191.59Skamil	if (tracee == 0) {
10201.59Skamil		// Wait for parent to let us crash
10211.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
10221.61Skre
10231.59Skamil		DPRINTF("Before executing a trap\n");
10241.59Skamil		switch (sig) {
10251.59Skamil		case SIGTRAP:
10261.59Skamil			trigger_trap();
10271.59Skamil			break;
10281.59Skamil		case SIGSEGV:
10291.59Skamil			trigger_segv();
10301.59Skamil			break;
10311.59Skamil		case SIGILL:
10321.59Skamil			trigger_ill();
10331.59Skamil			break;
10341.59Skamil		case SIGFPE:
10351.59Skamil			trigger_fpe();
10361.59Skamil			break;
10371.59Skamil		case SIGBUS:
10381.59Skamil			trigger_bus();
10391.59Skamil			break;
10401.59Skamil		default:
10411.59Skamil			/* NOTREACHED */
10421.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
10431.59Skamil		}
10441.59Skamil
10451.59Skamil		/* NOTREACHED */
10461.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
10471.59Skamil	}
10481.59Skamil
10491.59Skamil	DPRINTF("Spawn debugger\n");
10501.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10511.59Skamil	tracer = atf_utils_fork();
10521.59Skamil	if (tracer == 0) {
10531.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
10541.59Skamil		tracer = atf_utils_fork();
10551.59Skamil		if (tracer != 0)
10561.61Skre			_exit(exitval);
10571.59Skamil
10581.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10591.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10601.59Skamil
10611.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10621.59Skamil		FORKEE_REQUIRE_SUCCESS(
10631.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10641.59Skamil
10651.59Skamil		forkee_status_stopped(status, SIGSTOP);
10661.59Skamil
10671.59Skamil		/* Resume tracee with PT_CONTINUE */
10681.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10691.59Skamil
10701.59Skamil		/* Inform parent that tracer has attached to tracee */
10711.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
10721.59Skamil
10731.59Skamil		/* Wait for parent to tell use that tracee should have exited */
10741.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
10751.59Skamil
10761.59Skamil		/* Wait for tracee and assert that it exited */
10771.59Skamil		FORKEE_REQUIRE_SUCCESS(
10781.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10791.59Skamil
10801.59Skamil		validate_status_stopped(status, sig);
10811.59Skamil
10821.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
10831.61Skre		    "traced process\n");
10841.61Skre		SYSCALL_REQUIRE(
10851.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
10861.59Skamil
10871.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
10881.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
10891.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
10901.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
10911.59Skamil
10921.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
10931.59Skamil		switch (sig) {
10941.59Skamil		case SIGTRAP:
10951.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
10961.59Skamil			break;
10971.59Skamil		case SIGSEGV:
10981.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
10991.59Skamil			break;
11001.59Skamil//		case SIGILL:
11011.59Skamil//			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_ILLOP);
11021.59Skamil//			break;
11031.59Skamil		case SIGFPE:
11041.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
11051.59Skamil			break;
11061.59Skamil		case SIGBUS:
11071.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
11081.59Skamil			break;
11091.59Skamil		}
11101.59Skamil
11111.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
11121.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
11131.61Skre		TWAIT_REQUIRE_SUCCESS(
11141.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11151.59Skamil
11161.59Skamil		validate_status_signaled(status, SIGKILL, 0);
11171.59Skamil
11181.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
11191.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
11201.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
11211.59Skamil
11221.59Skamil		DPRINTF("Before exiting of the tracer process\n");
11231.59Skamil		_exit(0 /* collect by initproc */);
11241.59Skamil	}
11251.59Skamil
11261.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
11271.59Skamil	    "calling %s()\n", TWAIT_FNAME);
11281.59Skamil	TWAIT_REQUIRE_SUCCESS(
11291.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
11301.59Skamil
11311.59Skamil	validate_status_exited(status, exitval);
11321.59Skamil
11331.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
11341.59Skamil	    TWAIT_FNAME);
11351.59Skamil	TWAIT_REQUIRE_SUCCESS(
11361.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
11371.59Skamil
11381.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
11391.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
11401.59Skamil
11411.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
11421.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
11431.59Skamil
11441.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
11451.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11461.59Skamil
11471.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11481.59Skamil	    TWAIT_FNAME);
11491.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11501.59Skamil
11511.59Skamil	validate_status_signaled(status, SIGKILL, 0);
11521.59Skamil
11531.59Skamil	msg_close(&parent_tracer);
11541.59Skamil	msg_close(&parent_tracee);
11551.59Skamil}
11561.59Skamil
11571.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
11581.61SkreATF_TC(test);								\
11591.61SkreATF_TC_HEAD(test, tc)							\
11601.61Skre{									\
11611.61Skre	atf_tc_set_md_var(tc, "descr",					\
11621.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
11631.61Skre	    "debuggee");						\
11641.61Skre}									\
11651.61Skre									\
11661.61SkreATF_TC_BODY(test, tc)							\
11671.61Skre{									\
11681.61Skre									\
11691.61Skre	unrelated_tracer_sees_crash(sig);				\
11701.59Skamil}
11711.59Skamil
11721.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
11731.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
11741.59Skamil//UNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
11751.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
11761.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
11771.59Skamil#endif
11781.59Skamil
11791.59Skamil/// ----------------------------------------------------------------------------
11801.59Skamil
11811.59Skamil#if defined(TWAIT_HAVE_PID)
11821.59Skamilstatic void
11831.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
11841.67Skamil                                             bool stopped)
11851.1Skamil{
11861.51Skamil	/*
11871.51Skamil	 * notimeout - disable timeout in await zombie function
11881.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
11891.67Skamil	 * stopped - attach to a stopped process
11901.51Skamil	 */
11911.1Skamil
11921.1Skamil	struct msg_fds parent_tracee, parent_tracer;
11931.1Skamil	const int exitval_tracee = 5;
11941.1Skamil	const int exitval_tracer = 10;
11951.1Skamil	pid_t tracee, tracer, wpid;
11961.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
11971.1Skamil#if defined(TWAIT_HAVE_STATUS)
11981.1Skamil	int status;
11991.1Skamil#endif
12001.1Skamil
12011.67Skamil	/*
12021.67Skamil	 * Only a subset of options are supported.
12031.67Skamil	 */
12041.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
12051.67Skamil	            (!notimeout && unrelated && !stopped) ||
12061.67Skamil	            (notimeout && !unrelated && !stopped) ||
12071.67Skamil	            (!notimeout && unrelated && stopped));
12081.67Skamil
12091.13Schristos	DPRINTF("Spawn tracee\n");
12101.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
12111.1Skamil	tracee = atf_utils_fork();
12121.1Skamil	if (tracee == 0) {
12131.67Skamil		if (stopped) {
12141.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
12151.67Skamil			raise(SIGSTOP);
12161.67Skamil		}
12171.67Skamil
12181.1Skamil		// Wait for parent to let us exit
12191.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
12201.1Skamil		_exit(exitval_tracee);
12211.1Skamil	}
12221.1Skamil
12231.13Schristos	DPRINTF("Spawn debugger\n");
12241.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
12251.1Skamil	tracer = atf_utils_fork();
12261.1Skamil	if (tracer == 0) {
12271.51Skamil		if(unrelated) {
12281.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
12291.51Skamil			tracer = atf_utils_fork();
12301.51Skamil			if (tracer != 0)
12311.51Skamil				_exit(exitval_tracer);
12321.51Skamil		}
12331.51Skamil
12341.67Skamil		if (stopped) {
12351.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
12361.67Skamil			await_stopped(tracee);
12371.67Skamil		}
12381.67Skamil
12391.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12401.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12411.1Skamil
12421.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12431.1Skamil		FORKEE_REQUIRE_SUCCESS(
12441.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12451.1Skamil
12461.1Skamil		forkee_status_stopped(status, SIGSTOP);
12471.1Skamil
12481.1Skamil		/* Resume tracee with PT_CONTINUE */
12491.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
12501.1Skamil
12511.1Skamil		/* Inform parent that tracer has attached to tracee */
12521.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12531.1Skamil
12541.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12551.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12561.1Skamil
12571.1Skamil		/* Wait for tracee and assert that it exited */
12581.1Skamil		FORKEE_REQUIRE_SUCCESS(
12591.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12601.1Skamil
12611.1Skamil		forkee_status_exited(status, exitval_tracee);
12621.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
12631.1Skamil
12641.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12651.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
12661.51Skamil	}
12671.51Skamil
12681.51Skamil	if (unrelated) {
12691.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
12701.51Skamil		    "calling %s()\n", TWAIT_FNAME);
12711.51Skamil		TWAIT_REQUIRE_SUCCESS(
12721.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
12731.51Skamil
12741.51Skamil		validate_status_exited(status, exitval_tracer);
12751.51Skamil
12761.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
12771.51Skamil		    TWAIT_FNAME);
12781.51Skamil		TWAIT_REQUIRE_SUCCESS(
12791.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
12801.1Skamil	}
12811.1Skamil
12821.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
12831.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
12841.1Skamil
12851.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
12861.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
12871.1Skamil
12881.13Schristos	DPRINTF("Detect that tracee is zombie\n");
12891.51Skamil	if (notimeout)
12901.26Skamil		await_zombie_raw(tracee, 0);
12911.26Skamil	else
12921.26Skamil		await_zombie(tracee);
12931.1Skamil
12941.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
12951.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
12961.1Skamil	    TWAIT_FNAME);
12971.1Skamil	TWAIT_REQUIRE_SUCCESS(
12981.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
12991.1Skamil
13001.51Skamil	if (unrelated) {
13011.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
13021.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
13031.51Skamil	} else {
13041.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
13051.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
13061.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
13071.59Skamil			"%s()\n", TWAIT_FNAME);
13081.51Skamil
13091.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
13101.59Skamil			"tracee\n");
13111.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
13121.51Skamil		    tracer);
13131.1Skamil
13141.51Skamil		validate_status_exited(status, exitval_tracer);
13151.51Skamil	}
13161.1Skamil
13171.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
13181.1Skamil	    TWAIT_FNAME);
13191.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13201.1Skamil
13211.1Skamil	validate_status_exited(status, exitval_tracee);
13221.1Skamil
13231.1Skamil	msg_close(&parent_tracer);
13241.1Skamil	msg_close(&parent_tracee);
13251.1Skamil}
13261.26Skamil
13271.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
13281.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
13291.51Skamil{
13301.51Skamil	atf_tc_set_md_var(tc, "descr",
13311.51Skamil	    "Assert that tracer sees process termination before the parent");
13321.51Skamil}
13331.51Skamil
13341.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
13351.26Skamil{
13361.26Skamil
13371.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
13381.26Skamil}
13391.26Skamil
13401.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
13411.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
13421.1Skamil{
13431.1Skamil	atf_tc_set_md_var(tc, "descr",
13441.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
13451.51Skamil	    "process and no other error is reported");
13461.1Skamil}
13471.1Skamil
13481.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
13491.1Skamil{
13501.51Skamil	time_t start, end;
13511.51Skamil	double diff;
13521.51Skamil	unsigned long N = 0;
13531.1Skamil
13541.51Skamil	/*
13551.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
13561.51Skamil	 * This test body isn't specific to this race, however it's just good
13571.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
13581.51Skamil	 */
13591.1Skamil
13601.51Skamil	start = time(NULL);
13611.51Skamil	while (true) {
13621.51Skamil		DPRINTF("Step: %lu\n", N);
13631.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
13641.67Skamil		                                             false);
13651.51Skamil		end = time(NULL);
13661.51Skamil		diff = difftime(end, start);
13671.51Skamil		if (diff >= 5.0)
13681.51Skamil			break;
13691.51Skamil		++N;
13701.1Skamil	}
13711.51Skamil	DPRINTF("Iterations: %lu\n", N);
13721.51Skamil}
13731.1Skamil
13741.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
13751.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13761.51Skamil{
13771.51Skamil	atf_tc_set_md_var(tc, "descr",
13781.51Skamil	    "Assert that tracer sees process termination before the parent");
13791.51Skamil}
13801.1Skamil
13811.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13821.51Skamil{
13831.1Skamil
13841.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
13851.67Skamil}
13861.67Skamil
13871.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
13881.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
13891.67Skamil{
13901.67Skamil	atf_tc_set_md_var(tc, "descr",
13911.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
13921.67Skamil}
13931.67Skamil
13941.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
13951.67Skamil{
13961.67Skamil
13971.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
13981.1Skamil}
13991.1Skamil#endif
14001.1Skamil
14011.51Skamil/// ----------------------------------------------------------------------------
14021.51Skamil
14031.66Skamilstatic void
14041.66Skamilparent_attach_to_its_child(bool stopped)
14051.1Skamil{
14061.1Skamil	struct msg_fds parent_tracee;
14071.1Skamil	const int exitval_tracee = 5;
14081.1Skamil	pid_t tracee, wpid;
14091.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
14101.1Skamil#if defined(TWAIT_HAVE_STATUS)
14111.1Skamil	int status;
14121.1Skamil#endif
14131.1Skamil
14141.13Schristos	DPRINTF("Spawn tracee\n");
14151.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
14161.1Skamil	tracee = atf_utils_fork();
14171.1Skamil	if (tracee == 0) {
14181.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
14191.13Schristos		DPRINTF("Parent should now attach to tracee\n");
14201.1Skamil
14211.66Skamil		if (stopped) {
14221.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
14231.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
14241.66Skamil		}
14251.66Skamil
14261.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
14271.1Skamil		/* Wait for message from the parent */
14281.1Skamil		_exit(exitval_tracee);
14291.1Skamil	}
14301.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
14311.57Skamil
14321.66Skamil	if (stopped) {
14331.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
14341.66Skamil		await_stopped(tracee);
14351.66Skamil	}
14361.66Skamil
14371.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
14381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
14391.1Skamil
14401.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
14411.1Skamil	    TWAIT_FNAME);
14421.1Skamil	TWAIT_REQUIRE_SUCCESS(
14431.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14441.1Skamil
14451.1Skamil	validate_status_stopped(status, SIGSTOP);
14461.1Skamil
14471.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
14481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
14491.1Skamil
14501.13Schristos	DPRINTF("Let the tracee exit now\n");
14511.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
14521.1Skamil
14531.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
14541.1Skamil	TWAIT_REQUIRE_SUCCESS(
14551.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14561.1Skamil
14571.1Skamil	validate_status_exited(status, exitval_tracee);
14581.1Skamil
14591.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
14601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
14611.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
14621.1Skamil
14631.1Skamil	msg_close(&parent_tracee);
14641.1Skamil}
14651.1Skamil
14661.66SkamilATF_TC(parent_attach_to_its_child);
14671.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
14681.66Skamil{
14691.66Skamil	atf_tc_set_md_var(tc, "descr",
14701.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
14711.66Skamil}
14721.66Skamil
14731.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
14741.66Skamil{
14751.66Skamil
14761.66Skamil	parent_attach_to_its_child(false);
14771.66Skamil}
14781.66Skamil
14791.66SkamilATF_TC(parent_attach_to_its_stopped_child);
14801.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
14811.66Skamil{
14821.66Skamil	atf_tc_set_md_var(tc, "descr",
14831.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
14841.66Skamil}
14851.66Skamil
14861.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
14871.66Skamil{
14881.66Skamil
14891.66Skamil	parent_attach_to_its_child(true);
14901.66Skamil}
14911.66Skamil
14921.51Skamil/// ----------------------------------------------------------------------------
14931.51Skamil
14941.65Skamilstatic void
14951.65Skamilchild_attach_to_its_parent(bool stopped)
14961.1Skamil{
14971.1Skamil	struct msg_fds parent_tracee;
14981.1Skamil	const int exitval_tracer = 5;
14991.1Skamil	pid_t tracer, wpid;
15001.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15011.1Skamil#if defined(TWAIT_HAVE_STATUS)
15021.1Skamil	int status;
15031.1Skamil#endif
15041.1Skamil
15051.13Schristos	DPRINTF("Spawn tracer\n");
15061.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15071.1Skamil	tracer = atf_utils_fork();
15081.1Skamil	if (tracer == 0) {
15091.1Skamil		/* Wait for message from the parent */
15101.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
15111.1Skamil
15121.65Skamil		if (stopped) {
15131.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
15141.65Skamil			        getppid());
15151.65Skamil			await_stopped(getppid());
15161.65Skamil		}
15171.65Skamil
15181.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
15191.1Skamil		    getppid());
15201.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
15211.1Skamil
15221.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
15231.1Skamil		    TWAIT_FNAME);
15241.1Skamil		FORKEE_REQUIRE_SUCCESS(
15251.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
15261.1Skamil
15271.1Skamil		forkee_status_stopped(status, SIGSTOP);
15281.1Skamil
15291.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
15301.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
15311.1Skamil		    != -1);
15321.1Skamil
15331.1Skamil		/* Tell parent we are ready */
15341.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
15351.1Skamil
15361.1Skamil		_exit(exitval_tracer);
15371.1Skamil	}
15381.1Skamil
15391.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
15401.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
15411.65Skamil
15421.65Skamil	if (stopped) {
15431.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
15441.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
15451.65Skamil	}
15461.65Skamil
15471.13Schristos	DPRINTF("Allow the tracer to exit now\n");
15481.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
15491.1Skamil
15501.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
15511.1Skamil	TWAIT_REQUIRE_SUCCESS(
15521.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
15531.1Skamil
15541.1Skamil	validate_status_exited(status, exitval_tracer);
15551.1Skamil
15561.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
15571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
15581.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
15591.1Skamil
15601.1Skamil	msg_close(&parent_tracee);
15611.1Skamil}
15621.1Skamil
15631.65SkamilATF_TC(child_attach_to_its_parent);
15641.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
15651.65Skamil{
15661.65Skamil	atf_tc_set_md_var(tc, "descr",
15671.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
15681.65Skamil}
15691.65Skamil
15701.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
15711.65Skamil{
15721.65Skamil
15731.65Skamil	child_attach_to_its_parent(false);
15741.65Skamil}
15751.65Skamil
15761.65SkamilATF_TC(child_attach_to_its_stopped_parent);
15771.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
15781.65Skamil{
15791.65Skamil	atf_tc_set_md_var(tc, "descr",
15801.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
15811.65Skamil}
15821.65Skamil
15831.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
15841.65Skamil{
15851.65Skamil	/*
15861.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
15871.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
15881.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
15891.65Skamil	 *
15901.65Skamil	 * As a workaround spawn this test as a subprocess.
15911.65Skamil	 */
15921.65Skamil
15931.65Skamil	const int exitval = 15;
15941.65Skamil	pid_t child, wpid;
15951.65Skamil#if defined(TWAIT_HAVE_STATUS)
15961.65Skamil	int status;
15971.65Skamil#endif
15981.65Skamil
15991.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
16001.65Skamil	if (child == 0) {
16011.65Skamil		child_attach_to_its_parent(true);
16021.65Skamil		_exit(exitval);
16031.65Skamil	} else {
16041.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16051.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16061.65Skamil
16071.65Skamil		validate_status_exited(status, exitval);
16081.65Skamil
16091.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
16101.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16111.65Skamil	}
16121.65Skamil}
16131.65Skamil
16141.51Skamil/// ----------------------------------------------------------------------------
16151.51Skamil
16161.1Skamil#if defined(TWAIT_HAVE_PID)
16171.1Skamil
16181.51Skamilenum tracee_sees_its_original_parent_type {
16191.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
16201.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
16211.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
16221.51Skamil};
16231.51Skamil
16241.51Skamilstatic void
16251.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
16261.1Skamil{
16271.1Skamil	struct msg_fds parent_tracer, parent_tracee;
16281.1Skamil	const int exitval_tracee = 5;
16291.1Skamil	const int exitval_tracer = 10;
16301.1Skamil	pid_t parent, tracee, tracer, wpid;
16311.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
16321.1Skamil#if defined(TWAIT_HAVE_STATUS)
16331.1Skamil	int status;
16341.1Skamil#endif
16351.51Skamil	/* sysctl(3) - kinfo_proc2 */
16361.51Skamil	int name[CTL_MAXNAME];
16371.51Skamil	struct kinfo_proc2 kp;
16381.51Skamil	size_t len = sizeof(kp);
16391.51Skamil	unsigned int namelen;
16401.51Skamil
16411.51Skamil	/* procfs - status  */
16421.51Skamil	FILE *fp;
16431.51Skamil	struct stat st;
16441.51Skamil	const char *fname = "/proc/curproc/status";
16451.51Skamil	char s_executable[MAXPATHLEN];
16461.51Skamil	int s_pid, s_ppid;
16471.51Skamil	int rv;
16481.51Skamil
16491.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
16501.61Skre		SYSCALL_REQUIRE(
16511.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
16521.61Skre		if (rv != 0)
16531.51Skamil			atf_tc_skip("/proc/curproc/status not found");
16541.51Skamil	}
16551.1Skamil
16561.13Schristos	DPRINTF("Spawn tracee\n");
16571.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
16581.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
16591.1Skamil	tracee = atf_utils_fork();
16601.1Skamil	if (tracee == 0) {
16611.1Skamil		parent = getppid();
16621.1Skamil
16631.1Skamil		/* Emit message to the parent */
16641.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
16651.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
16661.1Skamil
16671.51Skamil		switch (type) {
16681.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
16691.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
16701.51Skamil			break;
16711.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
16721.51Skamil			namelen = 0;
16731.51Skamil			name[namelen++] = CTL_KERN;
16741.51Skamil			name[namelen++] = KERN_PROC2;
16751.51Skamil			name[namelen++] = KERN_PROC_PID;
16761.51Skamil			name[namelen++] = getpid();
16771.51Skamil			name[namelen++] = len;
16781.51Skamil			name[namelen++] = 1;
16791.51Skamil
16801.61Skre			FORKEE_ASSERT_EQ(
16811.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
16821.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
16831.51Skamil			break;
16841.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
16851.51Skamil			/*
16861.51Skamil			 * Format:
16871.51Skamil			 *  EXECUTABLE PID PPID ...
16881.51Skamil			 */
16891.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
16901.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
16911.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
16921.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
16931.51Skamil			break;
16941.51Skamil		}
16951.1Skamil
16961.1Skamil		_exit(exitval_tracee);
16971.1Skamil	}
16981.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
16991.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
17001.1Skamil
17011.13Schristos	DPRINTF("Spawn debugger\n");
17021.1Skamil	tracer = atf_utils_fork();
17031.1Skamil	if (tracer == 0) {
17041.1Skamil		/* No IPC to communicate with the child */
17051.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
17061.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
17071.1Skamil
17081.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
17091.1Skamil		FORKEE_REQUIRE_SUCCESS(
17101.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17111.1Skamil
17121.1Skamil		forkee_status_stopped(status, SIGSTOP);
17131.1Skamil
17141.1Skamil		/* Resume tracee with PT_CONTINUE */
17151.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
17161.1Skamil
17171.1Skamil		/* Inform parent that tracer has attached to tracee */
17181.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
17191.1Skamil
17201.1Skamil		/* Wait for parent to tell use that tracee should have exited */
17211.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
17221.1Skamil
17231.1Skamil		/* Wait for tracee and assert that it exited */
17241.1Skamil		FORKEE_REQUIRE_SUCCESS(
17251.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17261.1Skamil
17271.1Skamil		forkee_status_exited(status, exitval_tracee);
17281.1Skamil
17291.13Schristos		DPRINTF("Before exiting of the tracer process\n");
17301.1Skamil		_exit(exitval_tracer);
17311.1Skamil	}
17321.1Skamil
17331.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
17341.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
17351.1Skamil
17361.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
17371.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
17381.1Skamil
17391.13Schristos	DPRINTF("Detect that tracee is zombie\n");
17401.1Skamil	await_zombie(tracee);
17411.1Skamil
17421.13Schristos	DPRINTF("Assert that there is no status about tracee - "
17431.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
17441.1Skamil	TWAIT_REQUIRE_SUCCESS(
17451.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
17461.1Skamil
17471.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
17481.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
17491.1Skamil
17501.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
17511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
17521.1Skamil	    tracer);
17531.1Skamil
17541.1Skamil	validate_status_exited(status, exitval_tracer);
17551.1Skamil
17561.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
17571.1Skamil	    TWAIT_FNAME);
17581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
17591.1Skamil	    tracee);
17601.1Skamil
17611.1Skamil	validate_status_exited(status, exitval_tracee);
17621.1Skamil
17631.1Skamil	msg_close(&parent_tracer);
17641.1Skamil	msg_close(&parent_tracee);
17651.1Skamil}
17661.1Skamil
17671.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
17681.61SkreATF_TC(test);								\
17691.61SkreATF_TC_HEAD(test, tc)							\
17701.61Skre{									\
17711.61Skre	atf_tc_set_md_var(tc, "descr",					\
17721.61Skre	    "Assert that tracee sees its original parent when being traced " \
17731.61Skre	    "(check " descr ")");					\
17741.61Skre}									\
17751.61Skre									\
17761.61SkreATF_TC_BODY(test, tc)							\
17771.61Skre{									\
17781.61Skre									\
17791.61Skre	tracee_sees_its_original_parent(type);				\
17801.1Skamil}
17811.1Skamil
17821.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
17831.51Skamil	tracee_sees_its_original_parent_getppid,
17841.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
17851.51Skamil	"getppid(2)");
17861.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
17871.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
17881.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
17891.51Skamil	"sysctl(3) and kinfo_proc2");
17901.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
17911.51Skamil	tracee_sees_its_original_parent_procfs_status,
17921.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
17931.51Skamil	"the status file in procfs");
17941.1Skamil#endif
17951.1Skamil
17961.51Skamil/// ----------------------------------------------------------------------------
17971.1Skamil
17981.53Skamilstatic void
17991.53Skamileventmask_preserved(int event)
18001.1Skamil{
18011.1Skamil	const int exitval = 5;
18021.1Skamil	const int sigval = SIGSTOP;
18031.1Skamil	pid_t child, wpid;
18041.1Skamil#if defined(TWAIT_HAVE_STATUS)
18051.1Skamil	int status;
18061.1Skamil#endif
18071.1Skamil	ptrace_event_t set_event, get_event;
18081.1Skamil	const int len = sizeof(ptrace_event_t);
18091.1Skamil
18101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18121.1Skamil	if (child == 0) {
18131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18151.1Skamil
18161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18181.1Skamil
18191.13Schristos		DPRINTF("Before exiting of the child process\n");
18201.1Skamil		_exit(exitval);
18211.1Skamil	}
18221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18231.1Skamil
18241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18261.1Skamil
18271.1Skamil	validate_status_stopped(status, sigval);
18281.1Skamil
18291.53Skamil	set_event.pe_set_event = event;
18301.61Skre	SYSCALL_REQUIRE(
18311.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
18321.61Skre	SYSCALL_REQUIRE(
18331.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
18341.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
18351.1Skamil
18361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18371.1Skamil	    "without signal to be sent\n");
18381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18391.1Skamil
18401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18421.1Skamil
18431.1Skamil	validate_status_exited(status, exitval);
18441.1Skamil
18451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18471.1Skamil}
18481.1Skamil
18491.61Skre#define EVENTMASK_PRESERVED(test, event)				\
18501.61SkreATF_TC(test);								\
18511.61SkreATF_TC_HEAD(test, tc)							\
18521.61Skre{									\
18531.61Skre	atf_tc_set_md_var(tc, "descr",					\
18541.61Skre	    "Verify that eventmask " #event " is preserved");		\
18551.61Skre}									\
18561.61Skre									\
18571.61SkreATF_TC_BODY(test, tc)							\
18581.61Skre{									\
18591.61Skre									\
18601.61Skre	eventmask_preserved(event);					\
18611.1Skamil}
18621.1Skamil
18631.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
18641.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
18651.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
18661.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
18671.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
18681.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
18691.1Skamil
18701.53Skamil/// ----------------------------------------------------------------------------
18711.1Skamil
18721.28Skamilstatic void
18731.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
18741.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
18751.1Skamil{
18761.1Skamil	const int exitval = 5;
18771.1Skamil	const int exitval2 = 15;
18781.1Skamil	const int sigval = SIGSTOP;
18791.31Skamil	pid_t child, child2 = 0, wpid;
18801.1Skamil#if defined(TWAIT_HAVE_STATUS)
18811.1Skamil	int status;
18821.1Skamil#endif
18831.1Skamil	ptrace_state_t state;
18841.1Skamil	const int slen = sizeof(state);
18851.1Skamil	ptrace_event_t event;
18861.1Skamil	const int elen = sizeof(event);
18871.1Skamil
18881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18901.1Skamil	if (child == 0) {
18911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18931.1Skamil
18941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18961.1Skamil
18971.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
18981.1Skamil
18991.1Skamil		if (child2 == 0)
19001.1Skamil			_exit(exitval2);
19011.1Skamil
19021.1Skamil		FORKEE_REQUIRE_SUCCESS
19031.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
19041.1Skamil
19051.1Skamil		forkee_status_exited(status, exitval2);
19061.1Skamil
19071.13Schristos		DPRINTF("Before exiting of the child process\n");
19081.1Skamil		_exit(exitval);
19091.1Skamil	}
19101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19111.1Skamil
19121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19141.1Skamil
19151.1Skamil	validate_status_stopped(status, sigval);
19161.1Skamil
19171.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
19181.61Skre	    trackfork ? "|PTRACE_FORK" : "",
19191.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
19201.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
19211.30Skamil	event.pe_set_event = 0;
19221.30Skamil	if (trackfork)
19231.30Skamil		event.pe_set_event |= PTRACE_FORK;
19241.30Skamil	if (trackvfork)
19251.30Skamil		event.pe_set_event |= PTRACE_VFORK;
19261.30Skamil	if (trackvforkdone)
19271.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
19281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
19291.1Skamil
19301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19311.1Skamil	    "without signal to be sent\n");
19321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19331.1Skamil
19341.29Skamil#if defined(TWAIT_HAVE_PID)
19351.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
19361.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
19371.61Skre		    child);
19381.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
19391.61Skre		    child);
19401.1Skamil
19411.29Skamil		validate_status_stopped(status, SIGTRAP);
19421.1Skamil
19431.61Skre		SYSCALL_REQUIRE(
19441.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
19451.31Skamil		if (trackfork && fn == fork) {
19461.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
19471.30Skamil			       PTRACE_FORK);
19481.30Skamil		}
19491.31Skamil		if (trackvfork && fn == vfork) {
19501.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
19511.30Skamil			       PTRACE_VFORK);
19521.30Skamil		}
19531.29Skamil
19541.29Skamil		child2 = state.pe_other_pid;
19551.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
19561.29Skamil
19571.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
19581.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
19591.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
19601.29Skamil		    child2);
19611.1Skamil
19621.29Skamil		validate_status_stopped(status, SIGTRAP);
19631.1Skamil
19641.61Skre		SYSCALL_REQUIRE(
19651.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
19661.31Skamil		if (trackfork && fn == fork) {
19671.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
19681.30Skamil			       PTRACE_FORK);
19691.30Skamil		}
19701.31Skamil		if (trackvfork && fn == vfork) {
19711.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
19721.30Skamil			       PTRACE_VFORK);
19731.30Skamil		}
19741.30Skamil
19751.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
19761.29Skamil
19771.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
19781.29Skamil		    "and without signal to be sent\n");
19791.61Skre		SYSCALL_REQUIRE(
19801.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
19811.29Skamil
19821.29Skamil		DPRINTF("Before resuming the child process where it left off "
19831.61Skre		    "and without signal to be sent\n");
19841.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19851.30Skamil	}
19861.30Skamil#endif
19871.30Skamil
19881.31Skamil	if (trackvforkdone && fn == vfork) {
19891.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
19901.61Skre		    child);
19911.61Skre		TWAIT_REQUIRE_SUCCESS(
19921.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
19931.30Skamil
19941.30Skamil		validate_status_stopped(status, SIGTRAP);
19951.30Skamil
19961.61Skre		SYSCALL_REQUIRE(
19971.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
19981.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
19991.30Skamil
20001.30Skamil		child2 = state.pe_other_pid;
20011.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
20021.61Skre		    child2);
20031.30Skamil
20041.30Skamil		DPRINTF("Before resuming the child process where it left off "
20051.61Skre		    "and without signal to be sent\n");
20061.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20071.30Skamil	}
20081.29Skamil
20091.30Skamil#if defined(TWAIT_HAVE_PID)
20101.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
20111.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
20121.61Skre		    "\n", TWAIT_FNAME);
20131.61Skre		TWAIT_REQUIRE_SUCCESS(
20141.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
20151.29Skamil
20161.29Skamil		validate_status_exited(status, exitval2);
20171.29Skamil
20181.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
20191.61Skre		    "process\n", TWAIT_FNAME);
20201.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
20211.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
20221.29Skamil	}
20231.29Skamil#endif
20241.1Skamil
20251.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
20261.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
20271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20281.1Skamil
20291.1Skamil	validate_status_stopped(status, SIGCHLD);
20301.1Skamil
20311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20321.1Skamil	    "without signal to be sent\n");
20331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20341.1Skamil
20351.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
20361.1Skamil	    TWAIT_FNAME);
20371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20381.1Skamil
20391.1Skamil	validate_status_exited(status, exitval);
20401.1Skamil
20411.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
20421.1Skamil	    TWAIT_FNAME);
20431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20441.1Skamil}
20451.28Skamil
20461.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
20471.61SkreATF_TC(name);								\
20481.61SkreATF_TC_HEAD(name, tc)							\
20491.61Skre{									\
20501.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
20511.61Skre}									\
20521.61Skre									\
20531.61SkreATF_TC_BODY(name, tc)							\
20541.61Skre{									\
20551.61Skre									\
20561.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
20571.32Skamil}
20581.32Skamil
20591.32Skamil#define F false
20601.32Skamil#define T true
20611.32Skamil
20621.32Skamil#define F_IF__0(x)
20631.32Skamil#define F_IF__1(x) x
20641.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
20651.32Skamil#define F_IF_(x,y) F_IF__(x,y)
20661.32Skamil#define F_IF(x,y) F_IF_(x,y)
20671.32Skamil
20681.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
20691.61Skre	"Verify " #function "(2) called with 0"				\
20701.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
20711.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
20721.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
20731.61Skre	" in EVENT_MASK."						\
20741.61Skre	F_IF(dchildbit," Detach child in this test.")			\
20751.61Skre	F_IF(dparentbit," Detach parent in this test.")
20761.1Skamil
20771.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
20781.31Skamil#if defined(TWAIT_HAVE_PID)
20791.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
20801.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
20811.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
20821.31Skamil#endif
20831.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
20841.31Skamil#if defined(TWAIT_HAVE_PID)
20851.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
20861.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
20871.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
20881.31Skamil#endif
20891.1Skamil
20901.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
20911.31Skamil#if defined(TWAIT_HAVE_PID)
20921.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
20931.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
20941.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
20951.31Skamil#endif
20961.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
20971.31Skamil#if defined(TWAIT_HAVE_PID)
20981.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
20991.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
21001.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
21011.31Skamil#endif
21021.31Skamil
21031.54Skamil/// ----------------------------------------------------------------------------
21041.31Skamil
21051.54Skamilenum bytes_transfer_type {
21061.54Skamil	BYTES_TRANSFER_DATA,
21071.54Skamil	BYTES_TRANSFER_DATAIO,
21081.54Skamil	BYTES_TRANSFER_TEXT,
21091.54Skamil	BYTES_TRANSFER_TEXTIO,
21101.54Skamil	BYTES_TRANSFER_AUXV
21111.54Skamil};
21121.31Skamil
21131.54Skamilstatic int __used
21141.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
21151.54Skamil{
21161.54Skamil	int e, f, g, h;
21171.1Skamil
21181.54Skamil	a *= 4;
21191.54Skamil	b += 3;
21201.54Skamil	c -= 2;
21211.54Skamil	d /= 1;
21221.1Skamil
21231.54Skamil	e = strtol("10", NULL, 10);
21241.54Skamil	f = strtol("20", NULL, 10);
21251.54Skamil	g = strtol("30", NULL, 10);
21261.54Skamil	h = strtol("40", NULL, 10);
21271.1Skamil
21281.54Skamil	return (a + b * c - d) + (e * f - g / h);
21291.1Skamil}
21301.1Skamil
21311.54Skamilstatic void
21321.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
21331.1Skamil{
21341.1Skamil	const int exitval = 5;
21351.1Skamil	const int sigval = SIGSTOP;
21361.1Skamil	pid_t child, wpid;
21371.54Skamil	bool skip = false;
21381.1Skamil
21391.54Skamil	int lookup_me = 0;
21401.54Skamil	uint8_t lookup_me8 = 0;
21411.54Skamil	uint16_t lookup_me16 = 0;
21421.54Skamil	uint32_t lookup_me32 = 0;
21431.54Skamil	uint64_t lookup_me64 = 0;
21441.1Skamil
21451.54Skamil	int magic = 0x13579246;
21461.54Skamil	uint8_t magic8 = 0xab;
21471.54Skamil	uint16_t magic16 = 0x1234;
21481.54Skamil	uint32_t magic32 = 0x98765432;
21491.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
21501.1Skamil
21511.54Skamil	struct ptrace_io_desc io;
21521.1Skamil#if defined(TWAIT_HAVE_STATUS)
21531.1Skamil	int status;
21541.1Skamil#endif
21551.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
21561.60Skre	AuxInfo ai[513], *aip;
21571.55Schristos
21581.55Schristos	ATF_REQUIRE(size < sizeof(ai));
21591.1Skamil
21601.54Skamil	/* Prepare variables for .TEXT transfers */
21611.54Skamil	switch (type) {
21621.54Skamil	case BYTES_TRANSFER_TEXT:
21631.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
21641.54Skamil		break;
21651.54Skamil	case BYTES_TRANSFER_TEXTIO:
21661.54Skamil		switch (size) {
21671.54Skamil		case 8:
21681.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
21691.54Skamil			break;
21701.54Skamil		case 16:
21711.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
21721.54Skamil			break;
21731.54Skamil		case 32:
21741.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
21751.54Skamil			break;
21761.54Skamil		case 64:
21771.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
21781.54Skamil			break;
21791.54Skamil		}
21801.54Skamil		break;
21811.54Skamil	default:
21821.54Skamil		break;
21831.54Skamil	}
21841.1Skamil
21851.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
21861.54Skamil	switch (type) {
21871.54Skamil	case BYTES_TRANSFER_TEXTIO:
21881.54Skamil	case BYTES_TRANSFER_DATAIO:
21891.54Skamil		io.piod_op = operation;
21901.54Skamil		switch (size) {
21911.54Skamil		case 8:
21921.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
21931.54Skamil			               (void *)bytes_transfer_dummy :
21941.54Skamil			               &lookup_me8;
21951.54Skamil			io.piod_addr = &lookup_me8;
21961.54Skamil			io.piod_len = sizeof(lookup_me8);
21971.54Skamil			break;
21981.54Skamil		case 16:
21991.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22001.54Skamil			               (void *)bytes_transfer_dummy :
22011.54Skamil			               &lookup_me16;
22021.54Skamil			io.piod_addr = &lookup_me16;
22031.54Skamil			io.piod_len = sizeof(lookup_me16);
22041.54Skamil			break;
22051.54Skamil		case 32:
22061.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22071.54Skamil			               (void *)bytes_transfer_dummy :
22081.54Skamil			               &lookup_me32;
22091.54Skamil			io.piod_addr = &lookup_me32;
22101.54Skamil			io.piod_len = sizeof(lookup_me32);
22111.54Skamil			break;
22121.54Skamil		case 64:
22131.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22141.54Skamil			               (void *)bytes_transfer_dummy :
22151.54Skamil			               &lookup_me64;
22161.54Skamil			io.piod_addr = &lookup_me64;
22171.54Skamil			io.piod_len = sizeof(lookup_me64);
22181.54Skamil			break;
22191.54Skamil		default:
22201.54Skamil			break;
22211.54Skamil		}
22221.54Skamil		break;
22231.54Skamil	case BYTES_TRANSFER_AUXV:
22241.54Skamil		io.piod_op = operation;
22251.54Skamil		io.piod_offs = 0;
22261.54Skamil		io.piod_addr = ai;
22271.54Skamil		io.piod_len = size;
22281.54Skamil		break;
22291.54Skamil	default:
22301.54Skamil		break;
22311.1Skamil	}
22321.1Skamil
22331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22351.1Skamil	if (child == 0) {
22361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22381.1Skamil
22391.54Skamil		switch (type) {
22401.54Skamil		case BYTES_TRANSFER_DATA:
22411.54Skamil			switch (operation) {
22421.54Skamil			case PT_READ_D:
22431.54Skamil			case PT_READ_I:
22441.54Skamil				lookup_me = magic;
22451.54Skamil				break;
22461.54Skamil			default:
22471.54Skamil				break;
22481.54Skamil			}
22491.54Skamil			break;
22501.54Skamil		case BYTES_TRANSFER_DATAIO:
22511.54Skamil			switch (operation) {
22521.54Skamil			case PIOD_READ_D:
22531.54Skamil			case PIOD_READ_I:
22541.54Skamil				switch (size) {
22551.54Skamil				case 8:
22561.54Skamil					lookup_me8 = magic8;
22571.54Skamil					break;
22581.54Skamil				case 16:
22591.54Skamil					lookup_me16 = magic16;
22601.54Skamil					break;
22611.54Skamil				case 32:
22621.54Skamil					lookup_me32 = magic32;
22631.54Skamil					break;
22641.54Skamil				case 64:
22651.54Skamil					lookup_me64 = magic64;
22661.54Skamil					break;
22671.54Skamil				default:
22681.54Skamil					break;
22691.54Skamil				}
22701.54Skamil				break;
22711.54Skamil			default:
22721.54Skamil				break;
22731.54Skamil			}
22741.54Skamil		default:
22751.54Skamil			break;
22761.54Skamil		}
22771.54Skamil
22781.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22791.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22801.1Skamil
22811.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
22821.54Skamil		switch (type) {
22831.54Skamil		case BYTES_TRANSFER_DATA:
22841.54Skamil			switch (operation) {
22851.54Skamil			case PT_WRITE_D:
22861.54Skamil			case PT_WRITE_I:
22871.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
22881.54Skamil				break;
22891.54Skamil			default:
22901.54Skamil				break;
22911.54Skamil			}
22921.54Skamil			break;
22931.54Skamil		case BYTES_TRANSFER_DATAIO:
22941.54Skamil			switch (operation) {
22951.54Skamil			case PIOD_WRITE_D:
22961.54Skamil			case PIOD_WRITE_I:
22971.54Skamil				switch (size) {
22981.54Skamil				case 8:
22991.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
23001.54Skamil					break;
23011.54Skamil				case 16:
23021.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
23031.54Skamil					break;
23041.54Skamil				case 32:
23051.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
23061.54Skamil					break;
23071.54Skamil				case 64:
23081.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
23091.54Skamil					break;
23101.54Skamil				default:
23111.54Skamil					break;
23121.54Skamil				}
23131.54Skamil				break;
23141.54Skamil			default:
23151.54Skamil				break;
23161.54Skamil			}
23171.54Skamil			break;
23181.54Skamil		case BYTES_TRANSFER_TEXT:
23191.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
23201.54Skamil			                     sizeof(magic)) == 0);
23211.54Skamil			break;
23221.54Skamil		case BYTES_TRANSFER_TEXTIO:
23231.54Skamil			switch (size) {
23241.54Skamil			case 8:
23251.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
23261.54Skamil				                     bytes_transfer_dummy,
23271.54Skamil				                     sizeof(magic8)) == 0);
23281.54Skamil				break;
23291.54Skamil			case 16:
23301.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
23311.54Skamil				                     bytes_transfer_dummy,
23321.54Skamil				                     sizeof(magic16)) == 0);
23331.54Skamil				break;
23341.54Skamil			case 32:
23351.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
23361.54Skamil				                     bytes_transfer_dummy,
23371.54Skamil				                     sizeof(magic32)) == 0);
23381.54Skamil				break;
23391.54Skamil			case 64:
23401.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
23411.54Skamil				                     bytes_transfer_dummy,
23421.54Skamil				                     sizeof(magic64)) == 0);
23431.54Skamil				break;
23441.54Skamil			}
23451.54Skamil			break;
23461.54Skamil		default:
23471.54Skamil			break;
23481.54Skamil		}
23491.54Skamil
23501.13Schristos		DPRINTF("Before exiting of the child process\n");
23511.1Skamil		_exit(exitval);
23521.1Skamil	}
23531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23541.1Skamil
23551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23571.1Skamil
23581.1Skamil	validate_status_stopped(status, sigval);
23591.1Skamil
23601.54Skamil	/* Check PaX MPROTECT */
23611.54Skamil	if (!can_we_write_to_text(child)) {
23621.54Skamil		switch (type) {
23631.54Skamil		case BYTES_TRANSFER_TEXTIO:
23641.54Skamil			switch (operation) {
23651.54Skamil			case PIOD_WRITE_D:
23661.54Skamil			case PIOD_WRITE_I:
23671.54Skamil				skip = true;
23681.54Skamil				break;
23691.54Skamil			default:
23701.54Skamil				break;
23711.54Skamil			}
23721.54Skamil			break;
23731.54Skamil		case BYTES_TRANSFER_TEXT:
23741.54Skamil			switch (operation) {
23751.54Skamil			case PT_WRITE_D:
23761.54Skamil			case PT_WRITE_I:
23771.54Skamil				skip = true;
23781.54Skamil				break;
23791.54Skamil			default:
23801.54Skamil				break;
23811.54Skamil			}
23821.54Skamil			break;
23831.54Skamil		default:
23841.54Skamil			break;
23851.54Skamil		}
23861.54Skamil	}
23871.1Skamil
23881.54Skamil	/* Bailout cleanly killing the child process */
23891.54Skamil	if (skip) {
23901.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
23911.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23921.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
23931.54Skamil		                      child);
23941.1Skamil
23951.54Skamil		validate_status_signaled(status, SIGKILL, 0);
23961.1Skamil
23971.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
23981.54Skamil	}
23991.1Skamil
24001.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
24011.54Skamil	       "parent=%d\n", child, getpid());
24021.1Skamil
24031.54Skamil	switch (type) {
24041.54Skamil	case BYTES_TRANSFER_TEXTIO:
24051.54Skamil	case BYTES_TRANSFER_DATAIO:
24061.54Skamil	case BYTES_TRANSFER_AUXV:
24071.54Skamil		switch (operation) {
24081.54Skamil		case PIOD_WRITE_D:
24091.54Skamil		case PIOD_WRITE_I:
24101.54Skamil			switch (size) {
24111.54Skamil			case 8:
24121.54Skamil				lookup_me8 = magic8;
24131.54Skamil				break;
24141.54Skamil			case 16:
24151.54Skamil				lookup_me16 = magic16;
24161.54Skamil				break;
24171.54Skamil			case 32:
24181.54Skamil				lookup_me32 = magic32;
24191.54Skamil				break;
24201.54Skamil			case 64:
24211.54Skamil				lookup_me64 = magic64;
24221.54Skamil				break;
24231.54Skamil			default:
24241.54Skamil				break;
24251.54Skamil			}
24261.54Skamil			break;
24271.54Skamil		default:
24281.54Skamil			break;
24291.54Skamil		}
24301.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
24311.54Skamil		switch (operation) {
24321.54Skamil		case PIOD_READ_D:
24331.54Skamil		case PIOD_READ_I:
24341.54Skamil			switch (size) {
24351.54Skamil			case 8:
24361.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
24371.54Skamil				break;
24381.54Skamil			case 16:
24391.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
24401.54Skamil				break;
24411.54Skamil			case 32:
24421.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
24431.54Skamil				break;
24441.54Skamil			case 64:
24451.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
24461.54Skamil				break;
24471.54Skamil			default:
24481.54Skamil				break;
24491.54Skamil			}
24501.54Skamil			break;
24511.54Skamil		case PIOD_READ_AUXV:
24521.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
24531.54Skamil			        io.piod_len);
24541.54Skamil			ATF_REQUIRE(io.piod_len > 0);
24551.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
24561.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
24571.54Skamil				    (long long int)aip->a_type,
24581.54Skamil				    (long long int)aip->a_v);
24591.54Skamil			break;
24601.54Skamil		default:
24611.54Skamil			break;
24621.54Skamil		}
24631.54Skamil		break;
24641.54Skamil	case BYTES_TRANSFER_TEXT:
24651.54Skamil		switch (operation) {
24661.54Skamil		case PT_READ_D:
24671.54Skamil		case PT_READ_I:
24681.54Skamil			errno = 0;
24691.54Skamil			lookup_me = ptrace(operation, child,
24701.54Skamil			                   bytes_transfer_dummy, 0);
24711.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
24721.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
24731.54Skamil			break;
24741.54Skamil		case PT_WRITE_D:
24751.54Skamil		case PT_WRITE_I:
24761.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
24771.54Skamil			                       bytes_transfer_dummy, magic)
24781.54Skamil			                != -1);
24791.54Skamil			break;
24801.54Skamil		default:
24811.54Skamil			break;
24821.54Skamil		}
24831.54Skamil		break;
24841.54Skamil	case BYTES_TRANSFER_DATA:
24851.54Skamil		switch (operation) {
24861.54Skamil		case PT_READ_D:
24871.54Skamil		case PT_READ_I:
24881.54Skamil			errno = 0;
24891.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
24901.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
24911.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
24921.54Skamil			break;
24931.54Skamil		case PT_WRITE_D:
24941.54Skamil		case PT_WRITE_I:
24951.54Skamil			lookup_me = magic;
24961.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
24971.54Skamil			                       magic) != -1);
24981.54Skamil			break;
24991.54Skamil		default:
25001.54Skamil			break;
25011.54Skamil		}
25021.54Skamil		break;
25031.54Skamil	default:
25041.54Skamil		break;
25051.54Skamil	}
25061.1Skamil
25071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25081.1Skamil	    "without signal to be sent\n");
25091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25101.1Skamil
25111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25131.1Skamil
25141.1Skamil	validate_status_exited(status, exitval);
25151.1Skamil
25161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25181.1Skamil}
25191.1Skamil
25201.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
25211.61SkreATF_TC(test);								\
25221.61SkreATF_TC_HEAD(test, tc)							\
25231.61Skre{									\
25241.61Skre	atf_tc_set_md_var(tc, "descr",					\
25251.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
25261.61Skre	    " of type " #type);						\
25271.61Skre}									\
25281.61Skre									\
25291.61SkreATF_TC_BODY(test, tc)							\
25301.61Skre{									\
25311.61Skre									\
25321.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
25331.1Skamil}
25341.1Skamil
25351.54Skamil// DATA
25361.1Skamil
25371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
25381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
25391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
25401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
25411.54Skamil
25421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
25431.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
25441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
25451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
25461.54Skamil
25471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
25481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
25491.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
25501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
25511.54Skamil
25521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
25531.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
25541.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
25551.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
25561.54Skamil
25571.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
25581.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
25591.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
25601.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
25611.54Skamil
25621.54Skamil// TEXT
25631.54Skamil
25641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
25651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
25661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
25671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
25681.54Skamil
25691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
25701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
25711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
25721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
25731.54Skamil
25741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
25751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
25761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
25771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
25781.54Skamil
25791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
25801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
25811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
25821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
25831.54Skamil
25841.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
25851.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
25861.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
25871.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
25881.1Skamil
25891.54Skamil// AUXV
25901.1Skamil
25911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
25921.1Skamil
25931.54Skamil/// ----------------------------------------------------------------------------
25941.1Skamil
25951.1Skamil#if defined(HAVE_GPREGS)
25961.1SkamilATF_TC(regs1);
25971.1SkamilATF_TC_HEAD(regs1, tc)
25981.1Skamil{
25991.1Skamil	atf_tc_set_md_var(tc, "descr",
26001.1Skamil	    "Verify plain PT_GETREGS call without further steps");
26011.1Skamil}
26021.1Skamil
26031.1SkamilATF_TC_BODY(regs1, tc)
26041.1Skamil{
26051.1Skamil	const int exitval = 5;
26061.1Skamil	const int sigval = SIGSTOP;
26071.1Skamil	pid_t child, wpid;
26081.1Skamil#if defined(TWAIT_HAVE_STATUS)
26091.1Skamil	int status;
26101.1Skamil#endif
26111.1Skamil	struct reg r;
26121.1Skamil
26131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26151.1Skamil	if (child == 0) {
26161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26181.1Skamil
26191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26211.1Skamil
26221.13Schristos		DPRINTF("Before exiting of the child process\n");
26231.1Skamil		_exit(exitval);
26241.1Skamil	}
26251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26261.1Skamil
26271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26291.1Skamil
26301.1Skamil	validate_status_stopped(status, sigval);
26311.1Skamil
26321.13Schristos	DPRINTF("Call GETREGS for the child process\n");
26331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
26341.1Skamil
26351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26361.1Skamil	    "without signal to be sent\n");
26371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26381.1Skamil
26391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26411.1Skamil
26421.1Skamil	validate_status_exited(status, exitval);
26431.1Skamil
26441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26461.1Skamil}
26471.1Skamil#endif
26481.1Skamil
26491.1Skamil#if defined(HAVE_GPREGS)
26501.1SkamilATF_TC(regs2);
26511.1SkamilATF_TC_HEAD(regs2, tc)
26521.1Skamil{
26531.1Skamil	atf_tc_set_md_var(tc, "descr",
26541.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
26551.1Skamil}
26561.1Skamil
26571.1SkamilATF_TC_BODY(regs2, tc)
26581.1Skamil{
26591.1Skamil	const int exitval = 5;
26601.1Skamil	const int sigval = SIGSTOP;
26611.1Skamil	pid_t child, wpid;
26621.1Skamil#if defined(TWAIT_HAVE_STATUS)
26631.1Skamil	int status;
26641.1Skamil#endif
26651.1Skamil	struct reg r;
26661.1Skamil
26671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26691.1Skamil	if (child == 0) {
26701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26721.1Skamil
26731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26751.1Skamil
26761.13Schristos		DPRINTF("Before exiting of the child process\n");
26771.1Skamil		_exit(exitval);
26781.1Skamil	}
26791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26801.1Skamil
26811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26831.1Skamil
26841.1Skamil	validate_status_stopped(status, sigval);
26851.1Skamil
26861.13Schristos	DPRINTF("Call GETREGS for the child process\n");
26871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
26881.1Skamil
26891.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
26901.1Skamil
26911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26921.1Skamil	    "without signal to be sent\n");
26931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26941.1Skamil
26951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26971.1Skamil
26981.1Skamil	validate_status_exited(status, exitval);
26991.1Skamil
27001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27011.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27021.1Skamil}
27031.1Skamil#endif
27041.1Skamil
27051.1Skamil#if defined(HAVE_GPREGS)
27061.1SkamilATF_TC(regs3);
27071.1SkamilATF_TC_HEAD(regs3, tc)
27081.1Skamil{
27091.1Skamil	atf_tc_set_md_var(tc, "descr",
27101.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
27111.1Skamil}
27121.1Skamil
27131.1SkamilATF_TC_BODY(regs3, tc)
27141.1Skamil{
27151.1Skamil	const int exitval = 5;
27161.1Skamil	const int sigval = SIGSTOP;
27171.1Skamil	pid_t child, wpid;
27181.1Skamil#if defined(TWAIT_HAVE_STATUS)
27191.1Skamil	int status;
27201.1Skamil#endif
27211.1Skamil	struct reg r;
27221.1Skamil
27231.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27241.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27251.1Skamil	if (child == 0) {
27261.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27271.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27281.1Skamil
27291.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27301.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27311.1Skamil
27321.13Schristos		DPRINTF("Before exiting of the child process\n");
27331.1Skamil		_exit(exitval);
27341.1Skamil	}
27351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27361.1Skamil
27371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27391.1Skamil
27401.1Skamil	validate_status_stopped(status, sigval);
27411.1Skamil
27421.13Schristos	DPRINTF("Call GETREGS for the child process\n");
27431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
27441.1Skamil
27451.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
27461.1Skamil
27471.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27481.1Skamil	    "without signal to be sent\n");
27491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27501.1Skamil
27511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27531.1Skamil
27541.1Skamil	validate_status_exited(status, exitval);
27551.1Skamil
27561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27581.1Skamil}
27591.1Skamil#endif
27601.1Skamil
27611.1Skamil#if defined(HAVE_GPREGS)
27621.1SkamilATF_TC(regs4);
27631.1SkamilATF_TC_HEAD(regs4, tc)
27641.1Skamil{
27651.1Skamil	atf_tc_set_md_var(tc, "descr",
27661.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
27671.1Skamil}
27681.1Skamil
27691.1SkamilATF_TC_BODY(regs4, tc)
27701.1Skamil{
27711.1Skamil	const int exitval = 5;
27721.1Skamil	const int sigval = SIGSTOP;
27731.1Skamil	pid_t child, wpid;
27741.1Skamil#if defined(TWAIT_HAVE_STATUS)
27751.1Skamil	int status;
27761.1Skamil#endif
27771.1Skamil	struct reg r;
27781.1Skamil
27791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27811.1Skamil	if (child == 0) {
27821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27841.1Skamil
27851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27871.1Skamil
27881.13Schristos		DPRINTF("Before exiting of the child process\n");
27891.1Skamil		_exit(exitval);
27901.1Skamil	}
27911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27921.1Skamil
27931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27951.1Skamil
27961.1Skamil	validate_status_stopped(status, sigval);
27971.1Skamil
27981.13Schristos	DPRINTF("Call GETREGS for the child process\n");
27991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28001.1Skamil
28011.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
28021.1Skamil
28031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28041.1Skamil	    "without signal to be sent\n");
28051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28061.1Skamil
28071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28091.1Skamil
28101.1Skamil	validate_status_exited(status, exitval);
28111.1Skamil
28121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28141.1Skamil}
28151.1Skamil#endif
28161.1Skamil
28171.1Skamil#if defined(HAVE_GPREGS)
28181.1SkamilATF_TC(regs5);
28191.1SkamilATF_TC_HEAD(regs5, tc)
28201.1Skamil{
28211.1Skamil	atf_tc_set_md_var(tc, "descr",
28221.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
28231.1Skamil}
28241.1Skamil
28251.1SkamilATF_TC_BODY(regs5, tc)
28261.1Skamil{
28271.1Skamil	const int exitval = 5;
28281.1Skamil	const int sigval = SIGSTOP;
28291.1Skamil	pid_t child, wpid;
28301.1Skamil#if defined(TWAIT_HAVE_STATUS)
28311.1Skamil	int status;
28321.1Skamil#endif
28331.1Skamil	struct reg r;
28341.1Skamil
28351.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28361.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28371.1Skamil	if (child == 0) {
28381.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28391.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28401.1Skamil
28411.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28421.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28431.1Skamil
28441.13Schristos		DPRINTF("Before exiting of the child process\n");
28451.1Skamil		_exit(exitval);
28461.1Skamil	}
28471.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28481.1Skamil
28491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28511.1Skamil
28521.1Skamil	validate_status_stopped(status, sigval);
28531.1Skamil
28541.13Schristos	DPRINTF("Call GETREGS for the child process\n");
28551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28561.1Skamil
28571.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
28581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28591.1Skamil
28601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28611.1Skamil	    "without signal to be sent\n");
28621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28631.1Skamil
28641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28661.1Skamil
28671.1Skamil	validate_status_exited(status, exitval);
28681.1Skamil
28691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28711.1Skamil}
28721.1Skamil#endif
28731.1Skamil
28741.1Skamil#if defined(HAVE_FPREGS)
28751.1SkamilATF_TC(fpregs1);
28761.1SkamilATF_TC_HEAD(fpregs1, tc)
28771.1Skamil{
28781.1Skamil	atf_tc_set_md_var(tc, "descr",
28791.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
28801.1Skamil}
28811.1Skamil
28821.1SkamilATF_TC_BODY(fpregs1, tc)
28831.1Skamil{
28841.1Skamil	const int exitval = 5;
28851.1Skamil	const int sigval = SIGSTOP;
28861.1Skamil	pid_t child, wpid;
28871.1Skamil#if defined(TWAIT_HAVE_STATUS)
28881.1Skamil	int status;
28891.1Skamil#endif
28901.1Skamil	struct fpreg r;
28911.1Skamil
28921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28941.1Skamil	if (child == 0) {
28951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28971.1Skamil
28981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29001.1Skamil
29011.13Schristos		DPRINTF("Before exiting of the child process\n");
29021.1Skamil		_exit(exitval);
29031.1Skamil	}
29041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29051.1Skamil
29061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29081.1Skamil
29091.1Skamil	validate_status_stopped(status, sigval);
29101.1Skamil
29111.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
29121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
29131.1Skamil
29141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29151.1Skamil	    "without signal to be sent\n");
29161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29171.1Skamil
29181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29201.1Skamil
29211.1Skamil	validate_status_exited(status, exitval);
29221.1Skamil
29231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29251.1Skamil}
29261.1Skamil#endif
29271.1Skamil
29281.1Skamil#if defined(HAVE_FPREGS)
29291.1SkamilATF_TC(fpregs2);
29301.1SkamilATF_TC_HEAD(fpregs2, tc)
29311.1Skamil{
29321.1Skamil	atf_tc_set_md_var(tc, "descr",
29331.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
29341.1Skamil	    "regs");
29351.1Skamil}
29361.1Skamil
29371.1SkamilATF_TC_BODY(fpregs2, tc)
29381.1Skamil{
29391.1Skamil	const int exitval = 5;
29401.1Skamil	const int sigval = SIGSTOP;
29411.1Skamil	pid_t child, wpid;
29421.1Skamil#if defined(TWAIT_HAVE_STATUS)
29431.1Skamil	int status;
29441.1Skamil#endif
29451.1Skamil	struct fpreg r;
29461.1Skamil
29471.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29481.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29491.1Skamil	if (child == 0) {
29501.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29511.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29521.1Skamil
29531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29551.1Skamil
29561.13Schristos		DPRINTF("Before exiting of the child process\n");
29571.1Skamil		_exit(exitval);
29581.1Skamil	}
29591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29601.1Skamil
29611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29631.1Skamil
29641.1Skamil	validate_status_stopped(status, sigval);
29651.1Skamil
29661.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
29671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
29681.1Skamil
29691.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
29701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
29711.1Skamil
29721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29731.1Skamil	    "without signal to be sent\n");
29741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29751.1Skamil
29761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29781.1Skamil
29791.1Skamil	validate_status_exited(status, exitval);
29801.1Skamil
29811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29831.1Skamil}
29841.1Skamil#endif
29851.1Skamil
29861.1Skamil#if defined(PT_STEP)
29871.1Skamilstatic void
29881.2Skamilptrace_step(int N, int setstep)
29891.1Skamil{
29901.1Skamil	const int exitval = 5;
29911.1Skamil	const int sigval = SIGSTOP;
29921.1Skamil	pid_t child, wpid;
29931.1Skamil#if defined(TWAIT_HAVE_STATUS)
29941.1Skamil	int status;
29951.1Skamil#endif
29961.1Skamil	int happy;
29971.1Skamil
29981.1Skamil#if defined(__arm__)
29991.1Skamil	/* PT_STEP not supported on arm 32-bit */
30001.1Skamil	atf_tc_expect_fail("PR kern/52119");
30011.1Skamil#endif
30021.1Skamil
30031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30051.1Skamil	if (child == 0) {
30061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30081.1Skamil
30091.1Skamil		happy = check_happy(999);
30101.1Skamil
30111.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30121.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30131.1Skamil
30141.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
30151.1Skamil
30161.13Schristos		DPRINTF("Before exiting of the child process\n");
30171.1Skamil		_exit(exitval);
30181.1Skamil	}
30191.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30201.1Skamil
30211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30231.1Skamil
30241.1Skamil	validate_status_stopped(status, sigval);
30251.1Skamil
30261.1Skamil	while (N --> 0) {
30271.2Skamil		if (setstep) {
30281.13Schristos			DPRINTF("Before resuming the child process where it "
30291.2Skamil			    "left off and without signal to be sent (use "
30301.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
30311.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
30321.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
30331.2Skamil			    != -1);
30341.2Skamil		} else {
30351.13Schristos			DPRINTF("Before resuming the child process where it "
30361.2Skamil			    "left off and without signal to be sent (use "
30371.2Skamil			    "PT_STEP)\n");
30381.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
30391.2Skamil			    != -1);
30401.2Skamil		}
30411.1Skamil
30421.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30431.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30441.1Skamil		    child);
30451.1Skamil
30461.1Skamil		validate_status_stopped(status, SIGTRAP);
30471.2Skamil
30481.2Skamil		if (setstep) {
30491.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
30501.2Skamil		}
30511.1Skamil	}
30521.1Skamil
30531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30541.1Skamil	    "without signal to be sent\n");
30551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30561.1Skamil
30571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30591.1Skamil
30601.1Skamil	validate_status_exited(status, exitval);
30611.1Skamil
30621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30641.1Skamil}
30651.1Skamil#endif
30661.1Skamil
30671.1Skamil#if defined(PT_STEP)
30681.1SkamilATF_TC(step1);
30691.1SkamilATF_TC_HEAD(step1, tc)
30701.1Skamil{
30711.1Skamil	atf_tc_set_md_var(tc, "descr",
30721.1Skamil	    "Verify single PT_STEP call");
30731.1Skamil}
30741.1Skamil
30751.1SkamilATF_TC_BODY(step1, tc)
30761.1Skamil{
30771.2Skamil	ptrace_step(1, 0);
30781.1Skamil}
30791.1Skamil#endif
30801.1Skamil
30811.1Skamil#if defined(PT_STEP)
30821.1SkamilATF_TC(step2);
30831.1SkamilATF_TC_HEAD(step2, tc)
30841.1Skamil{
30851.1Skamil	atf_tc_set_md_var(tc, "descr",
30861.1Skamil	    "Verify PT_STEP called twice");
30871.1Skamil}
30881.1Skamil
30891.1SkamilATF_TC_BODY(step2, tc)
30901.1Skamil{
30911.2Skamil	ptrace_step(2, 0);
30921.1Skamil}
30931.1Skamil#endif
30941.1Skamil
30951.1Skamil#if defined(PT_STEP)
30961.1SkamilATF_TC(step3);
30971.1SkamilATF_TC_HEAD(step3, tc)
30981.1Skamil{
30991.1Skamil	atf_tc_set_md_var(tc, "descr",
31001.1Skamil	    "Verify PT_STEP called three times");
31011.1Skamil}
31021.1Skamil
31031.1SkamilATF_TC_BODY(step3, tc)
31041.1Skamil{
31051.2Skamil	ptrace_step(3, 0);
31061.1Skamil}
31071.1Skamil#endif
31081.1Skamil
31091.1Skamil#if defined(PT_STEP)
31101.1SkamilATF_TC(step4);
31111.1SkamilATF_TC_HEAD(step4, tc)
31121.1Skamil{
31131.1Skamil	atf_tc_set_md_var(tc, "descr",
31141.1Skamil	    "Verify PT_STEP called four times");
31151.1Skamil}
31161.1Skamil
31171.1SkamilATF_TC_BODY(step4, tc)
31181.1Skamil{
31191.2Skamil	ptrace_step(4, 0);
31201.2Skamil}
31211.2Skamil#endif
31221.2Skamil
31231.2Skamil#if defined(PT_STEP)
31241.2SkamilATF_TC(setstep1);
31251.2SkamilATF_TC_HEAD(setstep1, tc)
31261.2Skamil{
31271.2Skamil	atf_tc_set_md_var(tc, "descr",
31281.2Skamil	    "Verify single PT_SETSTEP call");
31291.2Skamil}
31301.2Skamil
31311.2SkamilATF_TC_BODY(setstep1, tc)
31321.2Skamil{
31331.2Skamil	ptrace_step(1, 1);
31341.2Skamil}
31351.2Skamil#endif
31361.2Skamil
31371.2Skamil#if defined(PT_STEP)
31381.2SkamilATF_TC(setstep2);
31391.2SkamilATF_TC_HEAD(setstep2, tc)
31401.2Skamil{
31411.2Skamil	atf_tc_set_md_var(tc, "descr",
31421.2Skamil	    "Verify PT_SETSTEP called twice");
31431.2Skamil}
31441.2Skamil
31451.2SkamilATF_TC_BODY(setstep2, tc)
31461.2Skamil{
31471.2Skamil	ptrace_step(2, 1);
31481.2Skamil}
31491.2Skamil#endif
31501.2Skamil
31511.2Skamil#if defined(PT_STEP)
31521.2SkamilATF_TC(setstep3);
31531.2SkamilATF_TC_HEAD(setstep3, tc)
31541.2Skamil{
31551.2Skamil	atf_tc_set_md_var(tc, "descr",
31561.2Skamil	    "Verify PT_SETSTEP called three times");
31571.2Skamil}
31581.2Skamil
31591.2SkamilATF_TC_BODY(setstep3, tc)
31601.2Skamil{
31611.2Skamil	ptrace_step(3, 1);
31621.2Skamil}
31631.2Skamil#endif
31641.2Skamil
31651.2Skamil#if defined(PT_STEP)
31661.2SkamilATF_TC(setstep4);
31671.2SkamilATF_TC_HEAD(setstep4, tc)
31681.2Skamil{
31691.2Skamil	atf_tc_set_md_var(tc, "descr",
31701.2Skamil	    "Verify PT_SETSTEP called four times");
31711.2Skamil}
31721.2Skamil
31731.2SkamilATF_TC_BODY(setstep4, tc)
31741.2Skamil{
31751.2Skamil	ptrace_step(4, 1);
31761.1Skamil}
31771.1Skamil#endif
31781.1Skamil
31791.1SkamilATF_TC(kill1);
31801.1SkamilATF_TC_HEAD(kill1, tc)
31811.1Skamil{
31821.1Skamil	atf_tc_set_md_var(tc, "descr",
31831.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
31841.1Skamil}
31851.1Skamil
31861.1SkamilATF_TC_BODY(kill1, tc)
31871.1Skamil{
31881.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
31891.1Skamil	pid_t child, wpid;
31901.1Skamil#if defined(TWAIT_HAVE_STATUS)
31911.1Skamil	int status;
31921.1Skamil#endif
31931.1Skamil
31941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31961.1Skamil	if (child == 0) {
31971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31991.1Skamil
32001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32021.1Skamil
32031.1Skamil		/* NOTREACHED */
32041.1Skamil		FORKEE_ASSERTX(0 &&
32051.1Skamil		    "Child should be terminated by a signal from its parent");
32061.1Skamil	}
32071.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32081.1Skamil
32091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32111.1Skamil
32121.1Skamil	validate_status_stopped(status, sigval);
32131.1Skamil
32141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32151.1Skamil	    "without signal to be sent\n");
32161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
32171.1Skamil
32181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32201.1Skamil
32211.1Skamil	validate_status_signaled(status, sigsent, 0);
32221.1Skamil
32231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32251.1Skamil}
32261.1Skamil
32271.1SkamilATF_TC(kill2);
32281.1SkamilATF_TC_HEAD(kill2, tc)
32291.1Skamil{
32301.1Skamil	atf_tc_set_md_var(tc, "descr",
32311.1Skamil	    "Verify that PT_KILL terminates child");
32321.1Skamil}
32331.1Skamil
32341.1SkamilATF_TC_BODY(kill2, tc)
32351.1Skamil{
32361.1Skamil	const int sigval = SIGSTOP;
32371.1Skamil	pid_t child, wpid;
32381.1Skamil#if defined(TWAIT_HAVE_STATUS)
32391.1Skamil	int status;
32401.1Skamil#endif
32411.1Skamil
32421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32441.1Skamil	if (child == 0) {
32451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32471.1Skamil
32481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32501.1Skamil
32511.1Skamil		/* NOTREACHED */
32521.1Skamil		FORKEE_ASSERTX(0 &&
32531.1Skamil		    "Child should be terminated by a signal from its parent");
32541.1Skamil	}
32551.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32561.1Skamil
32571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32591.1Skamil
32601.1Skamil	validate_status_stopped(status, sigval);
32611.1Skamil
32621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32631.1Skamil	    "without signal to be sent\n");
32641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
32651.1Skamil
32661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32681.1Skamil
32691.1Skamil	validate_status_signaled(status, SIGKILL, 0);
32701.1Skamil
32711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32721.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32731.1Skamil}
32741.1Skamil
32751.1SkamilATF_TC(lwpinfo1);
32761.1SkamilATF_TC_HEAD(lwpinfo1, tc)
32771.1Skamil{
32781.1Skamil	atf_tc_set_md_var(tc, "descr",
32791.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
32801.1Skamil}
32811.1Skamil
32821.1SkamilATF_TC_BODY(lwpinfo1, tc)
32831.1Skamil{
32841.1Skamil	const int exitval = 5;
32851.1Skamil	const int sigval = SIGSTOP;
32861.1Skamil	pid_t child, wpid;
32871.1Skamil#if defined(TWAIT_HAVE_STATUS)
32881.1Skamil	int status;
32891.1Skamil#endif
32901.1Skamil	struct ptrace_lwpinfo info = {0, 0};
32911.1Skamil
32921.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32931.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32941.1Skamil	if (child == 0) {
32951.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32961.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32971.1Skamil
32981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33001.1Skamil
33011.13Schristos		DPRINTF("Before exiting of the child process\n");
33021.1Skamil		_exit(exitval);
33031.1Skamil	}
33041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33051.1Skamil
33061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33081.1Skamil
33091.1Skamil	validate_status_stopped(status, sigval);
33101.1Skamil
33111.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
33131.1Skamil
33141.13Schristos	DPRINTF("Assert that there exists a thread\n");
33151.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
33161.1Skamil
33171.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
33181.1Skamil	    info.pl_lwpid);
33191.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
33201.1Skamil	    "Received event %d != expected event %d",
33211.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
33221.1Skamil
33231.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
33251.1Skamil
33261.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
33271.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
33281.1Skamil
33291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33301.1Skamil	    "without signal to be sent\n");
33311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33321.1Skamil
33331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33351.1Skamil
33361.1Skamil	validate_status_exited(status, exitval);
33371.1Skamil
33381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33401.1Skamil}
33411.1Skamil
33421.1Skamil#if defined(TWAIT_HAVE_PID)
33431.1SkamilATF_TC(lwpinfo2);
33441.1SkamilATF_TC_HEAD(lwpinfo2, tc)
33451.1Skamil{
33461.1Skamil	atf_tc_set_md_var(tc, "descr",
33471.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
33481.1Skamil	    "tracer)");
33491.1Skamil}
33501.1Skamil
33511.1SkamilATF_TC_BODY(lwpinfo2, tc)
33521.1Skamil{
33531.1Skamil	struct msg_fds parent_tracee, parent_tracer;
33541.1Skamil	const int exitval_tracee = 5;
33551.1Skamil	const int exitval_tracer = 10;
33561.1Skamil	pid_t tracee, tracer, wpid;
33571.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
33581.1Skamil#if defined(TWAIT_HAVE_STATUS)
33591.1Skamil	int status;
33601.1Skamil#endif
33611.1Skamil	struct ptrace_lwpinfo info = {0, 0};
33621.1Skamil
33631.13Schristos	DPRINTF("Spawn tracee\n");
33641.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
33651.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
33661.1Skamil	tracee = atf_utils_fork();
33671.1Skamil	if (tracee == 0) {
33681.1Skamil
33691.1Skamil		/* Wait for message from the parent */
33701.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
33711.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
33721.1Skamil
33731.1Skamil		_exit(exitval_tracee);
33741.1Skamil	}
33751.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
33761.1Skamil
33771.13Schristos	DPRINTF("Spawn debugger\n");
33781.1Skamil	tracer = atf_utils_fork();
33791.1Skamil	if (tracer == 0) {
33801.1Skamil		/* No IPC to communicate with the child */
33811.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
33821.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
33831.1Skamil
33841.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
33851.1Skamil		FORKEE_REQUIRE_SUCCESS(
33861.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
33871.1Skamil
33881.1Skamil		forkee_status_stopped(status, SIGSTOP);
33891.1Skamil
33901.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33911.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
33921.1Skamil		    != -1);
33931.1Skamil
33941.13Schristos		DPRINTF("Assert that there exists a thread\n");
33951.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
33961.1Skamil
33971.13Schristos		DPRINTF("Assert that lwp thread %d received event "
33981.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
33991.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
34001.1Skamil
34011.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
34021.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
34031.1Skamil		    != -1);
34041.1Skamil
34051.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
34061.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
34071.1Skamil
34081.1Skamil		/* Resume tracee with PT_CONTINUE */
34091.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
34101.1Skamil
34111.1Skamil		/* Inform parent that tracer has attached to tracee */
34121.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
34131.1Skamil		/* Wait for parent */
34141.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
34151.1Skamil
34161.1Skamil		/* Wait for tracee and assert that it exited */
34171.1Skamil		FORKEE_REQUIRE_SUCCESS(
34181.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
34191.1Skamil
34201.1Skamil		forkee_status_exited(status, exitval_tracee);
34211.1Skamil
34221.13Schristos		DPRINTF("Before exiting of the tracer process\n");
34231.1Skamil		_exit(exitval_tracer);
34241.1Skamil	}
34251.1Skamil
34261.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
34271.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
34281.1Skamil
34291.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
34301.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
34311.1Skamil
34321.13Schristos	DPRINTF("Detect that tracee is zombie\n");
34331.1Skamil	await_zombie(tracee);
34341.1Skamil
34351.13Schristos	DPRINTF("Assert that there is no status about tracee - "
34361.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
34371.1Skamil	TWAIT_REQUIRE_SUCCESS(
34381.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
34391.1Skamil
34401.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
34411.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
34421.1Skamil
34431.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
34441.1Skamil	    TWAIT_FNAME);
34451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
34461.1Skamil	    tracer);
34471.1Skamil
34481.1Skamil	validate_status_exited(status, exitval_tracer);
34491.1Skamil
34501.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
34511.1Skamil	    TWAIT_FNAME);
34521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
34531.1Skamil	    tracee);
34541.1Skamil
34551.1Skamil	validate_status_exited(status, exitval_tracee);
34561.1Skamil
34571.1Skamil	msg_close(&parent_tracer);
34581.1Skamil	msg_close(&parent_tracee);
34591.1Skamil}
34601.1Skamil#endif
34611.1Skamil
34621.1SkamilATF_TC(siginfo1);
34631.1SkamilATF_TC_HEAD(siginfo1, tc)
34641.1Skamil{
34651.1Skamil	atf_tc_set_md_var(tc, "descr",
34661.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
34671.1Skamil}
34681.1Skamil
34691.1SkamilATF_TC_BODY(siginfo1, tc)
34701.1Skamil{
34711.1Skamil	const int exitval = 5;
34721.1Skamil	const int sigval = SIGTRAP;
34731.1Skamil	pid_t child, wpid;
34741.1Skamil#if defined(TWAIT_HAVE_STATUS)
34751.1Skamil	int status;
34761.1Skamil#endif
34771.1Skamil	struct ptrace_siginfo info;
34781.1Skamil	memset(&info, 0, sizeof(info));
34791.1Skamil
34801.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34811.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34821.1Skamil	if (child == 0) {
34831.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34841.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34851.1Skamil
34861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34881.1Skamil
34891.13Schristos		DPRINTF("Before exiting of the child process\n");
34901.1Skamil		_exit(exitval);
34911.1Skamil	}
34921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34931.1Skamil
34941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34961.1Skamil
34971.1Skamil	validate_status_stopped(status, sigval);
34981.1Skamil
34991.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35011.1Skamil
35021.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35031.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35041.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35051.1Skamil	    info.psi_siginfo.si_errno);
35061.1Skamil
35071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35081.1Skamil	    "without signal to be sent\n");
35091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35101.1Skamil
35111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35131.1Skamil
35141.1Skamil	validate_status_exited(status, exitval);
35151.1Skamil
35161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35181.1Skamil}
35191.1Skamil
35201.1SkamilATF_TC(siginfo2);
35211.1SkamilATF_TC_HEAD(siginfo2, tc)
35221.1Skamil{
35231.1Skamil	atf_tc_set_md_var(tc, "descr",
35241.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
35251.1Skamil	    "modification of SIGINT from tracee");
35261.1Skamil}
35271.1Skamil
35281.1Skamilstatic int siginfo2_caught = 0;
35291.1Skamil
35301.1Skamilstatic void
35311.1Skamilsiginfo2_sighandler(int sig)
35321.1Skamil{
35331.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
35341.1Skamil
35351.1Skamil	++siginfo2_caught;
35361.1Skamil}
35371.1Skamil
35381.1SkamilATF_TC_BODY(siginfo2, tc)
35391.1Skamil{
35401.1Skamil	const int exitval = 5;
35411.1Skamil	const int sigval = SIGINT;
35421.1Skamil	pid_t child, wpid;
35431.1Skamil	struct sigaction sa;
35441.1Skamil#if defined(TWAIT_HAVE_STATUS)
35451.1Skamil	int status;
35461.1Skamil#endif
35471.1Skamil	struct ptrace_siginfo info;
35481.1Skamil	memset(&info, 0, sizeof(info));
35491.1Skamil
35501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35521.1Skamil	if (child == 0) {
35531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35551.1Skamil
35561.1Skamil		sa.sa_handler = siginfo2_sighandler;
35571.1Skamil		sa.sa_flags = SA_SIGINFO;
35581.1Skamil		sigemptyset(&sa.sa_mask);
35591.1Skamil
35601.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
35611.1Skamil
35621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35641.1Skamil
35651.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
35661.1Skamil
35671.13Schristos		DPRINTF("Before exiting of the child process\n");
35681.1Skamil		_exit(exitval);
35691.1Skamil	}
35701.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35711.1Skamil
35721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35741.1Skamil
35751.1Skamil	validate_status_stopped(status, sigval);
35761.1Skamil
35771.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35791.1Skamil
35801.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35811.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35821.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35831.1Skamil	    info.psi_siginfo.si_errno);
35841.1Skamil
35851.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
35861.61Skre	SYSCALL_REQUIRE(
35871.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
35881.1Skamil
35891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35901.1Skamil	    "without signal to be sent\n");
35911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
35921.1Skamil
35931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35951.1Skamil
35961.1Skamil	validate_status_exited(status, exitval);
35971.1Skamil
35981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36001.1Skamil}
36011.1Skamil
36021.1SkamilATF_TC(siginfo3);
36031.1SkamilATF_TC_HEAD(siginfo3, tc)
36041.1Skamil{
36051.1Skamil	atf_tc_set_md_var(tc, "descr",
36061.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
36071.1Skamil	    "setting signal to new value");
36081.1Skamil}
36091.1Skamil
36101.1Skamilstatic int siginfo3_caught = 0;
36111.1Skamil
36121.1Skamilstatic void
36131.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
36141.1Skamil{
36151.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
36161.1Skamil
36171.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
36181.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
36191.1Skamil
36201.1Skamil	++siginfo3_caught;
36211.1Skamil}
36221.1Skamil
36231.1SkamilATF_TC_BODY(siginfo3, tc)
36241.1Skamil{
36251.1Skamil	const int exitval = 5;
36261.1Skamil	const int sigval = SIGINT;
36271.1Skamil	const int sigfaked = SIGTRAP;
36281.1Skamil	const int sicodefaked = TRAP_BRKPT;
36291.1Skamil	pid_t child, wpid;
36301.1Skamil	struct sigaction sa;
36311.1Skamil#if defined(TWAIT_HAVE_STATUS)
36321.1Skamil	int status;
36331.1Skamil#endif
36341.1Skamil	struct ptrace_siginfo info;
36351.1Skamil	memset(&info, 0, sizeof(info));
36361.1Skamil
36371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36391.1Skamil	if (child == 0) {
36401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36421.1Skamil
36431.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
36441.1Skamil		sa.sa_flags = SA_SIGINFO;
36451.1Skamil		sigemptyset(&sa.sa_mask);
36461.1Skamil
36471.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
36481.1Skamil
36491.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36501.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36511.1Skamil
36521.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
36531.1Skamil
36541.13Schristos		DPRINTF("Before exiting of the child process\n");
36551.1Skamil		_exit(exitval);
36561.1Skamil	}
36571.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36581.1Skamil
36591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36611.1Skamil
36621.1Skamil	validate_status_stopped(status, sigval);
36631.1Skamil
36641.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36651.61Skre	SYSCALL_REQUIRE(
36661.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36671.1Skamil
36681.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36691.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
36701.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36711.1Skamil	    info.psi_siginfo.si_errno);
36721.1Skamil
36731.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
36741.1Skamil	    sigfaked, sicodefaked);
36751.1Skamil	info.psi_siginfo.si_signo = sigfaked;
36761.1Skamil	info.psi_siginfo.si_code = sicodefaked;
36771.1Skamil
36781.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
36791.61Skre	SYSCALL_REQUIRE(
36801.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
36811.1Skamil
36821.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36831.61Skre	SYSCALL_REQUIRE(
36841.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36851.1Skamil
36861.13Schristos	DPRINTF("Before checking siginfo_t\n");
36871.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
36881.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
36891.1Skamil
36901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36911.1Skamil	    "without signal to be sent\n");
36921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
36931.1Skamil
36941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36961.1Skamil
36971.1Skamil	validate_status_exited(status, exitval);
36981.1Skamil
36991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37001.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37011.1Skamil}
37021.1Skamil
37031.1SkamilATF_TC(siginfo4);
37041.1SkamilATF_TC_HEAD(siginfo4, tc)
37051.1Skamil{
37061.1Skamil	atf_tc_set_md_var(tc, "descr",
37071.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
37081.1Skamil}
37091.1Skamil
37101.1SkamilATF_TC_BODY(siginfo4, tc)
37111.1Skamil{
37121.1Skamil	const int sigval = SIGTRAP;
37131.1Skamil	pid_t child, wpid;
37141.1Skamil#if defined(TWAIT_HAVE_STATUS)
37151.1Skamil	int status;
37161.1Skamil#endif
37171.1Skamil
37181.1Skamil	struct ptrace_siginfo info;
37191.1Skamil	memset(&info, 0, sizeof(info));
37201.1Skamil
37211.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37221.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37231.1Skamil	if (child == 0) {
37241.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37251.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37261.1Skamil
37271.13Schristos		DPRINTF("Before calling execve(2) from child\n");
37281.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
37291.1Skamil
37301.1Skamil		FORKEE_ASSERT(0 && "Not reached");
37311.1Skamil	}
37321.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37331.1Skamil
37341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37361.1Skamil
37371.1Skamil	validate_status_stopped(status, sigval);
37381.1Skamil
37391.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37401.61Skre	SYSCALL_REQUIRE(
37411.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37421.1Skamil
37431.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37441.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
37451.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37461.1Skamil	    info.psi_siginfo.si_errno);
37471.1Skamil
37481.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
37491.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
37501.1Skamil
37511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37521.1Skamil	    "without signal to be sent\n");
37531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37541.1Skamil
37551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37571.1Skamil
37581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37601.1Skamil}
37611.1Skamil
37621.1Skamil#if defined(TWAIT_HAVE_PID)
37631.1SkamilATF_TC(siginfo5);
37641.1SkamilATF_TC_HEAD(siginfo5, tc)
37651.1Skamil{
37661.1Skamil	atf_tc_set_md_var(tc, "descr",
37671.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
37681.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
37691.1Skamil}
37701.1Skamil
37711.1SkamilATF_TC_BODY(siginfo5, tc)
37721.1Skamil{
37731.1Skamil	const int exitval = 5;
37741.1Skamil	const int exitval2 = 15;
37751.1Skamil	const int sigval = SIGSTOP;
37761.1Skamil	pid_t child, child2, wpid;
37771.1Skamil#if defined(TWAIT_HAVE_STATUS)
37781.1Skamil	int status;
37791.1Skamil#endif
37801.1Skamil	ptrace_state_t state;
37811.1Skamil	const int slen = sizeof(state);
37821.1Skamil	ptrace_event_t event;
37831.1Skamil	const int elen = sizeof(event);
37841.1Skamil	struct ptrace_siginfo info;
37851.1Skamil
37861.1Skamil	memset(&info, 0, sizeof(info));
37871.1Skamil
37881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37901.1Skamil	if (child == 0) {
37911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37931.1Skamil
37941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37961.1Skamil
37971.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
37981.1Skamil
37991.1Skamil		if (child2 == 0)
38001.1Skamil			_exit(exitval2);
38011.1Skamil
38021.1Skamil		FORKEE_REQUIRE_SUCCESS
38031.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
38041.1Skamil
38051.1Skamil		forkee_status_exited(status, exitval2);
38061.1Skamil
38071.13Schristos		DPRINTF("Before exiting of the child process\n");
38081.1Skamil		_exit(exitval);
38091.1Skamil	}
38101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38111.1Skamil
38121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38141.1Skamil
38151.1Skamil	validate_status_stopped(status, sigval);
38161.1Skamil
38171.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38181.61Skre	SYSCALL_REQUIRE(
38191.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38201.1Skamil
38211.13Schristos	DPRINTF("Before checking siginfo_t\n");
38221.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
38231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38241.1Skamil
38251.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
38261.1Skamil	event.pe_set_event = PTRACE_FORK;
38271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
38281.1Skamil
38291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38301.1Skamil	    "without signal to be sent\n");
38311.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
38321.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
38331.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
38341.1Skamil                "state.pe_other_pid=child)\n", child);
38351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38361.1Skamil
38371.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
38381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38391.1Skamil
38401.1Skamil	validate_status_stopped(status, SIGTRAP);
38411.1Skamil
38421.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38431.61Skre	SYSCALL_REQUIRE(
38441.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38451.1Skamil
38461.13Schristos	DPRINTF("Before checking siginfo_t\n");
38471.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38481.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
38491.1Skamil
38501.61Skre	SYSCALL_REQUIRE(
38511.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
38521.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
38531.1Skamil
38541.1Skamil	child2 = state.pe_other_pid;
38551.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
38561.1Skamil
38571.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
38581.1Skamil	    TWAIT_FNAME, child2, child);
38591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
38601.1Skamil	    child2);
38611.1Skamil
38621.1Skamil	validate_status_stopped(status, SIGTRAP);
38631.1Skamil
38641.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38651.61Skre	SYSCALL_REQUIRE(
38661.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38671.1Skamil
38681.13Schristos	DPRINTF("Before checking siginfo_t\n");
38691.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38701.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
38711.1Skamil
38721.61Skre	SYSCALL_REQUIRE(
38731.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
38741.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
38751.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
38761.1Skamil
38771.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
38781.1Skamil	    "without signal to be sent\n");
38791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
38801.1Skamil
38811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38821.1Skamil	    "without signal to be sent\n");
38831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38841.1Skamil
38851.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
38861.1Skamil	    TWAIT_FNAME);
38871.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
38881.1Skamil	    child2);
38891.1Skamil
38901.1Skamil	validate_status_exited(status, exitval2);
38911.1Skamil
38921.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
38931.1Skamil	    TWAIT_FNAME);
38941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
38951.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
38961.1Skamil
38971.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
38981.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
38991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39001.1Skamil
39011.1Skamil	validate_status_stopped(status, SIGCHLD);
39021.1Skamil
39031.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39041.61Skre	SYSCALL_REQUIRE(
39051.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39061.1Skamil
39071.13Schristos	DPRINTF("Before checking siginfo_t\n");
39081.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
39091.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
39101.1Skamil
39111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39121.1Skamil	    "without signal to be sent\n");
39131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39141.1Skamil
39151.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
39161.1Skamil	    TWAIT_FNAME);
39171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39181.1Skamil
39191.1Skamil	validate_status_exited(status, exitval);
39201.1Skamil
39211.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
39221.1Skamil	    TWAIT_FNAME);
39231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39241.1Skamil}
39251.1Skamil#endif
39261.1Skamil
39271.1Skamil#if defined(PT_STEP)
39281.1SkamilATF_TC(siginfo6);
39291.1SkamilATF_TC_HEAD(siginfo6, tc)
39301.1Skamil{
39311.1Skamil	atf_tc_set_md_var(tc, "descr",
39321.1Skamil	    "Verify single PT_STEP call with signal information check");
39331.1Skamil}
39341.1Skamil
39351.1SkamilATF_TC_BODY(siginfo6, tc)
39361.1Skamil{
39371.1Skamil	const int exitval = 5;
39381.1Skamil	const int sigval = SIGSTOP;
39391.1Skamil	pid_t child, wpid;
39401.1Skamil#if defined(TWAIT_HAVE_STATUS)
39411.1Skamil	int status;
39421.1Skamil#endif
39431.1Skamil	int happy;
39441.1Skamil	struct ptrace_siginfo info;
39451.1Skamil
39461.1Skamil#if defined(__arm__)
39471.1Skamil	/* PT_STEP not supported on arm 32-bit */
39481.1Skamil	atf_tc_expect_fail("PR kern/52119");
39491.1Skamil#endif
39501.1Skamil
39511.1Skamil	memset(&info, 0, sizeof(info));
39521.1Skamil
39531.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39541.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39551.1Skamil	if (child == 0) {
39561.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39571.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39581.1Skamil
39591.1Skamil		happy = check_happy(100);
39601.1Skamil
39611.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39621.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39631.1Skamil
39641.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
39651.1Skamil
39661.13Schristos		DPRINTF("Before exiting of the child process\n");
39671.1Skamil		_exit(exitval);
39681.1Skamil	}
39691.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39701.1Skamil
39711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39731.1Skamil
39741.1Skamil	validate_status_stopped(status, sigval);
39751.1Skamil
39761.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39771.61Skre	SYSCALL_REQUIRE(
39781.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39791.1Skamil
39801.13Schristos	DPRINTF("Before checking siginfo_t\n");
39811.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
39821.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
39831.1Skamil
39841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39851.1Skamil	    "without signal to be sent (use PT_STEP)\n");
39861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
39871.1Skamil
39881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39901.1Skamil
39911.1Skamil	validate_status_stopped(status, SIGTRAP);
39921.1Skamil
39931.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39941.61Skre	SYSCALL_REQUIRE(
39951.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39961.1Skamil
39971.13Schristos	DPRINTF("Before checking siginfo_t\n");
39981.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
39991.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
40001.1Skamil
40011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40021.1Skamil	    "without signal to be sent\n");
40031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40041.1Skamil
40051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40071.1Skamil
40081.1Skamil	validate_status_exited(status, exitval);
40091.1Skamil
40101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40121.1Skamil}
40131.1Skamil#endif
40141.1Skamil
40151.1Skamilvolatile lwpid_t the_lwp_id = 0;
40161.1Skamil
40171.1Skamilstatic void
40181.1Skamillwp_main_func(void *arg)
40191.1Skamil{
40201.1Skamil	the_lwp_id = _lwp_self();
40211.1Skamil	_lwp_exit();
40221.1Skamil}
40231.1Skamil
40241.1SkamilATF_TC(lwp_create1);
40251.1SkamilATF_TC_HEAD(lwp_create1, tc)
40261.1Skamil{
40271.1Skamil	atf_tc_set_md_var(tc, "descr",
40281.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
40291.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
40301.1Skamil}
40311.1Skamil
40321.1SkamilATF_TC_BODY(lwp_create1, tc)
40331.1Skamil{
40341.1Skamil	const int exitval = 5;
40351.1Skamil	const int sigval = SIGSTOP;
40361.1Skamil	pid_t child, wpid;
40371.1Skamil#if defined(TWAIT_HAVE_STATUS)
40381.1Skamil	int status;
40391.1Skamil#endif
40401.1Skamil	ptrace_state_t state;
40411.1Skamil	const int slen = sizeof(state);
40421.1Skamil	ptrace_event_t event;
40431.1Skamil	const int elen = sizeof(event);
40441.1Skamil	ucontext_t uc;
40451.1Skamil	lwpid_t lid;
40461.1Skamil	static const size_t ssize = 16*1024;
40471.1Skamil	void *stack;
40481.1Skamil
40491.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40501.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40511.1Skamil	if (child == 0) {
40521.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40531.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40541.1Skamil
40551.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40561.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40571.1Skamil
40581.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
40591.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
40601.1Skamil
40611.13Schristos		DPRINTF("Before making context for new lwp in child\n");
40621.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
40631.1Skamil
40641.13Schristos		DPRINTF("Before creating new in child\n");
40651.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
40661.1Skamil
40671.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
40681.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
40691.1Skamil
40701.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
40711.1Skamil		    "are the same\n", lid, the_lwp_id);
40721.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
40731.1Skamil
40741.13Schristos		DPRINTF("Before exiting of the child process\n");
40751.1Skamil		_exit(exitval);
40761.1Skamil	}
40771.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40781.1Skamil
40791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40811.1Skamil
40821.1Skamil	validate_status_stopped(status, sigval);
40831.1Skamil
40841.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
40851.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
40861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
40871.1Skamil
40881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40891.1Skamil	    "without signal to be sent\n");
40901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40911.1Skamil
40921.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
40931.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
40941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40951.1Skamil
40961.1Skamil	validate_status_stopped(status, SIGTRAP);
40971.1Skamil
40981.61Skre	SYSCALL_REQUIRE(
40991.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41001.1Skamil
41011.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
41021.1Skamil
41031.1Skamil	lid = state.pe_lwp;
41041.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
41051.1Skamil
41061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41071.1Skamil	    "without signal to be sent\n");
41081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41091.1Skamil
41101.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
41111.1Skamil	    TWAIT_FNAME);
41121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41131.1Skamil
41141.1Skamil	validate_status_exited(status, exitval);
41151.1Skamil
41161.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
41171.1Skamil	    TWAIT_FNAME);
41181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41191.1Skamil}
41201.1Skamil
41211.1SkamilATF_TC(lwp_exit1);
41221.1SkamilATF_TC_HEAD(lwp_exit1, tc)
41231.1Skamil{
41241.1Skamil	atf_tc_set_md_var(tc, "descr",
41251.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
41261.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
41271.1Skamil}
41281.1Skamil
41291.1SkamilATF_TC_BODY(lwp_exit1, tc)
41301.1Skamil{
41311.1Skamil	const int exitval = 5;
41321.1Skamil	const int sigval = SIGSTOP;
41331.1Skamil	pid_t child, wpid;
41341.1Skamil#if defined(TWAIT_HAVE_STATUS)
41351.1Skamil	int status;
41361.1Skamil#endif
41371.1Skamil	ptrace_state_t state;
41381.1Skamil	const int slen = sizeof(state);
41391.1Skamil	ptrace_event_t event;
41401.1Skamil	const int elen = sizeof(event);
41411.1Skamil	ucontext_t uc;
41421.1Skamil	lwpid_t lid;
41431.1Skamil	static const size_t ssize = 16*1024;
41441.1Skamil	void *stack;
41451.1Skamil
41461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41481.1Skamil	if (child == 0) {
41491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41511.1Skamil
41521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41541.1Skamil
41551.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
41561.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
41571.1Skamil
41581.13Schristos		DPRINTF("Before making context for new lwp in child\n");
41591.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
41601.1Skamil
41611.13Schristos		DPRINTF("Before creating new in child\n");
41621.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
41631.1Skamil
41641.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
41651.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
41661.1Skamil
41671.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
41681.1Skamil		    "are the same\n", lid, the_lwp_id);
41691.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
41701.1Skamil
41711.13Schristos		DPRINTF("Before exiting of the child process\n");
41721.1Skamil		_exit(exitval);
41731.1Skamil	}
41741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41751.1Skamil
41761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41781.1Skamil
41791.1Skamil	validate_status_stopped(status, sigval);
41801.1Skamil
41811.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
41821.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
41831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
41841.1Skamil
41851.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41861.1Skamil	    "without signal to be sent\n");
41871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41881.1Skamil
41891.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
41901.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
41911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41921.1Skamil
41931.1Skamil	validate_status_stopped(status, SIGTRAP);
41941.1Skamil
41951.61Skre	SYSCALL_REQUIRE(
41961.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41971.1Skamil
41981.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
41991.1Skamil
42001.1Skamil	lid = state.pe_lwp;
42011.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
42021.1Skamil
42031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42041.1Skamil	    "without signal to be sent\n");
42051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42061.1Skamil
42071.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
42081.1Skamil	    TWAIT_FNAME);
42091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42101.1Skamil
42111.1Skamil	validate_status_exited(status, exitval);
42121.1Skamil
42131.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
42141.1Skamil	    TWAIT_FNAME);
42151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42161.1Skamil}
42171.1Skamil
42181.1SkamilATF_TC(signal1);
42191.1SkamilATF_TC_HEAD(signal1, tc)
42201.1Skamil{
42211.1Skamil	atf_tc_set_md_var(tc, "descr",
42221.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
42231.1Skamil	    "from catching other signals");
42241.1Skamil}
42251.1Skamil
42261.1SkamilATF_TC_BODY(signal1, tc)
42271.1Skamil{
42281.1Skamil	const int exitval = 5;
42291.1Skamil	const int sigval = SIGSTOP;
42301.1Skamil	const int sigmasked = SIGTRAP;
42311.1Skamil	const int signotmasked = SIGINT;
42321.1Skamil	pid_t child, wpid;
42331.1Skamil#if defined(TWAIT_HAVE_STATUS)
42341.1Skamil	int status;
42351.1Skamil#endif
42361.1Skamil	sigset_t intmask;
42371.1Skamil
42381.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42391.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42401.1Skamil	if (child == 0) {
42411.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42421.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42431.1Skamil
42441.1Skamil		sigemptyset(&intmask);
42451.1Skamil		sigaddset(&intmask, sigmasked);
42461.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42471.1Skamil
42481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42501.1Skamil
42511.13Schristos		DPRINTF("Before raising %s from child\n",
42521.1Skamil		    strsignal(signotmasked));
42531.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
42541.1Skamil
42551.13Schristos		DPRINTF("Before exiting of the child process\n");
42561.1Skamil		_exit(exitval);
42571.1Skamil	}
42581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42591.1Skamil
42601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42621.1Skamil
42631.1Skamil	validate_status_stopped(status, sigval);
42641.1Skamil
42651.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42661.1Skamil	    "without signal to be sent\n");
42671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42681.1Skamil
42691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42701.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42711.1Skamil
42721.1Skamil	validate_status_stopped(status, signotmasked);
42731.1Skamil
42741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42751.1Skamil	    "without signal to be sent\n");
42761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42771.1Skamil
42781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42801.1Skamil
42811.1Skamil	validate_status_exited(status, exitval);
42821.1Skamil
42831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42851.1Skamil}
42861.1Skamil
42871.1SkamilATF_TC(signal2);
42881.1SkamilATF_TC_HEAD(signal2, tc)
42891.1Skamil{
42901.1Skamil	atf_tc_set_md_var(tc, "descr",
42911.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
42921.1Skamil	    "catching this raised signal");
42931.1Skamil}
42941.1Skamil
42951.1SkamilATF_TC_BODY(signal2, tc)
42961.1Skamil{
42971.1Skamil	const int exitval = 5;
42981.1Skamil	const int sigval = SIGSTOP;
42991.1Skamil	const int sigmasked = SIGTRAP;
43001.1Skamil	pid_t child, wpid;
43011.1Skamil#if defined(TWAIT_HAVE_STATUS)
43021.1Skamil	int status;
43031.1Skamil#endif
43041.1Skamil	sigset_t intmask;
43051.1Skamil
43061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43081.1Skamil	if (child == 0) {
43091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43111.1Skamil
43121.1Skamil		sigemptyset(&intmask);
43131.1Skamil		sigaddset(&intmask, sigmasked);
43141.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43151.1Skamil
43161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43181.1Skamil
43191.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
43201.1Skamil		    strsignal(sigmasked));
43211.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
43221.1Skamil
43231.13Schristos		DPRINTF("Before exiting of the child process\n");
43241.1Skamil		_exit(exitval);
43251.1Skamil	}
43261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43271.1Skamil
43281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43301.1Skamil
43311.1Skamil	validate_status_stopped(status, sigval);
43321.1Skamil
43331.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43341.1Skamil	    "without signal to be sent\n");
43351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43361.1Skamil
43371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43391.1Skamil
43401.1Skamil	validate_status_exited(status, exitval);
43411.1Skamil
43421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43441.1Skamil}
43451.1Skamil
43461.1SkamilATF_TC(signal3);
43471.1SkamilATF_TC_HEAD(signal3, tc)
43481.1Skamil{
43491.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
43501.1Skamil	atf_tc_set_md_var(tc, "descr",
43511.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43521.1Skamil	    "catching software breakpoints");
43531.1Skamil}
43541.1Skamil
43551.1SkamilATF_TC_BODY(signal3, tc)
43561.1Skamil{
43571.1Skamil	const int exitval = 5;
43581.1Skamil	const int sigval = SIGSTOP;
43591.1Skamil	const int sigmasked = SIGTRAP;
43601.1Skamil	pid_t child, wpid;
43611.1Skamil#if defined(TWAIT_HAVE_STATUS)
43621.1Skamil	int status;
43631.1Skamil#endif
43641.1Skamil	sigset_t intmask;
43651.1Skamil
43661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43681.1Skamil	if (child == 0) {
43691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43711.1Skamil
43721.1Skamil		sigemptyset(&intmask);
43731.1Skamil		sigaddset(&intmask, sigmasked);
43741.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43751.1Skamil
43761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43781.1Skamil
43791.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
43801.52Skamil		trigger_trap();
43811.1Skamil
43821.13Schristos		DPRINTF("Before exiting of the child process\n");
43831.1Skamil		_exit(exitval);
43841.1Skamil	}
43851.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43861.1Skamil
43871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43891.1Skamil
43901.1Skamil	validate_status_stopped(status, sigval);
43911.1Skamil
43921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43931.1Skamil	    "without signal to be sent\n");
43941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43951.1Skamil
43961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43971.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43981.1Skamil
43991.1Skamil	validate_status_stopped(status, sigmasked);
44001.1Skamil
44011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44021.1Skamil	    "without signal to be sent\n");
44031.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
44041.1Skamil
44051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44071.1Skamil
44081.49Skamil	validate_status_signaled(status, SIGKILL, 0);
44091.1Skamil
44101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44121.1Skamil}
44131.1Skamil
44141.1Skamil#if defined(PT_STEP)
44151.1SkamilATF_TC(signal4);
44161.1SkamilATF_TC_HEAD(signal4, tc)
44171.1Skamil{
44181.1Skamil	atf_tc_set_md_var(tc, "descr",
44191.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44201.1Skamil	    "catching single step trap");
44211.1Skamil}
44221.1Skamil
44231.1SkamilATF_TC_BODY(signal4, tc)
44241.1Skamil{
44251.1Skamil	const int exitval = 5;
44261.1Skamil	const int sigval = SIGSTOP;
44271.1Skamil	const int sigmasked = SIGTRAP;
44281.1Skamil	pid_t child, wpid;
44291.1Skamil#if defined(TWAIT_HAVE_STATUS)
44301.1Skamil	int status;
44311.1Skamil#endif
44321.1Skamil	sigset_t intmask;
44331.1Skamil	int happy;
44341.1Skamil
44351.1Skamil#if defined(__arm__)
44361.5Skamil	/* PT_STEP not supported on arm 32-bit */
44371.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
44381.1Skamil#endif
44391.1Skamil
44401.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44411.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44421.1Skamil	if (child == 0) {
44431.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44441.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44451.1Skamil
44461.1Skamil		happy = check_happy(100);
44471.1Skamil
44481.1Skamil		sigemptyset(&intmask);
44491.1Skamil		sigaddset(&intmask, sigmasked);
44501.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44511.1Skamil
44521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44541.1Skamil
44551.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
44561.1Skamil
44571.13Schristos		DPRINTF("Before exiting of the child process\n");
44581.1Skamil		_exit(exitval);
44591.1Skamil	}
44601.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44611.1Skamil
44621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44641.1Skamil
44651.1Skamil	validate_status_stopped(status, sigval);
44661.1Skamil
44671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44681.1Skamil	    "without signal to be sent\n");
44691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
44701.1Skamil
44711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44731.1Skamil
44741.1Skamil	validate_status_stopped(status, sigmasked);
44751.1Skamil
44761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44771.1Skamil	    "without signal to be sent\n");
44781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44791.1Skamil
44801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44821.1Skamil
44831.1Skamil	validate_status_exited(status, exitval);
44841.1Skamil
44851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44871.1Skamil}
44881.1Skamil#endif
44891.1Skamil
44901.1SkamilATF_TC(signal5);
44911.1SkamilATF_TC_HEAD(signal5, tc)
44921.1Skamil{
44931.1Skamil	atf_tc_set_md_var(tc, "descr",
44941.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44951.1Skamil	    "catching exec() breakpoint");
44961.1Skamil}
44971.1Skamil
44981.1SkamilATF_TC_BODY(signal5, tc)
44991.1Skamil{
45001.1Skamil	const int sigval = SIGSTOP;
45011.1Skamil	const int sigmasked = SIGTRAP;
45021.1Skamil	pid_t child, wpid;
45031.1Skamil#if defined(TWAIT_HAVE_STATUS)
45041.1Skamil	int status;
45051.1Skamil#endif
45061.58Skamil	struct ptrace_siginfo info;
45071.1Skamil	sigset_t intmask;
45081.1Skamil
45091.58Skamil	memset(&info, 0, sizeof(info));
45101.14Schristos
45111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45131.1Skamil	if (child == 0) {
45141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45161.1Skamil
45171.1Skamil		sigemptyset(&intmask);
45181.1Skamil		sigaddset(&intmask, sigmasked);
45191.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45201.1Skamil
45211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45231.1Skamil
45241.13Schristos		DPRINTF("Before calling execve(2) from child\n");
45251.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
45261.1Skamil
45271.58Skamil		/* NOTREACHED */
45281.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
45291.1Skamil	}
45301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45311.1Skamil
45321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45341.1Skamil
45351.1Skamil	validate_status_stopped(status, sigval);
45361.1Skamil
45371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45381.1Skamil	    "without signal to be sent\n");
45391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45401.1Skamil
45411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45431.1Skamil
45441.1Skamil	validate_status_stopped(status, sigmasked);
45451.1Skamil
45461.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45471.61Skre	SYSCALL_REQUIRE(
45481.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45491.58Skamil
45501.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45511.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
45521.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45531.58Skamil	    info.psi_siginfo.si_errno);
45541.58Skamil
45551.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
45561.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
45571.58Skamil
45581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45591.1Skamil	    "without signal to be sent\n");
45601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45611.1Skamil
45621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45641.1Skamil
45651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45671.1Skamil}
45681.1Skamil
45691.1Skamil#if defined(TWAIT_HAVE_PID)
45701.1SkamilATF_TC(signal6);
45711.1SkamilATF_TC_HEAD(signal6, tc)
45721.1Skamil{
45731.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
45741.1Skamil	atf_tc_set_md_var(tc, "descr",
45751.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45761.1Skamil	    "catching PTRACE_FORK breakpoint");
45771.1Skamil}
45781.1Skamil
45791.1SkamilATF_TC_BODY(signal6, tc)
45801.1Skamil{
45811.1Skamil	const int exitval = 5;
45821.1Skamil	const int exitval2 = 15;
45831.1Skamil	const int sigval = SIGSTOP;
45841.1Skamil	const int sigmasked = SIGTRAP;
45851.1Skamil	pid_t child, child2, wpid;
45861.1Skamil#if defined(TWAIT_HAVE_STATUS)
45871.1Skamil	int status;
45881.1Skamil#endif
45891.1Skamil	sigset_t intmask;
45901.1Skamil	ptrace_state_t state;
45911.1Skamil	const int slen = sizeof(state);
45921.1Skamil	ptrace_event_t event;
45931.1Skamil	const int elen = sizeof(event);
45941.1Skamil
45951.38Skamil	atf_tc_expect_fail("PR kern/51918");
45961.14Schristos
45971.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45981.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45991.1Skamil	if (child == 0) {
46001.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46011.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46021.1Skamil
46031.1Skamil		sigemptyset(&intmask);
46041.1Skamil		sigaddset(&intmask, sigmasked);
46051.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46061.1Skamil
46071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46091.1Skamil
46101.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
46111.1Skamil
46121.1Skamil		if (child2 == 0)
46131.1Skamil			_exit(exitval2);
46141.1Skamil
46151.1Skamil		FORKEE_REQUIRE_SUCCESS
46161.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
46171.1Skamil
46181.1Skamil		forkee_status_exited(status, exitval2);
46191.1Skamil
46201.13Schristos		DPRINTF("Before exiting of the child process\n");
46211.1Skamil		_exit(exitval);
46221.1Skamil	}
46231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46241.1Skamil
46251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46271.1Skamil
46281.1Skamil	validate_status_stopped(status, sigval);
46291.1Skamil
46301.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
46311.1Skamil	event.pe_set_event = PTRACE_FORK;
46321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
46331.1Skamil
46341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46351.1Skamil	    "without signal to be sent\n");
46361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46371.1Skamil
46381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46401.1Skamil
46411.1Skamil	validate_status_stopped(status, sigmasked);
46421.1Skamil
46431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
46441.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46451.1Skamil
46461.1Skamil	child2 = state.pe_other_pid;
46471.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
46481.1Skamil
46491.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
46501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46511.1Skamil	    child2);
46521.1Skamil
46531.1Skamil	validate_status_stopped(status, SIGTRAP);
46541.1Skamil
46551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
46561.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46571.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
46581.1Skamil
46591.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
46601.1Skamil	    "without signal to be sent\n");
46611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
46621.1Skamil
46631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46641.1Skamil	    "without signal to be sent\n");
46651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46661.1Skamil
46671.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
46681.1Skamil	    TWAIT_FNAME);
46691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46701.57Skamil	    child2);
46711.1Skamil
46721.1Skamil	validate_status_exited(status, exitval2);
46731.1Skamil
46741.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
46751.1Skamil	    TWAIT_FNAME);
46761.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
46771.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
46781.1Skamil
46791.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
46801.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
46811.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46821.1Skamil
46831.1Skamil	validate_status_stopped(status, SIGCHLD);
46841.1Skamil
46851.57Skamil	DPRINTF("Before resuming the child process where it left off and "
46861.1Skamil	    "without signal to be sent\n");
46871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46881.1Skamil
46891.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
46901.1Skamil	    TWAIT_FNAME);
46911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46921.1Skamil
46931.1Skamil	validate_status_exited(status, exitval);
46941.1Skamil
46951.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
46961.57Skamil	    TWAIT_FNAME);
46971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
46981.1Skamil}
46991.1Skamil#endif
47001.1Skamil
47011.1Skamil#if defined(TWAIT_HAVE_PID)
47021.1SkamilATF_TC(signal7);
47031.1SkamilATF_TC_HEAD(signal7, tc)
47041.1Skamil{
47051.1Skamil	atf_tc_set_md_var(tc, "descr",
47061.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
47071.1Skamil	    "catching PTRACE_VFORK breakpoint");
47081.1Skamil}
47091.1Skamil
47101.1SkamilATF_TC_BODY(signal7, tc)
47111.1Skamil{
47121.1Skamil	const int exitval = 5;
47131.1Skamil	const int exitval2 = 15;
47141.1Skamil	const int sigval = SIGSTOP;
47151.1Skamil	const int sigmasked = SIGTRAP;
47161.1Skamil	pid_t child, child2, wpid;
47171.1Skamil#if defined(TWAIT_HAVE_STATUS)
47181.1Skamil	int status;
47191.1Skamil#endif
47201.1Skamil	sigset_t intmask;
47211.1Skamil	ptrace_state_t state;
47221.1Skamil	const int slen = sizeof(state);
47231.1Skamil	ptrace_event_t event;
47241.1Skamil	const int elen = sizeof(event);
47251.1Skamil
47261.38Skamil	atf_tc_expect_fail("PR kern/51918");
47271.14Schristos
47281.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47291.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47301.1Skamil	if (child == 0) {
47311.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47321.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47331.1Skamil
47341.1Skamil		sigemptyset(&intmask);
47351.1Skamil		sigaddset(&intmask, sigmasked);
47361.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
47371.1Skamil
47381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47401.1Skamil
47411.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
47421.1Skamil
47431.1Skamil		if (child2 == 0)
47441.1Skamil			_exit(exitval2);
47451.1Skamil
47461.1Skamil		FORKEE_REQUIRE_SUCCESS
47471.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
47481.1Skamil
47491.1Skamil		forkee_status_exited(status, exitval2);
47501.1Skamil
47511.13Schristos		DPRINTF("Before exiting of the child process\n");
47521.1Skamil		_exit(exitval);
47531.1Skamil	}
47541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47551.1Skamil
47561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47581.1Skamil
47591.1Skamil	validate_status_stopped(status, sigval);
47601.1Skamil
47611.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
47621.1Skamil	event.pe_set_event = PTRACE_VFORK;
47631.61Skre	SYSCALL_REQUIRE(
47641.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
47651.61Skre	    errno == ENOTSUP);
47661.1Skamil
47671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47681.1Skamil	    "without signal to be sent\n");
47691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47701.1Skamil
47711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47731.1Skamil
47741.1Skamil	validate_status_stopped(status, sigmasked);
47751.1Skamil
47761.61Skre	SYSCALL_REQUIRE(
47771.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
47781.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
47791.1Skamil
47801.1Skamil	child2 = state.pe_other_pid;
47811.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
47821.1Skamil
47831.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
47841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
47851.1Skamil	    child2);
47861.1Skamil
47871.1Skamil	validate_status_stopped(status, SIGTRAP);
47881.1Skamil
47891.61Skre	SYSCALL_REQUIRE(
47901.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
47911.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
47921.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
47931.1Skamil
47941.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
47951.1Skamil	    "without signal to be sent\n");
47961.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
47971.1Skamil
47981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47991.1Skamil	    "without signal to be sent\n");
48001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48011.1Skamil
48021.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
48031.1Skamil	    TWAIT_FNAME);
48041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
48051.57Skamil	    child2);
48061.1Skamil
48071.1Skamil	validate_status_exited(status, exitval2);
48081.1Skamil
48091.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
48101.1Skamil	    TWAIT_FNAME);
48111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
48121.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
48131.1Skamil
48141.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48151.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
48161.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48171.1Skamil
48181.1Skamil	validate_status_stopped(status, SIGCHLD);
48191.1Skamil
48201.57Skamil	DPRINTF("Before resuming the child process where it left off and "
48211.1Skamil	    "without signal to be sent\n");
48221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48231.1Skamil
48241.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48251.1Skamil	    TWAIT_FNAME);
48261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48271.1Skamil
48281.1Skamil	validate_status_exited(status, exitval);
48291.1Skamil
48301.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48311.57Skamil	    TWAIT_FNAME);
48321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48331.1Skamil}
48341.1Skamil#endif
48351.1Skamil
48361.1SkamilATF_TC(signal8);
48371.1SkamilATF_TC_HEAD(signal8, tc)
48381.1Skamil{
48391.1Skamil	atf_tc_set_md_var(tc, "descr",
48401.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
48411.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
48421.1Skamil}
48431.1Skamil
48441.1SkamilATF_TC_BODY(signal8, tc)
48451.1Skamil{
48461.1Skamil	const int exitval = 5;
48471.1Skamil	const int exitval2 = 15;
48481.1Skamil	const int sigval = SIGSTOP;
48491.1Skamil	const int sigmasked = SIGTRAP;
48501.1Skamil	pid_t child, child2, wpid;
48511.1Skamil#if defined(TWAIT_HAVE_STATUS)
48521.1Skamil	int status;
48531.1Skamil#endif
48541.1Skamil	sigset_t intmask;
48551.1Skamil	ptrace_state_t state;
48561.1Skamil	const int slen = sizeof(state);
48571.1Skamil	ptrace_event_t event;
48581.1Skamil	const int elen = sizeof(event);
48591.1Skamil
48601.14Schristos	atf_tc_expect_fail("PR kern/51918");
48611.14Schristos
48621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48641.1Skamil	if (child == 0) {
48651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48671.1Skamil
48681.1Skamil		sigemptyset(&intmask);
48691.1Skamil		sigaddset(&intmask, sigmasked);
48701.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
48711.1Skamil
48721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48741.1Skamil
48751.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
48761.1Skamil
48771.1Skamil		if (child2 == 0)
48781.1Skamil			_exit(exitval2);
48791.1Skamil
48801.1Skamil		FORKEE_REQUIRE_SUCCESS
48811.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
48821.1Skamil
48831.1Skamil		forkee_status_exited(status, exitval2);
48841.1Skamil
48851.13Schristos		DPRINTF("Before exiting of the child process\n");
48861.1Skamil		_exit(exitval);
48871.1Skamil	}
48881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48891.1Skamil
48901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48921.1Skamil
48931.1Skamil	validate_status_stopped(status, sigval);
48941.1Skamil
48951.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
48961.1Skamil	    child);
48971.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
48981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
48991.1Skamil
49001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49011.1Skamil	    "without signal to be sent\n");
49021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49031.1Skamil
49041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49061.1Skamil
49071.1Skamil	validate_status_stopped(status, sigmasked);
49081.1Skamil
49091.61Skre	SYSCALL_REQUIRE(
49101.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
49111.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
49121.1Skamil
49131.1Skamil	child2 = state.pe_other_pid;
49141.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
49151.1Skamil
49161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49171.1Skamil	    "without signal to be sent\n");
49181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49191.1Skamil
49201.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49211.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
49221.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49231.1Skamil
49241.1Skamil	validate_status_stopped(status, SIGCHLD);
49251.1Skamil
49261.57Skamil	DPRINTF("Before resuming the child process where it left off and "
49271.1Skamil	    "without signal to be sent\n");
49281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49291.1Skamil
49301.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49311.1Skamil	    TWAIT_FNAME);
49321.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49331.1Skamil
49341.1Skamil	validate_status_exited(status, exitval);
49351.1Skamil
49361.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49371.57Skamil	    TWAIT_FNAME);
49381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49391.1Skamil}
49401.1Skamil
49411.1SkamilATF_TC(signal9);
49421.1SkamilATF_TC_HEAD(signal9, tc)
49431.1Skamil{
49441.1Skamil	atf_tc_set_md_var(tc, "descr",
49451.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
49461.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
49471.1Skamil}
49481.1Skamil
49491.1SkamilATF_TC_BODY(signal9, tc)
49501.1Skamil{
49511.1Skamil	const int exitval = 5;
49521.1Skamil	const int sigval = SIGSTOP;
49531.1Skamil	const int sigmasked = SIGTRAP;
49541.1Skamil	pid_t child, wpid;
49551.1Skamil#if defined(TWAIT_HAVE_STATUS)
49561.1Skamil	int status;
49571.1Skamil#endif
49581.1Skamil	sigset_t intmask;
49591.1Skamil	ptrace_state_t state;
49601.1Skamil	const int slen = sizeof(state);
49611.1Skamil	ptrace_event_t event;
49621.1Skamil	const int elen = sizeof(event);
49631.1Skamil	ucontext_t uc;
49641.1Skamil	lwpid_t lid;
49651.1Skamil	static const size_t ssize = 16*1024;
49661.1Skamil	void *stack;
49671.1Skamil
49681.14Schristos	atf_tc_expect_fail("PR kern/51918");
49691.14Schristos
49701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49721.1Skamil	if (child == 0) {
49731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49751.1Skamil
49761.1Skamil		sigemptyset(&intmask);
49771.1Skamil		sigaddset(&intmask, sigmasked);
49781.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
49791.1Skamil
49801.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49811.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49821.1Skamil
49831.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
49841.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
49851.1Skamil
49861.13Schristos		DPRINTF("Before making context for new lwp in child\n");
49871.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
49881.1Skamil
49891.13Schristos		DPRINTF("Before creating new in child\n");
49901.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
49911.1Skamil
49921.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
49931.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
49941.1Skamil
49951.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
49961.1Skamil		    "are the same\n", lid, the_lwp_id);
49971.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
49981.1Skamil
49991.13Schristos		DPRINTF("Before exiting of the child process\n");
50001.1Skamil		_exit(exitval);
50011.1Skamil	}
50021.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50031.1Skamil
50041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50061.1Skamil
50071.1Skamil	validate_status_stopped(status, sigval);
50081.1Skamil
50091.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
50101.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
50111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50121.1Skamil
50131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50141.1Skamil	    "without signal to be sent\n");
50151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50161.1Skamil
50171.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50181.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
50191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50201.1Skamil
50211.1Skamil	validate_status_stopped(status, sigmasked);
50221.1Skamil
50231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50241.1Skamil
50251.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
50261.1Skamil
50271.1Skamil	lid = state.pe_lwp;
50281.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
50291.1Skamil
50301.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50311.1Skamil	    "without signal to be sent\n");
50321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50331.1Skamil
50341.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50351.1Skamil	    TWAIT_FNAME);
50361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50371.1Skamil
50381.1Skamil	validate_status_exited(status, exitval);
50391.1Skamil
50401.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
50411.1Skamil	    TWAIT_FNAME);
50421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50431.1Skamil}
50441.1Skamil
50451.1SkamilATF_TC(signal10);
50461.1SkamilATF_TC_HEAD(signal10, tc)
50471.1Skamil{
50481.1Skamil	atf_tc_set_md_var(tc, "descr",
50491.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
50501.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
50511.1Skamil}
50521.1Skamil
50531.1SkamilATF_TC_BODY(signal10, tc)
50541.1Skamil{
50551.1Skamil	const int exitval = 5;
50561.1Skamil	const int sigval = SIGSTOP;
50571.1Skamil	const int sigmasked = SIGTRAP;
50581.1Skamil	pid_t child, wpid;
50591.1Skamil#if defined(TWAIT_HAVE_STATUS)
50601.1Skamil	int status;
50611.1Skamil#endif
50621.1Skamil	sigset_t intmask;
50631.1Skamil	ptrace_state_t state;
50641.1Skamil	const int slen = sizeof(state);
50651.1Skamil	ptrace_event_t event;
50661.1Skamil	const int elen = sizeof(event);
50671.1Skamil	ucontext_t uc;
50681.1Skamil	lwpid_t lid;
50691.1Skamil	static const size_t ssize = 16*1024;
50701.1Skamil	void *stack;
50711.1Skamil
50721.14Schristos	atf_tc_expect_fail("PR kern/51918");
50731.14Schristos
50741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50761.1Skamil	if (child == 0) {
50771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50791.1Skamil
50801.1Skamil		sigemptyset(&intmask);
50811.1Skamil		sigaddset(&intmask, sigmasked);
50821.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
50831.1Skamil
50841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50861.1Skamil
50871.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
50881.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
50891.1Skamil
50901.13Schristos		DPRINTF("Before making context for new lwp in child\n");
50911.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
50921.1Skamil
50931.13Schristos		DPRINTF("Before creating new in child\n");
50941.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
50951.1Skamil
50961.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
50971.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
50981.1Skamil
50991.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
51001.1Skamil		    "are the same\n", lid, the_lwp_id);
51011.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
51021.1Skamil
51031.13Schristos		DPRINTF("Before exiting of the child process\n");
51041.1Skamil		_exit(exitval);
51051.1Skamil	}
51061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51071.1Skamil
51081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51101.1Skamil
51111.1Skamil	validate_status_stopped(status, sigval);
51121.1Skamil
51131.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
51141.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
51151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
51161.1Skamil
51171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51181.1Skamil	    "without signal to be sent\n");
51191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51201.1Skamil
51211.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
51221.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
51231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51241.1Skamil
51251.1Skamil	validate_status_stopped(status, sigmasked);
51261.1Skamil
51271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51281.1Skamil
51291.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
51301.1Skamil
51311.1Skamil	lid = state.pe_lwp;
51321.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
51331.1Skamil
51341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51351.1Skamil	    "without signal to be sent\n");
51361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51371.1Skamil
51381.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51391.1Skamil	    TWAIT_FNAME);
51401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51411.1Skamil
51421.1Skamil	validate_status_exited(status, exitval);
51431.1Skamil
51441.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51451.1Skamil	    TWAIT_FNAME);
51461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51471.1Skamil}
51481.1Skamil
51491.1Skamilstatic void
51501.1Skamillwp_main_stop(void *arg)
51511.1Skamil{
51521.1Skamil	the_lwp_id = _lwp_self();
51531.1Skamil
51541.1Skamil	raise(SIGTRAP);
51551.1Skamil
51561.1Skamil	_lwp_exit();
51571.1Skamil}
51581.1Skamil
51591.1SkamilATF_TC(suspend1);
51601.1SkamilATF_TC_HEAD(suspend1, tc)
51611.1Skamil{
51621.1Skamil	atf_tc_set_md_var(tc, "descr",
51631.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
51641.1Skamil	    "resumed by a tracee");
51651.1Skamil}
51661.1Skamil
51671.1SkamilATF_TC_BODY(suspend1, tc)
51681.1Skamil{
51691.1Skamil	const int exitval = 5;
51701.1Skamil	const int sigval = SIGSTOP;
51711.1Skamil	pid_t child, wpid;
51721.1Skamil#if defined(TWAIT_HAVE_STATUS)
51731.1Skamil	int status;
51741.1Skamil#endif
51751.1Skamil	ucontext_t uc;
51761.1Skamil	lwpid_t lid;
51771.1Skamil	static const size_t ssize = 16*1024;
51781.1Skamil	void *stack;
51791.1Skamil	struct ptrace_lwpinfo pl;
51801.1Skamil	struct ptrace_siginfo psi;
51811.1Skamil	volatile int go = 0;
51821.1Skamil
51831.17Skamil	// Feature pending for refactoring
51841.17Skamil	atf_tc_expect_fail("PR kern/51995");
51851.17Skamil
51861.16Skamil	// Hangs with qemu
51871.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
51881.16Skamil
51891.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51901.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51911.1Skamil	if (child == 0) {
51921.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51931.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51941.1Skamil
51951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51971.1Skamil
51981.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
51991.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
52001.1Skamil
52011.13Schristos		DPRINTF("Before making context for new lwp in child\n");
52021.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
52031.1Skamil
52041.13Schristos		DPRINTF("Before creating new in child\n");
52051.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
52061.1Skamil
52071.1Skamil		while (go == 0)
52081.1Skamil			continue;
52091.1Skamil
52101.1Skamil		raise(SIGINT);
52111.1Skamil
52121.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
52131.1Skamil
52141.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
52151.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
52161.1Skamil
52171.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
52181.1Skamil		    "are the same\n", lid, the_lwp_id);
52191.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
52201.1Skamil
52211.13Schristos		DPRINTF("Before exiting of the child process\n");
52221.1Skamil		_exit(exitval);
52231.1Skamil	}
52241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52251.1Skamil
52261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52281.1Skamil
52291.1Skamil	validate_status_stopped(status, sigval);
52301.1Skamil
52311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52321.1Skamil	    "without signal to be sent\n");
52331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52341.1Skamil
52351.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52361.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
52371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52381.1Skamil
52391.1Skamil	validate_status_stopped(status, SIGTRAP);
52401.1Skamil
52411.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
52421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
52431.1Skamil
52441.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
52451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
52461.1Skamil
52471.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
52481.1Skamil	    child, getpid());
52491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
52501.1Skamil
52511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52521.1Skamil	    "without signal to be sent\n");
52531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52541.1Skamil
52551.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52561.1Skamil	    "SIGINT\n", TWAIT_FNAME);
52571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52581.1Skamil
52591.1Skamil	validate_status_stopped(status, SIGINT);
52601.1Skamil
52611.1Skamil	pl.pl_lwpid = 0;
52621.1Skamil
52631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52641.1Skamil	while (pl.pl_lwpid != 0) {
52651.1Skamil
52661.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52671.1Skamil		switch (pl.pl_lwpid) {
52681.1Skamil		case 1:
52691.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
52701.1Skamil			break;
52711.1Skamil		case 2:
52721.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
52731.1Skamil			break;
52741.1Skamil		}
52751.1Skamil	}
52761.1Skamil
52771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52781.1Skamil	    "without signal to be sent\n");
52791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52801.1Skamil
52811.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
52821.1Skamil	    TWAIT_FNAME);
52831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52841.1Skamil
52851.1Skamil	validate_status_exited(status, exitval);
52861.1Skamil
52871.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
52881.1Skamil	    TWAIT_FNAME);
52891.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52901.1Skamil}
52911.1Skamil
52921.1SkamilATF_TC(suspend2);
52931.1SkamilATF_TC_HEAD(suspend2, tc)
52941.1Skamil{
52951.1Skamil	atf_tc_set_md_var(tc, "descr",
52961.1Skamil	    "Verify that the while the only thread within a process is "
52971.1Skamil	    "suspended, the whole process cannot be unstopped");
52981.1Skamil}
52991.1Skamil
53001.1SkamilATF_TC_BODY(suspend2, tc)
53011.1Skamil{
53021.1Skamil	const int exitval = 5;
53031.1Skamil	const int sigval = SIGSTOP;
53041.1Skamil	pid_t child, wpid;
53051.1Skamil#if defined(TWAIT_HAVE_STATUS)
53061.1Skamil	int status;
53071.1Skamil#endif
53081.1Skamil	struct ptrace_siginfo psi;
53091.1Skamil
53101.17Skamil	// Feature pending for refactoring
53111.17Skamil	atf_tc_expect_fail("PR kern/51995");
53121.17Skamil
53131.16Skamil	// Hangs with qemu
53141.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
53151.16Skamil
53161.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53171.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53181.1Skamil	if (child == 0) {
53191.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53201.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53211.1Skamil
53221.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53231.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53241.1Skamil
53251.13Schristos		DPRINTF("Before exiting of the child process\n");
53261.1Skamil		_exit(exitval);
53271.1Skamil	}
53281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53291.1Skamil
53301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53321.1Skamil
53331.1Skamil	validate_status_stopped(status, sigval);
53341.1Skamil
53351.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
53361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
53371.1Skamil
53381.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
53391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
53401.1Skamil
53411.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53421.1Skamil	    "without signal to be sent\n");
53431.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
53441.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
53451.1Skamil
53461.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
53471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
53481.1Skamil
53491.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53501.1Skamil	    "without signal to be sent\n");
53511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53521.1Skamil
53531.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53541.1Skamil	    TWAIT_FNAME);
53551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53561.1Skamil
53571.1Skamil	validate_status_exited(status, exitval);
53581.1Skamil
53591.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53601.1Skamil	    TWAIT_FNAME);
53611.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53621.1Skamil}
53631.1Skamil
53641.1SkamilATF_TC(resume1);
53651.1SkamilATF_TC_HEAD(resume1, tc)
53661.1Skamil{
53671.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
53681.1Skamil	atf_tc_set_md_var(tc, "descr",
53691.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
53701.1Skamil	    "resumed by the debugger");
53711.1Skamil}
53721.1Skamil
53731.1SkamilATF_TC_BODY(resume1, tc)
53741.1Skamil{
53751.1Skamil	struct msg_fds fds;
53761.1Skamil	const int exitval = 5;
53771.1Skamil	const int sigval = SIGSTOP;
53781.1Skamil	pid_t child, wpid;
53791.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
53801.1Skamil#if defined(TWAIT_HAVE_STATUS)
53811.1Skamil	int status;
53821.1Skamil#endif
53831.1Skamil	ucontext_t uc;
53841.1Skamil	lwpid_t lid;
53851.1Skamil	static const size_t ssize = 16*1024;
53861.1Skamil	void *stack;
53871.1Skamil	struct ptrace_lwpinfo pl;
53881.1Skamil	struct ptrace_siginfo psi;
53891.1Skamil
53901.17Skamil	// Feature pending for refactoring
53911.17Skamil	atf_tc_expect_fail("PR kern/51995");
53921.17Skamil
53931.15Schristos	// Hangs with qemu
53941.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
53951.1Skamil
53961.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
53971.1Skamil
53981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54001.1Skamil	if (child == 0) {
54011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54031.1Skamil
54041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54061.1Skamil
54071.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54081.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54091.1Skamil
54101.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54111.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
54121.1Skamil
54131.13Schristos		DPRINTF("Before creating new in child\n");
54141.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54151.1Skamil
54161.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
54171.1Skamil
54181.1Skamil		raise(SIGINT);
54191.1Skamil
54201.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54211.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54221.1Skamil
54231.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54241.1Skamil		    "are the same\n", lid, the_lwp_id);
54251.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54261.1Skamil
54271.13Schristos		DPRINTF("Before exiting of the child process\n");
54281.1Skamil		_exit(exitval);
54291.1Skamil	}
54301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54311.1Skamil
54321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54341.1Skamil
54351.1Skamil	validate_status_stopped(status, sigval);
54361.1Skamil
54371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54381.1Skamil	    "without signal to be sent\n");
54391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54401.1Skamil
54411.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54421.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54441.1Skamil
54451.1Skamil	validate_status_stopped(status, SIGTRAP);
54461.1Skamil
54471.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
54481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
54491.1Skamil
54501.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
54511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
54521.1Skamil
54531.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
54541.1Skamil
54551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54561.1Skamil	    "without signal to be sent\n");
54571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54581.1Skamil
54591.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54601.1Skamil	    "SIGINT\n", TWAIT_FNAME);
54611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54621.1Skamil
54631.1Skamil	validate_status_stopped(status, SIGINT);
54641.1Skamil
54651.1Skamil	pl.pl_lwpid = 0;
54661.1Skamil
54671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54681.1Skamil	while (pl.pl_lwpid != 0) {
54691.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54701.1Skamil		switch (pl.pl_lwpid) {
54711.1Skamil		case 1:
54721.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
54731.1Skamil			break;
54741.1Skamil		case 2:
54751.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
54761.1Skamil			break;
54771.1Skamil		}
54781.1Skamil	}
54791.1Skamil
54801.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
54811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
54821.1Skamil
54831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54841.1Skamil	    "without signal to be sent\n");
54851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54861.1Skamil
54871.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54881.1Skamil	    TWAIT_FNAME);
54891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54901.1Skamil
54911.1Skamil	validate_status_exited(status, exitval);
54921.1Skamil
54931.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54941.1Skamil	    TWAIT_FNAME);
54951.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54961.1Skamil
54971.1Skamil	msg_close(&fds);
54981.1Skamil
54991.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
55001.1Skamil	sleep(10);
55011.1Skamil}
55021.1Skamil
55031.1SkamilATF_TC(syscall1);
55041.1SkamilATF_TC_HEAD(syscall1, tc)
55051.1Skamil{
55061.1Skamil	atf_tc_set_md_var(tc, "descr",
55071.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
55081.1Skamil}
55091.1Skamil
55101.1SkamilATF_TC_BODY(syscall1, tc)
55111.1Skamil{
55121.1Skamil	const int exitval = 5;
55131.1Skamil	const int sigval = SIGSTOP;
55141.1Skamil	pid_t child, wpid;
55151.1Skamil#if defined(TWAIT_HAVE_STATUS)
55161.1Skamil	int status;
55171.1Skamil#endif
55181.1Skamil	struct ptrace_siginfo info;
55191.1Skamil	memset(&info, 0, sizeof(info));
55201.1Skamil
55211.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55221.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55231.1Skamil	if (child == 0) {
55241.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55251.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55261.1Skamil
55271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55291.1Skamil
55301.1Skamil		syscall(SYS_getpid);
55311.1Skamil
55321.13Schristos		DPRINTF("Before exiting of the child process\n");
55331.1Skamil		_exit(exitval);
55341.1Skamil	}
55351.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55361.1Skamil
55371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55391.1Skamil
55401.1Skamil	validate_status_stopped(status, sigval);
55411.1Skamil
55421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55431.1Skamil	    "without signal to be sent\n");
55441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55451.1Skamil
55461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55481.1Skamil
55491.1Skamil	validate_status_stopped(status, SIGTRAP);
55501.1Skamil
55511.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55531.1Skamil
55541.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55551.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55561.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55571.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
55581.1Skamil
55591.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55601.1Skamil	    "without signal to be sent\n");
55611.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55621.1Skamil
55631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55651.1Skamil
55661.1Skamil	validate_status_stopped(status, SIGTRAP);
55671.1Skamil
55681.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55701.1Skamil
55711.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55721.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55731.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55741.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
55751.1Skamil
55761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55771.1Skamil	    "without signal to be sent\n");
55781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55791.1Skamil
55801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55821.1Skamil
55831.1Skamil	validate_status_exited(status, exitval);
55841.1Skamil
55851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55861.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55871.1Skamil}
55881.1Skamil
55891.1SkamilATF_TC(syscallemu1);
55901.1SkamilATF_TC_HEAD(syscallemu1, tc)
55911.1Skamil{
55921.1Skamil	atf_tc_set_md_var(tc, "descr",
55931.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
55941.1Skamil}
55951.1Skamil
55961.1SkamilATF_TC_BODY(syscallemu1, tc)
55971.1Skamil{
55981.1Skamil	const int exitval = 5;
55991.1Skamil	const int sigval = SIGSTOP;
56001.1Skamil	pid_t child, wpid;
56011.1Skamil#if defined(TWAIT_HAVE_STATUS)
56021.1Skamil	int status;
56031.1Skamil#endif
56041.1Skamil
56051.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
56061.6Skamil	/* syscallemu does not work on sparc (32-bit) */
56071.6Skamil	atf_tc_expect_fail("PR kern/52166");
56081.6Skamil#endif
56091.6Skamil
56101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56121.1Skamil	if (child == 0) {
56131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56151.1Skamil
56161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56181.1Skamil
56191.1Skamil		syscall(SYS_exit, 100);
56201.1Skamil
56211.13Schristos		DPRINTF("Before exiting of the child process\n");
56221.1Skamil		_exit(exitval);
56231.1Skamil	}
56241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56251.1Skamil
56261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56281.1Skamil
56291.1Skamil	validate_status_stopped(status, sigval);
56301.1Skamil
56311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56321.1Skamil	    "without signal to be sent\n");
56331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
56341.1Skamil
56351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56371.1Skamil
56381.1Skamil	validate_status_stopped(status, SIGTRAP);
56391.1Skamil
56401.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
56411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
56421.1Skamil
56431.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56441.1Skamil	    "without signal to be sent\n");
56451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
56461.1Skamil
56471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56491.1Skamil
56501.1Skamil	validate_status_stopped(status, SIGTRAP);
56511.1Skamil
56521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56531.1Skamil	    "without signal to be sent\n");
56541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56551.1Skamil
56561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56581.1Skamil
56591.1Skamil	validate_status_exited(status, exitval);
56601.1Skamil
56611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56631.1Skamil}
56641.1Skamil
56651.1Skamil#include "t_ptrace_amd64_wait.h"
56661.1Skamil#include "t_ptrace_i386_wait.h"
56671.1Skamil#include "t_ptrace_x86_wait.h"
56681.1Skamil
56691.1SkamilATF_TP_ADD_TCS(tp)
56701.1Skamil{
56711.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
56721.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
56731.33Skamil
56741.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
56751.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
56761.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
56771.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
56781.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
56791.33Skamil
56801.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
56811.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
56821.59Skamil//	ATF_TP_ADD_TC(tp, traceme_crash_ill);
56831.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
56841.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
56851.59Skamil
56861.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
56871.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
56881.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
56891.50Skamil
56901.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
56911.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
56921.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
56931.50Skamil
56941.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
56951.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
56961.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
56971.50Skamil
56981.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
56991.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
57001.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
57011.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
57021.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
57031.1Skamil
57041.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
57051.37Skamil
57061.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
57071.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
57081.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
57091.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
57101.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
57111.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
57121.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
57131.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
57141.40Skamil
57151.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
57161.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
57171.52Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
57181.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
57191.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
57201.41Skamil
57211.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
57221.43Skamil
57231.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
57241.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
57251.59Skamil//	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
57261.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
57271.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
57281.59Skamil
57291.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
57301.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
57311.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
57321.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
57331.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
57341.51Skamil
57351.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
57361.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
57371.51Skamil
57381.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
57391.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
57401.51Skamil
57411.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57421.51Skamil		tracee_sees_its_original_parent_getppid);
57431.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57441.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
57451.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57461.51Skamil		tracee_sees_its_original_parent_procfs_status);
57471.1Skamil
57481.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
57491.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
57501.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
57511.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
57521.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
57531.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
57541.1Skamil
57551.31Skamil	ATF_TP_ADD_TC(tp, fork1);
57561.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
57571.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
57581.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
57591.31Skamil	ATF_TP_ADD_TC(tp, fork5);
57601.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
57611.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
57621.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
57631.31Skamil
57641.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
57651.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
57661.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
57671.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
57681.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
57691.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
57701.64Smartin// thes tests hang on SMP machines, disable them for now
57711.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
57721.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
57731.1Skamil
57741.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
57751.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
57761.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
57771.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
57781.54Skamil
57791.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
57801.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
57811.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
57821.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
57831.54Skamil
57841.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
57851.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
57861.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
57871.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
57881.54Skamil
57891.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
57901.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
57911.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
57921.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
57931.54Skamil
57941.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
57951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
57961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
57971.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
57981.54Skamil
57991.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
58001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
58011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
58021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
58031.54Skamil
58041.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
58051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
58061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
58071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
58081.54Skamil
58091.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
58101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
58111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
58121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
58131.54Skamil
58141.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
58151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
58161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
58171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
58181.54Skamil
58191.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
58201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
58211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
58221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
58231.1Skamil
58241.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
58251.1Skamil
58261.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
58271.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
58281.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
58291.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
58301.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
58311.1Skamil
58321.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
58331.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
58341.1Skamil
58351.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
58361.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
58371.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
58381.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
58391.1Skamil
58401.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
58411.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
58421.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
58431.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
58441.2Skamil
58451.1Skamil	ATF_TP_ADD_TC(tp, kill1);
58461.1Skamil	ATF_TP_ADD_TC(tp, kill2);
58471.1Skamil
58481.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
58491.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
58501.1Skamil
58511.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
58521.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
58531.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
58541.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
58551.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
58561.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
58571.1Skamil
58581.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
58591.1Skamil
58601.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
58611.1Skamil
58621.1Skamil	ATF_TP_ADD_TC(tp, signal1);
58631.1Skamil	ATF_TP_ADD_TC(tp, signal2);
58641.1Skamil	ATF_TP_ADD_TC(tp, signal3);
58651.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
58661.1Skamil	ATF_TP_ADD_TC(tp, signal5);
58671.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
58681.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
58691.1Skamil	ATF_TP_ADD_TC(tp, signal8);
58701.1Skamil	ATF_TP_ADD_TC(tp, signal9);
58711.1Skamil	ATF_TP_ADD_TC(tp, signal10);
58721.1Skamil
58731.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
58741.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
58751.1Skamil
58761.1Skamil	ATF_TP_ADD_TC(tp, resume1);
58771.1Skamil
58781.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
58791.1Skamil
58801.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
58811.1Skamil
58821.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
58831.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
58841.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
58851.1Skamil
58861.1Skamil	return atf_no_error();
58871.1Skamil}
5888