t_ptrace_wait.c revision 1.71
11.71Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.71 2019/02/07 00:24:59 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.1Skamil * Copyright (c) 2016 The NetBSD Foundation, Inc.
51.1Skamil * All rights reserved.
61.1Skamil *
71.1Skamil * Redistribution and use in source and binary forms, with or without
81.1Skamil * modification, are permitted provided that the following conditions
91.1Skamil * are met:
101.1Skamil * 1. Redistributions of source code must retain the above copyright
111.1Skamil *    notice, this list of conditions and the following disclaimer.
121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil *    notice, this list of conditions and the following disclaimer in the
141.1Skamil *    documentation and/or other materials provided with the distribution.
151.1Skamil *
161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil * POSSIBILITY OF SUCH DAMAGE.
271.1Skamil */
281.1Skamil
291.1Skamil#include <sys/cdefs.h>
301.71Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.71 2019/02/07 00:24:59 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.1Skamil#include <sched.h>
471.1Skamil#include <signal.h>
481.1Skamil#include <stdint.h>
491.1Skamil#include <stdio.h>
501.1Skamil#include <stdlib.h>
511.1Skamil#include <strings.h>
521.26Skamil#include <time.h>
531.1Skamil#include <unistd.h>
541.1Skamil
551.1Skamil#include <atf-c.h>
561.1Skamil
571.1Skamil#include "h_macros.h"
581.1Skamil
591.1Skamil#include "t_ptrace_wait.h"
601.1Skamil#include "msg.h"
611.1Skamil
621.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
631.61Skre    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \
641.61Skre	sizeof(msg)) == 0)
651.1Skamil
661.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
671.61Skre    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \
681.61Skre	sizeof(msg)) == 0)
691.1Skamil
701.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
711.61Skre    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \
721.61Skre	sizeof(msg)) == 0)
731.1Skamil
741.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
751.61Skre    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \
761.61Skre	sizeof(msg)) == 0)
771.13Schristos
781.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
791.13Schristos    strerror(errno))
801.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
811.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
821.13Schristos
831.13Schristosstatic int debug = 0;
841.13Schristos
851.13Schristos#define DPRINTF(a, ...)	do  \
861.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
871.13Schristos    while (/*CONSTCOND*/0)
881.1Skamil
891.34Skamil/// ----------------------------------------------------------------------------
901.34Skamil
911.33Skamilstatic void
921.33Skamiltraceme_raise(int sigval)
931.1Skamil{
941.1Skamil	const int exitval = 5;
951.1Skamil	pid_t child, wpid;
961.1Skamil#if defined(TWAIT_HAVE_STATUS)
971.1Skamil	int status;
981.1Skamil#endif
991.1Skamil
1001.45Skamil	struct ptrace_siginfo info;
1011.45Skamil	memset(&info, 0, sizeof(info));
1021.45Skamil
1031.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1041.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1051.1Skamil	if (child == 0) {
1061.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1071.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1081.1Skamil
1091.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1101.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1111.1Skamil
1121.36Skamil		switch (sigval) {
1131.36Skamil		case SIGKILL:
1141.36Skamil			/* NOTREACHED */
1151.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1161.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.71Skamil#ifndef PTRACE_ILLEGAL_ASM
1941.71Skamil	if (sig == SIGILL)
1951.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
1961.71Skamil#endif
1971.71Skamil
1981.59Skamil	memset(&info, 0, sizeof(info));
1991.59Skamil
2001.59Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
2011.59Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
2021.59Skamil	if (child == 0) {
2031.59Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2041.59Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2051.59Skamil
2061.59Skamil		DPRINTF("Before executing a trap\n");
2071.59Skamil		switch (sig) {
2081.59Skamil		case SIGTRAP:
2091.59Skamil			trigger_trap();
2101.59Skamil			break;
2111.59Skamil		case SIGSEGV:
2121.59Skamil			trigger_segv();
2131.59Skamil			break;
2141.59Skamil		case SIGILL:
2151.59Skamil			trigger_ill();
2161.59Skamil			break;
2171.59Skamil		case SIGFPE:
2181.59Skamil			trigger_fpe();
2191.59Skamil			break;
2201.59Skamil		case SIGBUS:
2211.59Skamil			trigger_bus();
2221.59Skamil			break;
2231.59Skamil		default:
2241.59Skamil			/* NOTREACHED */
2251.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2261.59Skamil		}
2271.59Skamil
2281.59Skamil		/* NOTREACHED */
2291.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
2301.59Skamil	}
2311.59Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2321.59Skamil
2331.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2341.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2351.59Skamil
2361.59Skamil	validate_status_stopped(status, sig);
2371.59Skamil
2381.59Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child");
2391.61Skre	SYSCALL_REQUIRE(
2401.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
2411.59Skamil
2421.59Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
2431.59Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
2441.61Skre	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
2451.61Skre	    info.psi_siginfo.si_errno);
2461.59Skamil
2471.59Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
2481.59Skamil	switch (sig) {
2491.59Skamil	case SIGTRAP:
2501.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
2511.59Skamil		break;
2521.59Skamil	case SIGSEGV:
2531.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
2541.59Skamil		break;
2551.71Skamil	case SIGILL:
2561.71Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
2571.71Skamil		break;
2581.59Skamil	case SIGFPE:
2591.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
2601.59Skamil		break;
2611.59Skamil	case SIGBUS:
2621.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
2631.59Skamil		break;
2641.59Skamil	}
2651.59Skamil
2661.59Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
2671.59Skamil
2681.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2691.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2701.59Skamil
2711.59Skamil	validate_status_signaled(status, SIGKILL, 0);
2721.59Skamil
2731.59Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2741.59Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2751.59Skamil}
2761.59Skamil
2771.61Skre#define TRACEME_CRASH(test, sig)					\
2781.61SkreATF_TC(test);								\
2791.61SkreATF_TC_HEAD(test, tc)							\
2801.61Skre{									\
2811.61Skre	atf_tc_set_md_var(tc, "descr",					\
2821.61Skre	    "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \
2831.61Skre}									\
2841.61Skre									\
2851.61SkreATF_TC_BODY(test, tc)							\
2861.61Skre{									\
2871.61Skre									\
2881.61Skre	traceme_crash(sig);						\
2891.59Skamil}
2901.59Skamil
2911.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP)
2921.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV)
2931.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL)
2941.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE)
2951.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS)
2961.59Skamil
2971.59Skamil/// ----------------------------------------------------------------------------
2981.59Skamil
2991.59Skamilstatic void
3001.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught)
3011.1Skamil{
3021.1Skamil	const int exitval = 5;
3031.34Skamil	const int sigval = SIGSTOP;
3041.1Skamil	pid_t child, wpid;
3051.1Skamil	struct sigaction sa;
3061.1Skamil#if defined(TWAIT_HAVE_STATUS)
3071.1Skamil	int status;
3081.1Skamil#endif
3091.61Skre	struct ptrace_siginfo info;
3101.1Skamil
3111.45Skamil	memset(&info, 0, sizeof(info));
3121.45Skamil
3131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
3141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
3151.1Skamil	if (child == 0) {
3161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3181.1Skamil
3191.34Skamil		sa.sa_handler = sah;
3201.1Skamil		sa.sa_flags = SA_SIGINFO;
3211.1Skamil		sigemptyset(&sa.sa_mask);
3221.1Skamil
3231.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
3241.1Skamil
3251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
3271.1Skamil
3281.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
3291.1Skamil
3301.13Schristos		DPRINTF("Before exiting of the child process\n");
3311.1Skamil		_exit(exitval);
3321.1Skamil	}
3331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3341.1Skamil
3351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3371.1Skamil
3381.1Skamil	validate_status_stopped(status, sigval);
3391.1Skamil
3401.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3411.61Skre	SYSCALL_REQUIRE(
3421.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3431.45Skamil
3441.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3451.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3461.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3471.45Skamil	    info.psi_siginfo.si_errno);
3481.45Skamil
3491.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3501.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3511.45Skamil
3521.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
3531.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
3541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
3551.1Skamil
3561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3581.1Skamil
3591.1Skamil	validate_status_exited(status, exitval);
3601.1Skamil
3611.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
3621.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
3631.1Skamil}
3641.1Skamil
3651.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig)				\
3661.61SkreATF_TC(test);								\
3671.61SkreATF_TC_HEAD(test, tc)							\
3681.61Skre{									\
3691.61Skre	atf_tc_set_md_var(tc, "descr",					\
3701.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
3711.61Skre	    "handled correctly and caught by a signal handler");	\
3721.61Skre}									\
3731.61Skre									\
3741.61Skrestatic int test##_caught = 0;						\
3751.61Skre									\
3761.61Skrestatic void								\
3771.61Skretest##_sighandler(int arg)						\
3781.61Skre{									\
3791.61Skre	FORKEE_ASSERT_EQ(arg, sig);					\
3801.61Skre									\
3811.61Skre	++ test##_caught;						\
3821.61Skre}									\
3831.61Skre									\
3841.61SkreATF_TC_BODY(test, tc)							\
3851.61Skre{									\
3861.61Skre									\
3871.61Skre	traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \
3881.34Skamil}
3891.34Skamil
3901.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
3911.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */
3921.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP)  /* hangup */
3931.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */
3941.34Skamil
3951.34Skamil/// ----------------------------------------------------------------------------
3961.34Skamil
3971.35Skamilstatic void
3981.50Skamiltraceme_sendsignal_masked(int sigsent)
3991.50Skamil{
4001.50Skamil	const int exitval = 5;
4011.50Skamil	const int sigval = SIGSTOP;
4021.50Skamil	pid_t child, wpid;
4031.50Skamil	sigset_t set;
4041.50Skamil#if defined(TWAIT_HAVE_STATUS)
4051.50Skamil	int status;
4061.50Skamil#endif
4071.61Skre	struct ptrace_siginfo info;
4081.50Skamil
4091.50Skamil	memset(&info, 0, sizeof(info));
4101.50Skamil
4111.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4121.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4131.50Skamil	if (child == 0) {
4141.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4151.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4161.50Skamil
4171.50Skamil		sigemptyset(&set);
4181.50Skamil		sigaddset(&set, sigsent);
4191.50Skamil		FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
4201.50Skamil
4211.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4221.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4231.50Skamil
4241.50Skamil		_exit(exitval);
4251.50Skamil	}
4261.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4271.50Skamil
4281.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4291.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4301.50Skamil
4311.50Skamil	validate_status_stopped(status, sigval);
4321.50Skamil
4331.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
4341.61Skre	SYSCALL_REQUIRE(
4351.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
4361.50Skamil
4371.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
4381.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
4391.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
4401.50Skamil	    info.psi_siginfo.si_errno);
4411.50Skamil
4421.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
4431.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
4441.50Skamil
4451.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
4461.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
4471.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
4481.50Skamil
4491.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4501.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4511.50Skamil
4521.50Skamil	validate_status_exited(status, exitval);
4531.50Skamil
4541.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
4551.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4561.50Skamil}
4571.50Skamil
4581.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig)				\
4591.61SkreATF_TC(test);								\
4601.61SkreATF_TC_HEAD(test, tc)							\
4611.61Skre{									\
4621.61Skre	atf_tc_set_md_var(tc, "descr",					\
4631.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
4641.61Skre	    "handled correctly and the signal is masked by SIG_BLOCK");	\
4651.61Skre}									\
4661.61Skre									\
4671.61SkreATF_TC_BODY(test, tc)							\
4681.61Skre{									\
4691.61Skre									\
4701.61Skre	traceme_sendsignal_masked(sig);					\
4711.50Skamil}
4721.50Skamil
4731.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked.
4741.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */
4751.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP)  /* hangup */
4761.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */
4771.50Skamil
4781.50Skamil/// ----------------------------------------------------------------------------
4791.50Skamil
4801.50Skamilstatic void
4811.50Skamiltraceme_sendsignal_ignored(int sigsent)
4821.50Skamil{
4831.50Skamil	const int exitval = 5;
4841.50Skamil	const int sigval = SIGSTOP;
4851.50Skamil	pid_t child, wpid;
4861.50Skamil	struct sigaction sa;
4871.50Skamil#if defined(TWAIT_HAVE_STATUS)
4881.50Skamil	int status;
4891.50Skamil#endif
4901.61Skre	struct ptrace_siginfo info;
4911.50Skamil
4921.50Skamil	memset(&info, 0, sizeof(info));
4931.50Skamil
4941.50Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4951.50Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4961.50Skamil	if (child == 0) {
4971.50Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4981.61Skre
4991.50Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5001.50Skamil
5011.50Skamil		memset(&sa, 0, sizeof(sa));
5021.50Skamil		sa.sa_handler = SIG_IGN;
5031.50Skamil		sigemptyset(&sa.sa_mask);
5041.50Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
5051.50Skamil
5061.50Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5071.50Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5081.50Skamil
5091.50Skamil		_exit(exitval);
5101.50Skamil	}
5111.50Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5121.50Skamil
5131.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5141.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5151.50Skamil
5161.50Skamil	validate_status_stopped(status, sigval);
5171.50Skamil
5181.50Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5191.61Skre	SYSCALL_REQUIRE(
5201.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5211.50Skamil
5221.50Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5231.50Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5241.50Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5251.50Skamil	    info.psi_siginfo.si_errno);
5261.50Skamil
5271.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5281.50Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5291.50Skamil
5301.50Skamil	DPRINTF("Before resuming the child process where it left off and with "
5311.50Skamil	    "signal %s to be sent\n", strsignal(sigsent));
5321.50Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
5331.50Skamil
5341.50Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5351.50Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5361.50Skamil
5371.50Skamil	validate_status_exited(status, exitval);
5381.50Skamil
5391.50Skamil	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
5401.50Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
5411.50Skamil}
5421.50Skamil
5431.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig)				\
5441.61SkreATF_TC(test);								\
5451.61SkreATF_TC_HEAD(test, tc)							\
5461.61Skre{									\
5471.61Skre	atf_tc_set_md_var(tc, "descr",					\
5481.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
5491.61Skre	    "handled correctly and the signal is masked by SIG_IGN");	\
5501.61Skre}									\
5511.61Skre									\
5521.61SkreATF_TC_BODY(test, tc)							\
5531.61Skre{									\
5541.61Skre									\
5551.61Skre	traceme_sendsignal_ignored(sig);				\
5561.50Skamil}
5571.50Skamil
5581.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored.
5591.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */
5601.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP)  /* hangup */
5611.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */
5621.50Skamil
5631.50Skamil/// ----------------------------------------------------------------------------
5641.50Skamil
5651.50Skamilstatic void
5661.50Skamiltraceme_sendsignal_simple(int sigsent)
5671.1Skamil{
5681.35Skamil	const int sigval = SIGSTOP;
5691.35Skamil	int exitval = 0;
5701.1Skamil	pid_t child, wpid;
5711.1Skamil#if defined(TWAIT_HAVE_STATUS)
5721.1Skamil	int status;
5731.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
5741.1Skamil#endif
5751.61Skre	struct ptrace_siginfo info;
5761.1Skamil
5771.45Skamil	memset(&info, 0, sizeof(info));
5781.45Skamil
5791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
5801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
5811.1Skamil	if (child == 0) {
5821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
5831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
5841.1Skamil
5851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
5861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
5871.1Skamil
5881.35Skamil		switch (sigsent) {
5891.35Skamil		case SIGCONT:
5901.48Skamil		case SIGSTOP:
5911.35Skamil			_exit(exitval);
5921.35Skamil		default:
5931.35Skamil			/* NOTREACHED */
5941.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
5951.35Skamil		}
5961.1Skamil	}
5971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5981.1Skamil
5991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6011.1Skamil
6021.1Skamil	validate_status_stopped(status, sigval);
6031.1Skamil
6041.45Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
6051.61Skre	SYSCALL_REQUIRE(
6061.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6071.45Skamil
6081.45Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6091.45Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
6101.45Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6111.45Skamil	    info.psi_siginfo.si_errno);
6121.45Skamil
6131.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6141.45Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6151.45Skamil
6161.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
6171.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
6181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
6191.1Skamil
6201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6221.1Skamil
6231.35Skamil	switch (sigsent) {
6241.48Skamil	case SIGSTOP:
6251.48Skamil		validate_status_stopped(status, sigsent);
6261.48Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
6271.61Skre		    "child\n");
6281.48Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
6291.61Skre		    sizeof(info)) != -1);
6301.48Skamil
6311.48Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6321.48Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
6331.61Skre		    "si_errno=%#x\n",
6341.61Skre		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6351.61Skre		    info.psi_siginfo.si_errno);
6361.48Skamil
6371.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
6381.48Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
6391.48Skamil
6401.48Skamil		DPRINTF("Before resuming the child process where it left off "
6411.61Skre		    "and with signal %s to be sent\n", strsignal(sigsent));
6421.48Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6431.48Skamil
6441.48Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6451.48Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
6461.61Skre		    child);
6471.48Skamil		/* FALLTHROUGH */
6481.35Skamil	case SIGCONT:
6491.35Skamil		validate_status_exited(status, exitval);
6501.35Skamil		break;
6511.35Skamil	default:
6521.35Skamil		validate_status_signaled(status, sigsent, expect_core);
6531.35Skamil		break;
6541.35Skamil	}
6551.1Skamil
6561.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
6571.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6581.1Skamil}
6591.1Skamil
6601.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig)				\
6611.61SkreATF_TC(test);								\
6621.61SkreATF_TC_HEAD(test, tc)							\
6631.61Skre{									\
6641.61Skre	atf_tc_set_md_var(tc, "descr",					\
6651.61Skre	    "Verify that a signal " #sig " emitted by a tracer to a child is " \
6661.61Skre	    "handled correctly in a child without a signal handler");	\
6671.61Skre}									\
6681.61Skre									\
6691.61SkreATF_TC_BODY(test, tc)							\
6701.61Skre{									\
6711.61Skre									\
6721.61Skre	traceme_sendsignal_simple(sig);					\
6731.35Skamil}
6741.35Skamil
6751.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/
6761.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/
6771.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */
6781.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP)  /* hangup */
6791.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */
6801.35Skamil
6811.35Skamil/// ----------------------------------------------------------------------------
6821.35Skamil
6831.37SkamilATF_TC(traceme_pid1_parent);
6841.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
6851.37Skamil{
6861.37Skamil	atf_tc_set_md_var(tc, "descr",
6871.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
6881.37Skamil}
6891.37Skamil
6901.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
6911.37Skamil{
6921.37Skamil	struct msg_fds parent_child;
6931.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
6941.37Skamil	pid_t child1, child2, wpid;
6951.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6961.37Skamil#if defined(TWAIT_HAVE_STATUS)
6971.37Skamil	int status;
6981.37Skamil#endif
6991.37Skamil
7001.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
7011.37Skamil
7021.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7031.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
7041.37Skamil	if (child1 == 0) {
7051.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
7061.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
7071.37Skamil		if (child2 != 0) {
7081.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
7091.61Skre			    getpid(), child2);
7101.37Skamil			_exit(exitval_child1);
7111.37Skamil		}
7121.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
7131.37Skamil
7141.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
7151.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
7161.37Skamil
7171.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7181.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
7191.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
7201.37Skamil
7211.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
7221.37Skamil
7231.37Skamil		_exit(exitval_child2);
7241.37Skamil	}
7251.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
7261.37Skamil
7271.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7281.61Skre	TWAIT_REQUIRE_SUCCESS(
7291.61Skre	    wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1);
7301.37Skamil
7311.37Skamil	validate_status_exited(status, exitval_child1);
7321.37Skamil
7331.37Skamil	DPRINTF("Notify that child1 is dead\n");
7341.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
7351.37Skamil
7361.37Skamil	DPRINTF("Wait for exiting of child2\n");
7371.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
7381.37Skamil}
7391.37Skamil
7401.37Skamil/// ----------------------------------------------------------------------------
7411.37Skamil
7421.40Skamilstatic void
7431.40Skamiltraceme_vfork_raise(int sigval)
7441.40Skamil{
7451.46Skamil	const int exitval = 5, exitval_watcher = 10;
7461.46Skamil	pid_t child, parent, watcher, wpid;
7471.46Skamil	int rv;
7481.40Skamil#if defined(TWAIT_HAVE_STATUS)
7491.40Skamil	int status;
7501.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
7511.40Skamil#endif
7521.40Skamil
7531.46Skamil	/*
7541.46Skamil	 * Spawn a dedicated thread to watch for a stopped child and emit
7551.46Skamil	 * the SIGKILL signal to it.
7561.46Skamil	 *
7571.46Skamil	 * vfork(2) might clobber watcher, this means that it's safer and
7581.46Skamil	 * simpler to reparent this process to initproc and forget about it.
7591.46Skamil	 */
7601.46Skamil	if (sigval == SIGSTOP) {
7611.46Skamil		parent = getpid();
7621.46Skamil
7631.46Skamil		watcher = fork();
7641.46Skamil		ATF_REQUIRE(watcher != 1);
7651.46Skamil		if (watcher == 0) {
7661.46Skamil			/* Double fork(2) trick to reparent to initproc */
7671.46Skamil			watcher = fork();
7681.46Skamil			FORKEE_ASSERT_NEQ(watcher, -1);
7691.46Skamil			if (watcher != 0)
7701.46Skamil				_exit(exitval_watcher);
7711.46Skamil
7721.46Skamil			child = await_stopped_child(parent);
7731.46Skamil
7741.46Skamil			errno = 0;
7751.46Skamil			rv = kill(child, SIGKILL);
7761.46Skamil			FORKEE_ASSERT_EQ(rv, 0);
7771.46Skamil			FORKEE_ASSERT_EQ(errno, 0);
7781.46Skamil
7791.46Skamil			/* This exit value will be collected by initproc */
7801.46Skamil			_exit(0);
7811.46Skamil		}
7821.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7831.46Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0),
7841.61Skre		    watcher);
7851.46Skamil
7861.46Skamil		validate_status_exited(status, exitval_watcher);
7871.46Skamil
7881.46Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7891.61Skre		TWAIT_REQUIRE_FAILURE(ECHILD,
7901.61Skre		    wpid = TWAIT_GENERIC(watcher, &status, 0));
7911.46Skamil	}
7921.46Skamil
7931.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
7941.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
7951.40Skamil	if (child == 0) {
7961.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7971.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7981.40Skamil
7991.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8001.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
8011.40Skamil
8021.40Skamil		switch (sigval) {
8031.46Skamil		case SIGSTOP:
8041.40Skamil		case SIGKILL:
8051.40Skamil		case SIGABRT:
8061.40Skamil		case SIGHUP:
8071.40Skamil			/* NOTREACHED */
8081.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
8091.70Smrg			__unreachable();
8101.40Skamil		default:
8111.40Skamil			DPRINTF("Before exiting of the child process\n");
8121.40Skamil			_exit(exitval);
8131.40Skamil		}
8141.40Skamil	}
8151.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8161.40Skamil
8171.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8181.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8191.40Skamil
8201.40Skamil	switch (sigval) {
8211.40Skamil	case SIGKILL:
8221.40Skamil	case SIGABRT:
8231.40Skamil	case SIGHUP:
8241.40Skamil		validate_status_signaled(status, sigval, expect_core);
8251.40Skamil		break;
8261.40Skamil	case SIGSTOP:
8271.46Skamil		validate_status_signaled(status, SIGKILL, 0);
8281.46Skamil		break;
8291.40Skamil	case SIGCONT:
8301.47Skamil	case SIGTSTP:
8311.47Skamil	case SIGTTIN:
8321.47Skamil	case SIGTTOU:
8331.40Skamil		validate_status_exited(status, exitval);
8341.40Skamil		break;
8351.40Skamil	default:
8361.40Skamil		/* NOTREACHED */
8371.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
8381.40Skamil		break;
8391.40Skamil	}
8401.40Skamil
8411.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8421.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8431.40Skamil}
8441.40Skamil
8451.61Skre#define TRACEME_VFORK_RAISE(test, sig)					\
8461.61SkreATF_TC(test);								\
8471.61SkreATF_TC_HEAD(test, tc)							\
8481.61Skre{									\
8491.61Skre	atf_tc_set_md_var(tc, "descr",					\
8501.61Skre	    "Verify PT_TRACE_ME followed by raise of " #sig " in a "	\
8511.61Skre	    "vfork(2)ed child");					\
8521.61Skre}									\
8531.61Skre									\
8541.61SkreATF_TC_BODY(test, tc)							\
8551.61Skre{									\
8561.61Skre									\
8571.61Skre	traceme_vfork_raise(sig);					\
8581.40Skamil}
8591.40Skamil
8601.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
8611.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */
8621.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */
8631.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */
8641.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */
8651.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */
8661.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP)  /* hangup */
8671.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */
8681.40Skamil
8691.40Skamil/// ----------------------------------------------------------------------------
8701.40Skamil
8711.52Skamilstatic void
8721.52Skamiltraceme_vfork_crash(int sig)
8731.41Skamil{
8741.41Skamil	pid_t child, wpid;
8751.41Skamil#if defined(TWAIT_HAVE_STATUS)
8761.41Skamil	int status;
8771.41Skamil#endif
8781.41Skamil
8791.71Skamil#ifndef PTRACE_ILLEGAL_ASM
8801.71Skamil	if (sig == SIGILL)
8811.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
8821.71Skamil#endif
8831.71Skamil
8841.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8851.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
8861.41Skamil	if (child == 0) {
8871.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8881.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8891.41Skamil
8901.52Skamil		DPRINTF("Before executing a trap\n");
8911.52Skamil		switch (sig) {
8921.52Skamil		case SIGTRAP:
8931.52Skamil			trigger_trap();
8941.52Skamil			break;
8951.52Skamil		case SIGSEGV:
8961.52Skamil			trigger_segv();
8971.52Skamil			break;
8981.52Skamil		case SIGILL:
8991.52Skamil			trigger_ill();
9001.52Skamil			break;
9011.52Skamil		case SIGFPE:
9021.52Skamil			trigger_fpe();
9031.52Skamil			break;
9041.52Skamil		case SIGBUS:
9051.52Skamil			trigger_bus();
9061.52Skamil			break;
9071.52Skamil		default:
9081.52Skamil			/* NOTREACHED */
9091.52Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
9101.52Skamil		}
9111.41Skamil
9121.41Skamil		/* NOTREACHED */
9131.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
9141.41Skamil	}
9151.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9161.41Skamil
9171.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9181.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9191.41Skamil
9201.52Skamil	validate_status_signaled(status, sig, 1);
9211.41Skamil
9221.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9231.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9241.41Skamil}
9251.41Skamil
9261.61Skre#define TRACEME_VFORK_CRASH(test, sig)					\
9271.61SkreATF_TC(test);								\
9281.61SkreATF_TC_HEAD(test, tc)							\
9291.61Skre{									\
9301.61Skre	atf_tc_set_md_var(tc, "descr",					\
9311.61Skre	    "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \
9321.61Skre	    "vfork(2)ed child");					\
9331.61Skre}									\
9341.61Skre									\
9351.61SkreATF_TC_BODY(test, tc)							\
9361.61Skre{									\
9371.61Skre									\
9381.61Skre	traceme_vfork_crash(sig);					\
9391.52Skamil}
9401.52Skamil
9411.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP)
9421.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV)
9431.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL)
9441.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE)
9451.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS)
9461.52Skamil
9471.41Skamil/// ----------------------------------------------------------------------------
9481.41Skamil
9491.43SkamilATF_TC(traceme_vfork_exec);
9501.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc)
9511.43Skamil{
9521.43Skamil	atf_tc_set_md_var(tc, "descr",
9531.43Skamil	    "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child");
9541.43Skamil}
9551.43Skamil
9561.43SkamilATF_TC_BODY(traceme_vfork_exec, tc)
9571.43Skamil{
9581.43Skamil	const int sigval = SIGTRAP;
9591.43Skamil	pid_t child, wpid;
9601.43Skamil#if defined(TWAIT_HAVE_STATUS)
9611.43Skamil	int status;
9621.43Skamil#endif
9631.61Skre	struct ptrace_siginfo info;
9641.43Skamil
9651.43Skamil	memset(&info, 0, sizeof(info));
9661.43Skamil
9671.43Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
9681.43Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
9691.43Skamil	if (child == 0) {
9701.43Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
9711.43Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
9721.43Skamil
9731.43Skamil		DPRINTF("Before calling execve(2) from child\n");
9741.43Skamil		execlp("/bin/echo", "/bin/echo", NULL);
9751.43Skamil
9761.43Skamil		/* NOTREACHED */
9771.43Skamil		FORKEE_ASSERTX(0 && "Not reached");
9781.43Skamil	}
9791.43Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
9801.43Skamil
9811.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9821.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9831.43Skamil
9841.43Skamil	validate_status_stopped(status, sigval);
9851.43Skamil
9861.43Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
9871.61Skre	SYSCALL_REQUIRE(
9881.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
9891.43Skamil
9901.43Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9911.43Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
9921.43Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9931.43Skamil	    info.psi_siginfo.si_errno);
9941.43Skamil
9951.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9961.43Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
9971.43Skamil
9981.43Skamil	DPRINTF("Before resuming the child process where it left off and "
9991.43Skamil	    "without signal to be sent\n");
10001.43Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
10011.43Skamil
10021.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10031.43Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10041.43Skamil
10051.43Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10061.43Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
10071.43Skamil}
10081.43Skamil
10091.43Skamil/// ----------------------------------------------------------------------------
10101.43Skamil
10111.1Skamil#if defined(TWAIT_HAVE_PID)
10121.51Skamilstatic void
10131.59Skamilunrelated_tracer_sees_crash(int sig)
10141.59Skamil{
10151.59Skamil	struct msg_fds parent_tracee, parent_tracer;
10161.59Skamil	const int exitval = 10;
10171.59Skamil	pid_t tracee, tracer, wpid;
10181.59Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10191.59Skamil#if defined(TWAIT_HAVE_STATUS)
10201.59Skamil	int status;
10211.59Skamil#endif
10221.59Skamil	struct ptrace_siginfo info;
10231.61Skre
10241.71Skamil#ifndef PTRACE_ILLEGAL_ASM
10251.71Skamil	if (sig == SIGILL)
10261.71Skamil		atf_tc_skip("PTRACE_ILLEGAL_ASM not defined");
10271.71Skamil#endif
10281.71Skamil
10291.59Skamil	memset(&info, 0, sizeof(info));
10301.59Skamil
10311.59Skamil	DPRINTF("Spawn tracee\n");
10321.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
10331.59Skamil	tracee = atf_utils_fork();
10341.59Skamil	if (tracee == 0) {
10351.59Skamil		// Wait for parent to let us crash
10361.59Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
10371.61Skre
10381.59Skamil		DPRINTF("Before executing a trap\n");
10391.59Skamil		switch (sig) {
10401.59Skamil		case SIGTRAP:
10411.59Skamil			trigger_trap();
10421.59Skamil			break;
10431.59Skamil		case SIGSEGV:
10441.59Skamil			trigger_segv();
10451.59Skamil			break;
10461.59Skamil		case SIGILL:
10471.59Skamil			trigger_ill();
10481.59Skamil			break;
10491.59Skamil		case SIGFPE:
10501.59Skamil			trigger_fpe();
10511.59Skamil			break;
10521.59Skamil		case SIGBUS:
10531.59Skamil			trigger_bus();
10541.59Skamil			break;
10551.59Skamil		default:
10561.59Skamil			/* NOTREACHED */
10571.59Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
10581.59Skamil		}
10591.59Skamil
10601.59Skamil		/* NOTREACHED */
10611.59Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
10621.59Skamil	}
10631.59Skamil
10641.59Skamil	DPRINTF("Spawn debugger\n");
10651.59Skamil	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
10661.59Skamil	tracer = atf_utils_fork();
10671.59Skamil	if (tracer == 0) {
10681.59Skamil		/* Fork again and drop parent to reattach to PID 1 */
10691.59Skamil		tracer = atf_utils_fork();
10701.59Skamil		if (tracer != 0)
10711.61Skre			_exit(exitval);
10721.59Skamil
10731.59Skamil		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10741.59Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10751.59Skamil
10761.59Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10771.59Skamil		FORKEE_REQUIRE_SUCCESS(
10781.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10791.59Skamil
10801.59Skamil		forkee_status_stopped(status, SIGSTOP);
10811.59Skamil
10821.59Skamil		/* Resume tracee with PT_CONTINUE */
10831.59Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10841.59Skamil
10851.59Skamil		/* Inform parent that tracer has attached to tracee */
10861.59Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
10871.59Skamil
10881.59Skamil		/* Wait for parent to tell use that tracee should have exited */
10891.59Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
10901.59Skamil
10911.59Skamil		/* Wait for tracee and assert that it exited */
10921.59Skamil		FORKEE_REQUIRE_SUCCESS(
10931.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10941.59Skamil
10951.59Skamil		validate_status_stopped(status, sig);
10961.59Skamil
10971.59Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the "
10981.61Skre		    "traced process\n");
10991.61Skre		SYSCALL_REQUIRE(
11001.61Skre		    ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1);
11011.59Skamil
11021.59Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
11031.59Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
11041.61Skre		    "si_errno=%#x\n", info.psi_siginfo.si_signo,
11051.61Skre		    info.psi_siginfo.si_code, info.psi_siginfo.si_errno);
11061.59Skamil
11071.59Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig);
11081.59Skamil		switch (sig) {
11091.59Skamil		case SIGTRAP:
11101.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT);
11111.59Skamil			break;
11121.59Skamil		case SIGSEGV:
11131.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR);
11141.59Skamil			break;
11151.71Skamil		case SIGILL:
11161.71Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC);
11171.71Skamil			break;
11181.59Skamil		case SIGFPE:
11191.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV);
11201.59Skamil			break;
11211.59Skamil		case SIGBUS:
11221.59Skamil			ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR);
11231.59Skamil			break;
11241.59Skamil		}
11251.59Skamil
11261.59Skamil		FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1);
11271.59Skamil		DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME);
11281.61Skre		TWAIT_REQUIRE_SUCCESS(
11291.61Skre		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11301.59Skamil
11311.59Skamil		validate_status_signaled(status, SIGKILL, 0);
11321.59Skamil
11331.59Skamil		DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
11341.59Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
11351.59Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0));
11361.59Skamil
11371.71Skamil		/* Inform parent that tracer is exiting normally */
11381.71Skamil		CHILD_TO_PARENT("tracer done", parent_tracer, msg);
11391.71Skamil
11401.59Skamil		DPRINTF("Before exiting of the tracer process\n");
11411.59Skamil		_exit(0 /* collect by initproc */);
11421.59Skamil	}
11431.59Skamil
11441.59Skamil	DPRINTF("Wait for the tracer process (direct child) to exit "
11451.59Skamil	    "calling %s()\n", TWAIT_FNAME);
11461.59Skamil	TWAIT_REQUIRE_SUCCESS(
11471.59Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
11481.59Skamil
11491.59Skamil	validate_status_exited(status, exitval);
11501.59Skamil
11511.59Skamil	DPRINTF("Wait for the non-exited tracee process with %s()\n",
11521.59Skamil	    TWAIT_FNAME);
11531.59Skamil	TWAIT_REQUIRE_SUCCESS(
11541.59Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
11551.59Skamil
11561.59Skamil	DPRINTF("Wait for the tracer to attach to the tracee\n");
11571.59Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
11581.59Skamil
11591.59Skamil	DPRINTF("Resume the tracee and let it crash\n");
11601.59Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
11611.59Skamil
11621.59Skamil	DPRINTF("Resume the tracer and let it detect crashed tracee\n");
11631.59Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11641.59Skamil
11651.59Skamil	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11661.59Skamil	    TWAIT_FNAME);
11671.59Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11681.59Skamil
11691.59Skamil	validate_status_signaled(status, SIGKILL, 0);
11701.59Skamil
11711.71Skamil	DPRINTF("Await normal exit of tracer\n");
11721.71Skamil	PARENT_FROM_CHILD("tracer done", parent_tracer, msg);
11731.71Skamil
11741.59Skamil	msg_close(&parent_tracer);
11751.59Skamil	msg_close(&parent_tracee);
11761.59Skamil}
11771.59Skamil
11781.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig)				\
11791.61SkreATF_TC(test);								\
11801.61SkreATF_TC_HEAD(test, tc)							\
11811.61Skre{									\
11821.61Skre	atf_tc_set_md_var(tc, "descr",					\
11831.61Skre	    "Assert that an unrelated tracer sees crash signal from the " \
11841.61Skre	    "debuggee");						\
11851.61Skre}									\
11861.61Skre									\
11871.61SkreATF_TC_BODY(test, tc)							\
11881.61Skre{									\
11891.61Skre									\
11901.61Skre	unrelated_tracer_sees_crash(sig);				\
11911.59Skamil}
11921.59Skamil
11931.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP)
11941.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV)
11951.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL)
11961.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE)
11971.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS)
11981.59Skamil#endif
11991.59Skamil
12001.59Skamil/// ----------------------------------------------------------------------------
12011.59Skamil
12021.59Skamil#if defined(TWAIT_HAVE_PID)
12031.59Skamilstatic void
12041.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated,
12051.67Skamil                                             bool stopped)
12061.1Skamil{
12071.51Skamil	/*
12081.51Skamil	 * notimeout - disable timeout in await zombie function
12091.51Skamil	 * unrelated - attach from unrelated tracer reparented to initproc
12101.67Skamil	 * stopped - attach to a stopped process
12111.51Skamil	 */
12121.1Skamil
12131.1Skamil	struct msg_fds parent_tracee, parent_tracer;
12141.1Skamil	const int exitval_tracee = 5;
12151.1Skamil	const int exitval_tracer = 10;
12161.1Skamil	pid_t tracee, tracer, wpid;
12171.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
12181.1Skamil#if defined(TWAIT_HAVE_STATUS)
12191.1Skamil	int status;
12201.1Skamil#endif
12211.1Skamil
12221.67Skamil	/*
12231.67Skamil	 * Only a subset of options are supported.
12241.67Skamil	 */
12251.67Skamil	ATF_REQUIRE((!notimeout && !unrelated && !stopped) ||
12261.67Skamil	            (!notimeout && unrelated && !stopped) ||
12271.67Skamil	            (notimeout && !unrelated && !stopped) ||
12281.67Skamil	            (!notimeout && unrelated && stopped));
12291.67Skamil
12301.13Schristos	DPRINTF("Spawn tracee\n");
12311.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
12321.1Skamil	tracee = atf_utils_fork();
12331.1Skamil	if (tracee == 0) {
12341.67Skamil		if (stopped) {
12351.67Skamil			DPRINTF("Stop self PID %d\n", getpid());
12361.67Skamil			raise(SIGSTOP);
12371.67Skamil		}
12381.67Skamil
12391.1Skamil		// Wait for parent to let us exit
12401.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
12411.1Skamil		_exit(exitval_tracee);
12421.1Skamil	}
12431.1Skamil
12441.13Schristos	DPRINTF("Spawn debugger\n");
12451.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
12461.1Skamil	tracer = atf_utils_fork();
12471.1Skamil	if (tracer == 0) {
12481.51Skamil		if(unrelated) {
12491.51Skamil			/* Fork again and drop parent to reattach to PID 1 */
12501.51Skamil			tracer = atf_utils_fork();
12511.51Skamil			if (tracer != 0)
12521.51Skamil				_exit(exitval_tracer);
12531.51Skamil		}
12541.51Skamil
12551.67Skamil		if (stopped) {
12561.67Skamil			DPRINTF("Await for a stopped parent PID %d\n", tracee);
12571.67Skamil			await_stopped(tracee);
12581.67Skamil		}
12591.67Skamil
12601.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
12611.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
12621.1Skamil
12631.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
12641.1Skamil		FORKEE_REQUIRE_SUCCESS(
12651.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12661.1Skamil
12671.1Skamil		forkee_status_stopped(status, SIGSTOP);
12681.1Skamil
12691.1Skamil		/* Resume tracee with PT_CONTINUE */
12701.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
12711.1Skamil
12721.1Skamil		/* Inform parent that tracer has attached to tracee */
12731.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
12741.1Skamil
12751.1Skamil		/* Wait for parent to tell use that tracee should have exited */
12761.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
12771.1Skamil
12781.1Skamil		/* Wait for tracee and assert that it exited */
12791.1Skamil		FORKEE_REQUIRE_SUCCESS(
12801.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
12811.1Skamil
12821.1Skamil		forkee_status_exited(status, exitval_tracee);
12831.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
12841.1Skamil
12851.13Schristos		DPRINTF("Before exiting of the tracer process\n");
12861.51Skamil		_exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer);
12871.51Skamil	}
12881.51Skamil
12891.51Skamil	if (unrelated) {
12901.51Skamil		DPRINTF("Wait for the tracer process (direct child) to exit "
12911.51Skamil		    "calling %s()\n", TWAIT_FNAME);
12921.51Skamil		TWAIT_REQUIRE_SUCCESS(
12931.51Skamil		    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
12941.51Skamil
12951.51Skamil		validate_status_exited(status, exitval_tracer);
12961.51Skamil
12971.51Skamil		DPRINTF("Wait for the non-exited tracee process with %s()\n",
12981.51Skamil		    TWAIT_FNAME);
12991.51Skamil		TWAIT_REQUIRE_SUCCESS(
13001.51Skamil		    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
13011.1Skamil	}
13021.1Skamil
13031.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
13041.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
13051.1Skamil
13061.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
13071.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
13081.1Skamil
13091.13Schristos	DPRINTF("Detect that tracee is zombie\n");
13101.51Skamil	if (notimeout)
13111.26Skamil		await_zombie_raw(tracee, 0);
13121.26Skamil	else
13131.26Skamil		await_zombie(tracee);
13141.1Skamil
13151.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
13161.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
13171.1Skamil	    TWAIT_FNAME);
13181.1Skamil	TWAIT_REQUIRE_SUCCESS(
13191.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
13201.1Skamil
13211.51Skamil	if (unrelated) {
13221.51Skamil		DPRINTF("Resume the tracer and let it detect exited tracee\n");
13231.51Skamil		PARENT_TO_CHILD("Message 2", parent_tracer, msg);
13241.51Skamil	} else {
13251.51Skamil		DPRINTF("Tell the tracer child should have exited\n");
13261.51Skamil		PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
13271.51Skamil		DPRINTF("Wait for tracer to finish its job and exit - calling "
13281.59Skamil			"%s()\n", TWAIT_FNAME);
13291.51Skamil
13301.51Skamil		DPRINTF("Wait from tracer child to complete waiting for "
13311.59Skamil			"tracee\n");
13321.51Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
13331.51Skamil		    tracer);
13341.1Skamil
13351.51Skamil		validate_status_exited(status, exitval_tracer);
13361.51Skamil	}
13371.1Skamil
13381.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
13391.1Skamil	    TWAIT_FNAME);
13401.51Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
13411.1Skamil
13421.1Skamil	validate_status_exited(status, exitval_tracee);
13431.1Skamil
13441.1Skamil	msg_close(&parent_tracer);
13451.1Skamil	msg_close(&parent_tracee);
13461.1Skamil}
13471.26Skamil
13481.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent);
13491.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc)
13501.51Skamil{
13511.51Skamil	atf_tc_set_md_var(tc, "descr",
13521.51Skamil	    "Assert that tracer sees process termination before the parent");
13531.51Skamil}
13541.51Skamil
13551.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc)
13561.26Skamil{
13571.26Skamil
13581.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, false, false);
13591.26Skamil}
13601.26Skamil
13611.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates);
13621.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc)
13631.1Skamil{
13641.1Skamil	atf_tc_set_md_var(tc, "descr",
13651.51Skamil	    "Assert that await_zombie() in attach1 always finds a single "
13661.51Skamil	    "process and no other error is reported");
13671.1Skamil}
13681.1Skamil
13691.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc)
13701.1Skamil{
13711.51Skamil	time_t start, end;
13721.51Skamil	double diff;
13731.51Skamil	unsigned long N = 0;
13741.1Skamil
13751.51Skamil	/*
13761.51Skamil	 * Reuse this test with tracer_sees_terminaton_before_the_parent_raw().
13771.51Skamil	 * This test body isn't specific to this race, however it's just good
13781.51Skamil	 * enough for this purposes, no need to invent a dedicated code flow.
13791.51Skamil	 */
13801.1Skamil
13811.51Skamil	start = time(NULL);
13821.51Skamil	while (true) {
13831.51Skamil		DPRINTF("Step: %lu\n", N);
13841.67Skamil		tracer_sees_terminaton_before_the_parent_raw(true, false,
13851.67Skamil		                                             false);
13861.51Skamil		end = time(NULL);
13871.51Skamil		diff = difftime(end, start);
13881.51Skamil		if (diff >= 5.0)
13891.51Skamil			break;
13901.51Skamil		++N;
13911.1Skamil	}
13921.51Skamil	DPRINTF("Iterations: %lu\n", N);
13931.51Skamil}
13941.1Skamil
13951.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent);
13961.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc)
13971.51Skamil{
13981.51Skamil	atf_tc_set_md_var(tc, "descr",
13991.51Skamil	    "Assert that tracer sees process termination before the parent");
14001.51Skamil}
14011.1Skamil
14021.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc)
14031.51Skamil{
14041.1Skamil
14051.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, false);
14061.67Skamil}
14071.67Skamil
14081.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process);
14091.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc)
14101.67Skamil{
14111.67Skamil	atf_tc_set_md_var(tc, "descr",
14121.67Skamil	    "Assert that tracer can attach to an unrelated stopped process");
14131.67Skamil}
14141.67Skamil
14151.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc)
14161.67Skamil{
14171.67Skamil
14181.67Skamil	tracer_sees_terminaton_before_the_parent_raw(false, true, true);
14191.1Skamil}
14201.1Skamil#endif
14211.1Skamil
14221.51Skamil/// ----------------------------------------------------------------------------
14231.51Skamil
14241.66Skamilstatic void
14251.66Skamilparent_attach_to_its_child(bool stopped)
14261.1Skamil{
14271.1Skamil	struct msg_fds parent_tracee;
14281.1Skamil	const int exitval_tracee = 5;
14291.1Skamil	pid_t tracee, wpid;
14301.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
14311.1Skamil#if defined(TWAIT_HAVE_STATUS)
14321.1Skamil	int status;
14331.1Skamil#endif
14341.1Skamil
14351.13Schristos	DPRINTF("Spawn tracee\n");
14361.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
14371.1Skamil	tracee = atf_utils_fork();
14381.1Skamil	if (tracee == 0) {
14391.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
14401.13Schristos		DPRINTF("Parent should now attach to tracee\n");
14411.1Skamil
14421.66Skamil		if (stopped) {
14431.66Skamil			DPRINTF("Stop self PID %d\n", getpid());
14441.66Skamil			SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
14451.66Skamil		}
14461.66Skamil
14471.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
14481.1Skamil		/* Wait for message from the parent */
14491.1Skamil		_exit(exitval_tracee);
14501.1Skamil	}
14511.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
14521.57Skamil
14531.66Skamil	if (stopped) {
14541.66Skamil		DPRINTF("Await for a stopped tracee PID %d\n", tracee);
14551.66Skamil		await_stopped(tracee);
14561.66Skamil	}
14571.66Skamil
14581.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
14591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
14601.1Skamil
14611.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
14621.1Skamil	    TWAIT_FNAME);
14631.1Skamil	TWAIT_REQUIRE_SUCCESS(
14641.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14651.1Skamil
14661.1Skamil	validate_status_stopped(status, SIGSTOP);
14671.1Skamil
14681.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
14691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
14701.1Skamil
14711.13Schristos	DPRINTF("Let the tracee exit now\n");
14721.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
14731.1Skamil
14741.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
14751.1Skamil	TWAIT_REQUIRE_SUCCESS(
14761.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
14771.1Skamil
14781.1Skamil	validate_status_exited(status, exitval_tracee);
14791.1Skamil
14801.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
14811.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
14821.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
14831.1Skamil
14841.1Skamil	msg_close(&parent_tracee);
14851.1Skamil}
14861.1Skamil
14871.66SkamilATF_TC(parent_attach_to_its_child);
14881.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc)
14891.66Skamil{
14901.66Skamil	atf_tc_set_md_var(tc, "descr",
14911.66Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
14921.66Skamil}
14931.66Skamil
14941.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc)
14951.66Skamil{
14961.66Skamil
14971.66Skamil	parent_attach_to_its_child(false);
14981.66Skamil}
14991.66Skamil
15001.66SkamilATF_TC(parent_attach_to_its_stopped_child);
15011.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc)
15021.66Skamil{
15031.66Skamil	atf_tc_set_md_var(tc, "descr",
15041.66Skamil	    "Assert that tracer parent can PT_ATTACH to its stopped child");
15051.66Skamil}
15061.66Skamil
15071.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc)
15081.66Skamil{
15091.66Skamil
15101.66Skamil	parent_attach_to_its_child(true);
15111.66Skamil}
15121.66Skamil
15131.51Skamil/// ----------------------------------------------------------------------------
15141.51Skamil
15151.65Skamilstatic void
15161.65Skamilchild_attach_to_its_parent(bool stopped)
15171.1Skamil{
15181.1Skamil	struct msg_fds parent_tracee;
15191.1Skamil	const int exitval_tracer = 5;
15201.1Skamil	pid_t tracer, wpid;
15211.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
15221.1Skamil#if defined(TWAIT_HAVE_STATUS)
15231.1Skamil	int status;
15241.1Skamil#endif
15251.1Skamil
15261.13Schristos	DPRINTF("Spawn tracer\n");
15271.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
15281.1Skamil	tracer = atf_utils_fork();
15291.1Skamil	if (tracer == 0) {
15301.1Skamil		/* Wait for message from the parent */
15311.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
15321.1Skamil
15331.65Skamil		if (stopped) {
15341.65Skamil			DPRINTF("Await for a stopped parent PID %d\n",
15351.65Skamil			        getppid());
15361.65Skamil			await_stopped(getppid());
15371.65Skamil		}
15381.65Skamil
15391.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
15401.1Skamil		    getppid());
15411.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
15421.1Skamil
15431.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
15441.1Skamil		    TWAIT_FNAME);
15451.1Skamil		FORKEE_REQUIRE_SUCCESS(
15461.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
15471.1Skamil
15481.1Skamil		forkee_status_stopped(status, SIGSTOP);
15491.1Skamil
15501.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
15511.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
15521.1Skamil		    != -1);
15531.1Skamil
15541.1Skamil		/* Tell parent we are ready */
15551.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
15561.1Skamil
15571.1Skamil		_exit(exitval_tracer);
15581.1Skamil	}
15591.1Skamil
15601.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
15611.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
15621.65Skamil
15631.65Skamil	if (stopped) {
15641.65Skamil		DPRINTF("Stop self PID %d\n", getpid());
15651.65Skamil		SYSCALL_REQUIRE(raise(SIGSTOP) != -1);
15661.65Skamil	}
15671.65Skamil
15681.13Schristos	DPRINTF("Allow the tracer to exit now\n");
15691.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
15701.1Skamil
15711.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
15721.1Skamil	TWAIT_REQUIRE_SUCCESS(
15731.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
15741.1Skamil
15751.1Skamil	validate_status_exited(status, exitval_tracer);
15761.1Skamil
15771.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
15781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
15791.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
15801.1Skamil
15811.1Skamil	msg_close(&parent_tracee);
15821.1Skamil}
15831.1Skamil
15841.65SkamilATF_TC(child_attach_to_its_parent);
15851.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc)
15861.65Skamil{
15871.65Skamil	atf_tc_set_md_var(tc, "descr",
15881.65Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
15891.65Skamil}
15901.65Skamil
15911.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc)
15921.65Skamil{
15931.65Skamil
15941.65Skamil	child_attach_to_its_parent(false);
15951.65Skamil}
15961.65Skamil
15971.65SkamilATF_TC(child_attach_to_its_stopped_parent);
15981.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc)
15991.65Skamil{
16001.65Skamil	atf_tc_set_md_var(tc, "descr",
16011.65Skamil	    "Assert that tracer child can PT_ATTACH to its stopped parent");
16021.65Skamil}
16031.65Skamil
16041.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc)
16051.65Skamil{
16061.65Skamil	/*
16071.65Skamil	 * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as
16081.65Skamil	 * this causes a pipe (established from atf-run) to be broken.
16091.65Skamil	 * atf-run uses this mechanism to monitor whether a test is alive.
16101.65Skamil	 *
16111.65Skamil	 * As a workaround spawn this test as a subprocess.
16121.65Skamil	 */
16131.65Skamil
16141.65Skamil	const int exitval = 15;
16151.65Skamil	pid_t child, wpid;
16161.65Skamil#if defined(TWAIT_HAVE_STATUS)
16171.65Skamil	int status;
16181.65Skamil#endif
16191.65Skamil
16201.65Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
16211.65Skamil	if (child == 0) {
16221.65Skamil		child_attach_to_its_parent(true);
16231.65Skamil		_exit(exitval);
16241.65Skamil	} else {
16251.65Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
16261.65Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16271.65Skamil
16281.65Skamil		validate_status_exited(status, exitval);
16291.65Skamil
16301.65Skamil		DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
16311.65Skamil		TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16321.65Skamil	}
16331.65Skamil}
16341.65Skamil
16351.51Skamil/// ----------------------------------------------------------------------------
16361.51Skamil
16371.1Skamil#if defined(TWAIT_HAVE_PID)
16381.1Skamil
16391.51Skamilenum tracee_sees_its_original_parent_type {
16401.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
16411.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
16421.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS
16431.51Skamil};
16441.51Skamil
16451.51Skamilstatic void
16461.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type)
16471.1Skamil{
16481.1Skamil	struct msg_fds parent_tracer, parent_tracee;
16491.1Skamil	const int exitval_tracee = 5;
16501.1Skamil	const int exitval_tracer = 10;
16511.1Skamil	pid_t parent, tracee, tracer, wpid;
16521.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
16531.1Skamil#if defined(TWAIT_HAVE_STATUS)
16541.1Skamil	int status;
16551.1Skamil#endif
16561.51Skamil	/* sysctl(3) - kinfo_proc2 */
16571.51Skamil	int name[CTL_MAXNAME];
16581.51Skamil	struct kinfo_proc2 kp;
16591.51Skamil	size_t len = sizeof(kp);
16601.51Skamil	unsigned int namelen;
16611.51Skamil
16621.51Skamil	/* procfs - status  */
16631.51Skamil	FILE *fp;
16641.51Skamil	struct stat st;
16651.51Skamil	const char *fname = "/proc/curproc/status";
16661.51Skamil	char s_executable[MAXPATHLEN];
16671.51Skamil	int s_pid, s_ppid;
16681.51Skamil	int rv;
16691.51Skamil
16701.51Skamil	if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) {
16711.61Skre		SYSCALL_REQUIRE(
16721.61Skre		    (rv = stat(fname, &st)) == 0 || (errno == ENOENT));
16731.61Skre		if (rv != 0)
16741.51Skamil			atf_tc_skip("/proc/curproc/status not found");
16751.51Skamil	}
16761.1Skamil
16771.13Schristos	DPRINTF("Spawn tracee\n");
16781.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
16791.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
16801.1Skamil	tracee = atf_utils_fork();
16811.1Skamil	if (tracee == 0) {
16821.1Skamil		parent = getppid();
16831.1Skamil
16841.1Skamil		/* Emit message to the parent */
16851.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
16861.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
16871.1Skamil
16881.51Skamil		switch (type) {
16891.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID:
16901.51Skamil			FORKEE_ASSERT_EQ(parent, getppid());
16911.51Skamil			break;
16921.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2:
16931.51Skamil			namelen = 0;
16941.51Skamil			name[namelen++] = CTL_KERN;
16951.51Skamil			name[namelen++] = KERN_PROC2;
16961.51Skamil			name[namelen++] = KERN_PROC_PID;
16971.51Skamil			name[namelen++] = getpid();
16981.51Skamil			name[namelen++] = len;
16991.51Skamil			name[namelen++] = 1;
17001.51Skamil
17011.61Skre			FORKEE_ASSERT_EQ(
17021.61Skre			    sysctl(name, namelen, &kp, &len, NULL, 0), 0);
17031.51Skamil			FORKEE_ASSERT_EQ(parent, kp.p_ppid);
17041.51Skamil			break;
17051.51Skamil		case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS:
17061.51Skamil			/*
17071.51Skamil			 * Format:
17081.51Skamil			 *  EXECUTABLE PID PPID ...
17091.51Skamil			 */
17101.51Skamil			FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
17111.51Skamil			fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
17121.51Skamil			FORKEE_ASSERT_EQ(fclose(fp), 0);
17131.51Skamil			FORKEE_ASSERT_EQ(parent, s_ppid);
17141.51Skamil			break;
17151.51Skamil		}
17161.1Skamil
17171.1Skamil		_exit(exitval_tracee);
17181.1Skamil	}
17191.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
17201.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
17211.1Skamil
17221.13Schristos	DPRINTF("Spawn debugger\n");
17231.1Skamil	tracer = atf_utils_fork();
17241.1Skamil	if (tracer == 0) {
17251.1Skamil		/* No IPC to communicate with the child */
17261.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
17271.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
17281.1Skamil
17291.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
17301.1Skamil		FORKEE_REQUIRE_SUCCESS(
17311.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17321.1Skamil
17331.1Skamil		forkee_status_stopped(status, SIGSTOP);
17341.1Skamil
17351.1Skamil		/* Resume tracee with PT_CONTINUE */
17361.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
17371.1Skamil
17381.1Skamil		/* Inform parent that tracer has attached to tracee */
17391.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
17401.1Skamil
17411.1Skamil		/* Wait for parent to tell use that tracee should have exited */
17421.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
17431.1Skamil
17441.1Skamil		/* Wait for tracee and assert that it exited */
17451.1Skamil		FORKEE_REQUIRE_SUCCESS(
17461.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
17471.1Skamil
17481.1Skamil		forkee_status_exited(status, exitval_tracee);
17491.1Skamil
17501.13Schristos		DPRINTF("Before exiting of the tracer process\n");
17511.1Skamil		_exit(exitval_tracer);
17521.1Skamil	}
17531.1Skamil
17541.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
17551.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
17561.1Skamil
17571.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
17581.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
17591.1Skamil
17601.13Schristos	DPRINTF("Detect that tracee is zombie\n");
17611.1Skamil	await_zombie(tracee);
17621.1Skamil
17631.13Schristos	DPRINTF("Assert that there is no status about tracee - "
17641.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
17651.1Skamil	TWAIT_REQUIRE_SUCCESS(
17661.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
17671.1Skamil
17681.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
17691.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
17701.1Skamil
17711.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
17721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
17731.1Skamil	    tracer);
17741.1Skamil
17751.1Skamil	validate_status_exited(status, exitval_tracer);
17761.1Skamil
17771.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
17781.1Skamil	    TWAIT_FNAME);
17791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
17801.1Skamil	    tracee);
17811.1Skamil
17821.1Skamil	validate_status_exited(status, exitval_tracee);
17831.1Skamil
17841.1Skamil	msg_close(&parent_tracer);
17851.1Skamil	msg_close(&parent_tracee);
17861.1Skamil}
17871.1Skamil
17881.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr)		\
17891.61SkreATF_TC(test);								\
17901.61SkreATF_TC_HEAD(test, tc)							\
17911.61Skre{									\
17921.61Skre	atf_tc_set_md_var(tc, "descr",					\
17931.61Skre	    "Assert that tracee sees its original parent when being traced " \
17941.61Skre	    "(check " descr ")");					\
17951.61Skre}									\
17961.61Skre									\
17971.61SkreATF_TC_BODY(test, tc)							\
17981.61Skre{									\
17991.61Skre									\
18001.61Skre	tracee_sees_its_original_parent(type);				\
18011.1Skamil}
18021.1Skamil
18031.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18041.51Skamil	tracee_sees_its_original_parent_getppid,
18051.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID,
18061.51Skamil	"getppid(2)");
18071.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18081.51Skamil	tracee_sees_its_original_parent_sysctl_kinfo_proc2,
18091.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2,
18101.51Skamil	"sysctl(3) and kinfo_proc2");
18111.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT(
18121.51Skamil	tracee_sees_its_original_parent_procfs_status,
18131.51Skamil	TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS,
18141.51Skamil	"the status file in procfs");
18151.1Skamil#endif
18161.1Skamil
18171.51Skamil/// ----------------------------------------------------------------------------
18181.1Skamil
18191.53Skamilstatic void
18201.53Skamileventmask_preserved(int event)
18211.1Skamil{
18221.1Skamil	const int exitval = 5;
18231.1Skamil	const int sigval = SIGSTOP;
18241.1Skamil	pid_t child, wpid;
18251.1Skamil#if defined(TWAIT_HAVE_STATUS)
18261.1Skamil	int status;
18271.1Skamil#endif
18281.1Skamil	ptrace_event_t set_event, get_event;
18291.1Skamil	const int len = sizeof(ptrace_event_t);
18301.1Skamil
18311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18331.1Skamil	if (child == 0) {
18341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18361.1Skamil
18371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18391.1Skamil
18401.13Schristos		DPRINTF("Before exiting of the child process\n");
18411.1Skamil		_exit(exitval);
18421.1Skamil	}
18431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18441.1Skamil
18451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18471.1Skamil
18481.1Skamil	validate_status_stopped(status, sigval);
18491.1Skamil
18501.53Skamil	set_event.pe_set_event = event;
18511.61Skre	SYSCALL_REQUIRE(
18521.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
18531.61Skre	SYSCALL_REQUIRE(
18541.61Skre	    ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
18551.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
18561.1Skamil
18571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18581.1Skamil	    "without signal to be sent\n");
18591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18601.1Skamil
18611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18631.1Skamil
18641.1Skamil	validate_status_exited(status, exitval);
18651.1Skamil
18661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18681.1Skamil}
18691.1Skamil
18701.61Skre#define EVENTMASK_PRESERVED(test, event)				\
18711.61SkreATF_TC(test);								\
18721.61SkreATF_TC_HEAD(test, tc)							\
18731.61Skre{									\
18741.61Skre	atf_tc_set_md_var(tc, "descr",					\
18751.61Skre	    "Verify that eventmask " #event " is preserved");		\
18761.61Skre}									\
18771.61Skre									\
18781.61SkreATF_TC_BODY(test, tc)							\
18791.61Skre{									\
18801.61Skre									\
18811.61Skre	eventmask_preserved(event);					\
18821.1Skamil}
18831.1Skamil
18841.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0)
18851.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK)
18861.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK)
18871.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE)
18881.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE)
18891.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT)
18901.1Skamil
18911.53Skamil/// ----------------------------------------------------------------------------
18921.1Skamil
18931.28Skamilstatic void
18941.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
18951.61Skre    bool trackvforkdone, bool detachchild, bool detachparent)
18961.1Skamil{
18971.1Skamil	const int exitval = 5;
18981.1Skamil	const int exitval2 = 15;
18991.1Skamil	const int sigval = SIGSTOP;
19001.31Skamil	pid_t child, child2 = 0, wpid;
19011.1Skamil#if defined(TWAIT_HAVE_STATUS)
19021.1Skamil	int status;
19031.1Skamil#endif
19041.1Skamil	ptrace_state_t state;
19051.1Skamil	const int slen = sizeof(state);
19061.1Skamil	ptrace_event_t event;
19071.1Skamil	const int elen = sizeof(event);
19081.1Skamil
19091.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19101.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19111.1Skamil	if (child == 0) {
19121.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19131.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19141.1Skamil
19151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19171.1Skamil
19181.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
19191.1Skamil
19201.1Skamil		if (child2 == 0)
19211.1Skamil			_exit(exitval2);
19221.1Skamil
19231.1Skamil		FORKEE_REQUIRE_SUCCESS
19241.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
19251.1Skamil
19261.1Skamil		forkee_status_exited(status, exitval2);
19271.1Skamil
19281.13Schristos		DPRINTF("Before exiting of the child process\n");
19291.1Skamil		_exit(exitval);
19301.1Skamil	}
19311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19321.1Skamil
19331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19351.1Skamil
19361.1Skamil	validate_status_stopped(status, sigval);
19371.1Skamil
19381.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
19391.61Skre	    trackfork ? "|PTRACE_FORK" : "",
19401.61Skre	    trackvfork ? "|PTRACE_VFORK" : "",
19411.61Skre	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
19421.30Skamil	event.pe_set_event = 0;
19431.30Skamil	if (trackfork)
19441.30Skamil		event.pe_set_event |= PTRACE_FORK;
19451.30Skamil	if (trackvfork)
19461.30Skamil		event.pe_set_event |= PTRACE_VFORK;
19471.30Skamil	if (trackvforkdone)
19481.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
19491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
19501.1Skamil
19511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19521.1Skamil	    "without signal to be sent\n");
19531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19541.1Skamil
19551.29Skamil#if defined(TWAIT_HAVE_PID)
19561.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
19571.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
19581.61Skre		    child);
19591.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
19601.61Skre		    child);
19611.1Skamil
19621.29Skamil		validate_status_stopped(status, SIGTRAP);
19631.1Skamil
19641.61Skre		SYSCALL_REQUIRE(
19651.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &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.29Skamil
19751.29Skamil		child2 = state.pe_other_pid;
19761.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
19771.29Skamil
19781.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
19791.61Skre		    "%d\n", TWAIT_FNAME, child2, child);
19801.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
19811.29Skamil		    child2);
19821.1Skamil
19831.29Skamil		validate_status_stopped(status, SIGTRAP);
19841.1Skamil
19851.61Skre		SYSCALL_REQUIRE(
19861.61Skre		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
19871.31Skamil		if (trackfork && fn == fork) {
19881.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
19891.30Skamil			       PTRACE_FORK);
19901.30Skamil		}
19911.31Skamil		if (trackvfork && fn == vfork) {
19921.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
19931.30Skamil			       PTRACE_VFORK);
19941.30Skamil		}
19951.30Skamil
19961.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
19971.29Skamil
19981.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
19991.29Skamil		    "and without signal to be sent\n");
20001.61Skre		SYSCALL_REQUIRE(
20011.61Skre		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
20021.29Skamil
20031.29Skamil		DPRINTF("Before resuming the child process where it left off "
20041.61Skre		    "and without signal to be sent\n");
20051.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20061.30Skamil	}
20071.30Skamil#endif
20081.30Skamil
20091.31Skamil	if (trackvforkdone && fn == vfork) {
20101.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
20111.61Skre		    child);
20121.61Skre		TWAIT_REQUIRE_SUCCESS(
20131.61Skre		    wpid = TWAIT_GENERIC(child, &status, 0), child);
20141.30Skamil
20151.30Skamil		validate_status_stopped(status, SIGTRAP);
20161.30Skamil
20171.61Skre		SYSCALL_REQUIRE(
20181.61Skre		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
20191.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
20201.30Skamil
20211.30Skamil		child2 = state.pe_other_pid;
20221.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
20231.61Skre		    child2);
20241.30Skamil
20251.30Skamil		DPRINTF("Before resuming the child process where it left off "
20261.61Skre		    "and without signal to be sent\n");
20271.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20281.30Skamil	}
20291.29Skamil
20301.30Skamil#if defined(TWAIT_HAVE_PID)
20311.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
20321.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
20331.61Skre		    "\n", TWAIT_FNAME);
20341.61Skre		TWAIT_REQUIRE_SUCCESS(
20351.61Skre		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
20361.29Skamil
20371.29Skamil		validate_status_exited(status, exitval2);
20381.29Skamil
20391.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
20401.61Skre		    "process\n", TWAIT_FNAME);
20411.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
20421.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
20431.29Skamil	}
20441.29Skamil#endif
20451.1Skamil
20461.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
20471.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
20481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20491.1Skamil
20501.1Skamil	validate_status_stopped(status, SIGCHLD);
20511.1Skamil
20521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20531.1Skamil	    "without signal to be sent\n");
20541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20551.1Skamil
20561.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
20571.1Skamil	    TWAIT_FNAME);
20581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20591.1Skamil
20601.1Skamil	validate_status_exited(status, exitval);
20611.1Skamil
20621.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
20631.1Skamil	    TWAIT_FNAME);
20641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20651.1Skamil}
20661.28Skamil
20671.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \
20681.61SkreATF_TC(name);								\
20691.61SkreATF_TC_HEAD(name, tc)							\
20701.61Skre{									\
20711.61Skre	atf_tc_set_md_var(tc, "descr", descr);				\
20721.61Skre}									\
20731.61Skre									\
20741.61SkreATF_TC_BODY(name, tc)							\
20751.61Skre{									\
20761.61Skre									\
20771.61Skre	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);	\
20781.32Skamil}
20791.32Skamil
20801.32Skamil#define F false
20811.32Skamil#define T true
20821.32Skamil
20831.32Skamil#define F_IF__0(x)
20841.32Skamil#define F_IF__1(x) x
20851.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
20861.32Skamil#define F_IF_(x,y) F_IF__(x,y)
20871.32Skamil#define F_IF(x,y) F_IF_(x,y)
20881.32Skamil
20891.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \
20901.61Skre	"Verify " #function "(2) called with 0"				\
20911.61Skre	F_IF(forkbit,"|PTRACE_FORK")					\
20921.61Skre	F_IF(vforkbit,"|PTRACE_VFORK")					\
20931.61Skre	F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")				\
20941.61Skre	" in EVENT_MASK."						\
20951.61Skre	F_IF(dchildbit," Detach child in this test.")			\
20961.61Skre	F_IF(dparentbit," Detach parent in this test.")
20971.1Skamil
20981.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
20991.31Skamil#if defined(TWAIT_HAVE_PID)
21001.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
21011.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
21021.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
21031.31Skamil#endif
21041.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
21051.31Skamil#if defined(TWAIT_HAVE_PID)
21061.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
21071.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
21081.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
21091.31Skamil#endif
21101.1Skamil
21111.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
21121.31Skamil#if defined(TWAIT_HAVE_PID)
21131.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
21141.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
21151.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
21161.31Skamil#endif
21171.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
21181.31Skamil#if defined(TWAIT_HAVE_PID)
21191.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
21201.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
21211.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
21221.31Skamil#endif
21231.31Skamil
21241.54Skamil/// ----------------------------------------------------------------------------
21251.31Skamil
21261.54Skamilenum bytes_transfer_type {
21271.54Skamil	BYTES_TRANSFER_DATA,
21281.54Skamil	BYTES_TRANSFER_DATAIO,
21291.54Skamil	BYTES_TRANSFER_TEXT,
21301.54Skamil	BYTES_TRANSFER_TEXTIO,
21311.54Skamil	BYTES_TRANSFER_AUXV
21321.54Skamil};
21331.31Skamil
21341.54Skamilstatic int __used
21351.54Skamilbytes_transfer_dummy(int a, int b, int c, int d)
21361.54Skamil{
21371.54Skamil	int e, f, g, h;
21381.1Skamil
21391.54Skamil	a *= 4;
21401.54Skamil	b += 3;
21411.54Skamil	c -= 2;
21421.54Skamil	d /= 1;
21431.1Skamil
21441.54Skamil	e = strtol("10", NULL, 10);
21451.54Skamil	f = strtol("20", NULL, 10);
21461.54Skamil	g = strtol("30", NULL, 10);
21471.54Skamil	h = strtol("40", NULL, 10);
21481.1Skamil
21491.54Skamil	return (a + b * c - d) + (e * f - g / h);
21501.1Skamil}
21511.1Skamil
21521.54Skamilstatic void
21531.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
21541.1Skamil{
21551.1Skamil	const int exitval = 5;
21561.1Skamil	const int sigval = SIGSTOP;
21571.1Skamil	pid_t child, wpid;
21581.54Skamil	bool skip = false;
21591.1Skamil
21601.54Skamil	int lookup_me = 0;
21611.54Skamil	uint8_t lookup_me8 = 0;
21621.54Skamil	uint16_t lookup_me16 = 0;
21631.54Skamil	uint32_t lookup_me32 = 0;
21641.54Skamil	uint64_t lookup_me64 = 0;
21651.1Skamil
21661.54Skamil	int magic = 0x13579246;
21671.54Skamil	uint8_t magic8 = 0xab;
21681.54Skamil	uint16_t magic16 = 0x1234;
21691.54Skamil	uint32_t magic32 = 0x98765432;
21701.54Skamil	uint64_t magic64 = 0xabcdef0123456789;
21711.1Skamil
21721.54Skamil	struct ptrace_io_desc io;
21731.1Skamil#if defined(TWAIT_HAVE_STATUS)
21741.1Skamil	int status;
21751.1Skamil#endif
21761.60Skre	/* 513 is just enough, for the purposes of ATF it's good enough */
21771.60Skre	AuxInfo ai[513], *aip;
21781.55Schristos
21791.55Schristos	ATF_REQUIRE(size < sizeof(ai));
21801.1Skamil
21811.54Skamil	/* Prepare variables for .TEXT transfers */
21821.54Skamil	switch (type) {
21831.54Skamil	case BYTES_TRANSFER_TEXT:
21841.54Skamil		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
21851.54Skamil		break;
21861.54Skamil	case BYTES_TRANSFER_TEXTIO:
21871.54Skamil		switch (size) {
21881.54Skamil		case 8:
21891.54Skamil			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
21901.54Skamil			break;
21911.54Skamil		case 16:
21921.54Skamil			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
21931.54Skamil			break;
21941.54Skamil		case 32:
21951.54Skamil			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
21961.54Skamil			break;
21971.54Skamil		case 64:
21981.54Skamil			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
21991.54Skamil			break;
22001.54Skamil		}
22011.54Skamil		break;
22021.54Skamil	default:
22031.54Skamil		break;
22041.54Skamil	}
22051.1Skamil
22061.54Skamil	/* Prepare variables for PIOD and AUXV transfers */
22071.54Skamil	switch (type) {
22081.54Skamil	case BYTES_TRANSFER_TEXTIO:
22091.54Skamil	case BYTES_TRANSFER_DATAIO:
22101.54Skamil		io.piod_op = operation;
22111.54Skamil		switch (size) {
22121.54Skamil		case 8:
22131.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22141.54Skamil			               (void *)bytes_transfer_dummy :
22151.54Skamil			               &lookup_me8;
22161.54Skamil			io.piod_addr = &lookup_me8;
22171.54Skamil			io.piod_len = sizeof(lookup_me8);
22181.54Skamil			break;
22191.54Skamil		case 16:
22201.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22211.54Skamil			               (void *)bytes_transfer_dummy :
22221.54Skamil			               &lookup_me16;
22231.54Skamil			io.piod_addr = &lookup_me16;
22241.54Skamil			io.piod_len = sizeof(lookup_me16);
22251.54Skamil			break;
22261.54Skamil		case 32:
22271.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22281.54Skamil			               (void *)bytes_transfer_dummy :
22291.54Skamil			               &lookup_me32;
22301.54Skamil			io.piod_addr = &lookup_me32;
22311.54Skamil			io.piod_len = sizeof(lookup_me32);
22321.54Skamil			break;
22331.54Skamil		case 64:
22341.54Skamil			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
22351.54Skamil			               (void *)bytes_transfer_dummy :
22361.54Skamil			               &lookup_me64;
22371.54Skamil			io.piod_addr = &lookup_me64;
22381.54Skamil			io.piod_len = sizeof(lookup_me64);
22391.54Skamil			break;
22401.54Skamil		default:
22411.54Skamil			break;
22421.54Skamil		}
22431.54Skamil		break;
22441.54Skamil	case BYTES_TRANSFER_AUXV:
22451.54Skamil		io.piod_op = operation;
22461.54Skamil		io.piod_offs = 0;
22471.54Skamil		io.piod_addr = ai;
22481.54Skamil		io.piod_len = size;
22491.54Skamil		break;
22501.54Skamil	default:
22511.54Skamil		break;
22521.1Skamil	}
22531.1Skamil
22541.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22551.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22561.1Skamil	if (child == 0) {
22571.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22581.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22591.1Skamil
22601.54Skamil		switch (type) {
22611.54Skamil		case BYTES_TRANSFER_DATA:
22621.54Skamil			switch (operation) {
22631.54Skamil			case PT_READ_D:
22641.54Skamil			case PT_READ_I:
22651.54Skamil				lookup_me = magic;
22661.54Skamil				break;
22671.54Skamil			default:
22681.54Skamil				break;
22691.54Skamil			}
22701.54Skamil			break;
22711.54Skamil		case BYTES_TRANSFER_DATAIO:
22721.54Skamil			switch (operation) {
22731.54Skamil			case PIOD_READ_D:
22741.54Skamil			case PIOD_READ_I:
22751.54Skamil				switch (size) {
22761.54Skamil				case 8:
22771.54Skamil					lookup_me8 = magic8;
22781.54Skamil					break;
22791.54Skamil				case 16:
22801.54Skamil					lookup_me16 = magic16;
22811.54Skamil					break;
22821.54Skamil				case 32:
22831.54Skamil					lookup_me32 = magic32;
22841.54Skamil					break;
22851.54Skamil				case 64:
22861.54Skamil					lookup_me64 = magic64;
22871.54Skamil					break;
22881.54Skamil				default:
22891.54Skamil					break;
22901.54Skamil				}
22911.54Skamil				break;
22921.54Skamil			default:
22931.54Skamil				break;
22941.54Skamil			}
22951.54Skamil		default:
22961.54Skamil			break;
22971.54Skamil		}
22981.54Skamil
22991.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23001.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23011.1Skamil
23021.54Skamil		/* Handle PIOD and PT separately as operation values overlap */
23031.54Skamil		switch (type) {
23041.54Skamil		case BYTES_TRANSFER_DATA:
23051.54Skamil			switch (operation) {
23061.54Skamil			case PT_WRITE_D:
23071.54Skamil			case PT_WRITE_I:
23081.54Skamil				FORKEE_ASSERT_EQ(lookup_me, magic);
23091.54Skamil				break;
23101.54Skamil			default:
23111.54Skamil				break;
23121.54Skamil			}
23131.54Skamil			break;
23141.54Skamil		case BYTES_TRANSFER_DATAIO:
23151.54Skamil			switch (operation) {
23161.54Skamil			case PIOD_WRITE_D:
23171.54Skamil			case PIOD_WRITE_I:
23181.54Skamil				switch (size) {
23191.54Skamil				case 8:
23201.54Skamil					FORKEE_ASSERT_EQ(lookup_me8, magic8);
23211.54Skamil					break;
23221.54Skamil				case 16:
23231.54Skamil					FORKEE_ASSERT_EQ(lookup_me16, magic16);
23241.54Skamil					break;
23251.54Skamil				case 32:
23261.54Skamil					FORKEE_ASSERT_EQ(lookup_me32, magic32);
23271.54Skamil					break;
23281.54Skamil				case 64:
23291.54Skamil					FORKEE_ASSERT_EQ(lookup_me64, magic64);
23301.54Skamil					break;
23311.54Skamil				default:
23321.54Skamil					break;
23331.54Skamil				}
23341.54Skamil				break;
23351.54Skamil			default:
23361.54Skamil				break;
23371.54Skamil			}
23381.54Skamil			break;
23391.54Skamil		case BYTES_TRANSFER_TEXT:
23401.54Skamil			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
23411.54Skamil			                     sizeof(magic)) == 0);
23421.54Skamil			break;
23431.54Skamil		case BYTES_TRANSFER_TEXTIO:
23441.54Skamil			switch (size) {
23451.54Skamil			case 8:
23461.54Skamil				FORKEE_ASSERT(memcmp(&magic8,
23471.54Skamil				                     bytes_transfer_dummy,
23481.54Skamil				                     sizeof(magic8)) == 0);
23491.54Skamil				break;
23501.54Skamil			case 16:
23511.54Skamil				FORKEE_ASSERT(memcmp(&magic16,
23521.54Skamil				                     bytes_transfer_dummy,
23531.54Skamil				                     sizeof(magic16)) == 0);
23541.54Skamil				break;
23551.54Skamil			case 32:
23561.54Skamil				FORKEE_ASSERT(memcmp(&magic32,
23571.54Skamil				                     bytes_transfer_dummy,
23581.54Skamil				                     sizeof(magic32)) == 0);
23591.54Skamil				break;
23601.54Skamil			case 64:
23611.54Skamil				FORKEE_ASSERT(memcmp(&magic64,
23621.54Skamil				                     bytes_transfer_dummy,
23631.54Skamil				                     sizeof(magic64)) == 0);
23641.54Skamil				break;
23651.54Skamil			}
23661.54Skamil			break;
23671.54Skamil		default:
23681.54Skamil			break;
23691.54Skamil		}
23701.54Skamil
23711.13Schristos		DPRINTF("Before exiting of the child process\n");
23721.1Skamil		_exit(exitval);
23731.1Skamil	}
23741.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23751.1Skamil
23761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23781.1Skamil
23791.1Skamil	validate_status_stopped(status, sigval);
23801.1Skamil
23811.54Skamil	/* Check PaX MPROTECT */
23821.54Skamil	if (!can_we_write_to_text(child)) {
23831.54Skamil		switch (type) {
23841.54Skamil		case BYTES_TRANSFER_TEXTIO:
23851.54Skamil			switch (operation) {
23861.54Skamil			case PIOD_WRITE_D:
23871.54Skamil			case PIOD_WRITE_I:
23881.54Skamil				skip = true;
23891.54Skamil				break;
23901.54Skamil			default:
23911.54Skamil				break;
23921.54Skamil			}
23931.54Skamil			break;
23941.54Skamil		case BYTES_TRANSFER_TEXT:
23951.54Skamil			switch (operation) {
23961.54Skamil			case PT_WRITE_D:
23971.54Skamil			case PT_WRITE_I:
23981.54Skamil				skip = true;
23991.54Skamil				break;
24001.54Skamil			default:
24011.54Skamil				break;
24021.54Skamil			}
24031.54Skamil			break;
24041.54Skamil		default:
24051.54Skamil			break;
24061.54Skamil		}
24071.54Skamil	}
24081.1Skamil
24091.54Skamil	/* Bailout cleanly killing the child process */
24101.54Skamil	if (skip) {
24111.54Skamil		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
24121.54Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24131.54Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
24141.54Skamil		                      child);
24151.1Skamil
24161.54Skamil		validate_status_signaled(status, SIGKILL, 0);
24171.1Skamil
24181.54Skamil		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
24191.54Skamil	}
24201.1Skamil
24211.54Skamil	DPRINTF("Calling operation to transfer bytes between child=%d and "
24221.54Skamil	       "parent=%d\n", child, getpid());
24231.1Skamil
24241.54Skamil	switch (type) {
24251.54Skamil	case BYTES_TRANSFER_TEXTIO:
24261.54Skamil	case BYTES_TRANSFER_DATAIO:
24271.54Skamil	case BYTES_TRANSFER_AUXV:
24281.54Skamil		switch (operation) {
24291.54Skamil		case PIOD_WRITE_D:
24301.54Skamil		case PIOD_WRITE_I:
24311.54Skamil			switch (size) {
24321.54Skamil			case 8:
24331.54Skamil				lookup_me8 = magic8;
24341.54Skamil				break;
24351.54Skamil			case 16:
24361.54Skamil				lookup_me16 = magic16;
24371.54Skamil				break;
24381.54Skamil			case 32:
24391.54Skamil				lookup_me32 = magic32;
24401.54Skamil				break;
24411.54Skamil			case 64:
24421.54Skamil				lookup_me64 = magic64;
24431.54Skamil				break;
24441.54Skamil			default:
24451.54Skamil				break;
24461.54Skamil			}
24471.54Skamil			break;
24481.54Skamil		default:
24491.54Skamil			break;
24501.54Skamil		}
24511.54Skamil		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
24521.54Skamil		switch (operation) {
24531.54Skamil		case PIOD_READ_D:
24541.54Skamil		case PIOD_READ_I:
24551.54Skamil			switch (size) {
24561.54Skamil			case 8:
24571.54Skamil				ATF_REQUIRE_EQ(lookup_me8, magic8);
24581.54Skamil				break;
24591.54Skamil			case 16:
24601.54Skamil				ATF_REQUIRE_EQ(lookup_me16, magic16);
24611.54Skamil				break;
24621.54Skamil			case 32:
24631.54Skamil				ATF_REQUIRE_EQ(lookup_me32, magic32);
24641.54Skamil				break;
24651.54Skamil			case 64:
24661.54Skamil				ATF_REQUIRE_EQ(lookup_me64, magic64);
24671.54Skamil				break;
24681.54Skamil			default:
24691.54Skamil				break;
24701.54Skamil			}
24711.54Skamil			break;
24721.54Skamil		case PIOD_READ_AUXV:
24731.54Skamil			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
24741.54Skamil			        io.piod_len);
24751.54Skamil			ATF_REQUIRE(io.piod_len > 0);
24761.54Skamil			for (aip = ai; aip->a_type != AT_NULL; aip++)
24771.54Skamil				DPRINTF("a_type=%#llx a_v=%#llx\n",
24781.54Skamil				    (long long int)aip->a_type,
24791.54Skamil				    (long long int)aip->a_v);
24801.54Skamil			break;
24811.54Skamil		default:
24821.54Skamil			break;
24831.54Skamil		}
24841.54Skamil		break;
24851.54Skamil	case BYTES_TRANSFER_TEXT:
24861.54Skamil		switch (operation) {
24871.54Skamil		case PT_READ_D:
24881.54Skamil		case PT_READ_I:
24891.54Skamil			errno = 0;
24901.54Skamil			lookup_me = ptrace(operation, child,
24911.54Skamil			                   bytes_transfer_dummy, 0);
24921.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
24931.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
24941.54Skamil			break;
24951.54Skamil		case PT_WRITE_D:
24961.54Skamil		case PT_WRITE_I:
24971.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child,
24981.54Skamil			                       bytes_transfer_dummy, magic)
24991.54Skamil			                != -1);
25001.54Skamil			break;
25011.54Skamil		default:
25021.54Skamil			break;
25031.54Skamil		}
25041.54Skamil		break;
25051.54Skamil	case BYTES_TRANSFER_DATA:
25061.54Skamil		switch (operation) {
25071.54Skamil		case PT_READ_D:
25081.54Skamil		case PT_READ_I:
25091.54Skamil			errno = 0;
25101.54Skamil			lookup_me = ptrace(operation, child, &lookup_me, 0);
25111.54Skamil			ATF_REQUIRE_EQ(lookup_me, magic);
25121.54Skamil			SYSCALL_REQUIRE_ERRNO(errno, 0);
25131.54Skamil			break;
25141.54Skamil		case PT_WRITE_D:
25151.54Skamil		case PT_WRITE_I:
25161.54Skamil			lookup_me = magic;
25171.54Skamil			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
25181.54Skamil			                       magic) != -1);
25191.54Skamil			break;
25201.54Skamil		default:
25211.54Skamil			break;
25221.54Skamil		}
25231.54Skamil		break;
25241.54Skamil	default:
25251.54Skamil		break;
25261.54Skamil	}
25271.1Skamil
25281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25291.1Skamil	    "without signal to be sent\n");
25301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25311.1Skamil
25321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25341.1Skamil
25351.1Skamil	validate_status_exited(status, exitval);
25361.1Skamil
25371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25391.1Skamil}
25401.1Skamil
25411.61Skre#define BYTES_TRANSFER(test, operation, size, type)			\
25421.61SkreATF_TC(test);								\
25431.61SkreATF_TC_HEAD(test, tc)							\
25441.61Skre{									\
25451.61Skre	atf_tc_set_md_var(tc, "descr",					\
25461.61Skre	    "Verify bytes transfer operation" #operation " and size " #size \
25471.61Skre	    " of type " #type);						\
25481.61Skre}									\
25491.61Skre									\
25501.61SkreATF_TC_BODY(test, tc)							\
25511.61Skre{									\
25521.61Skre									\
25531.61Skre	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
25541.1Skamil}
25551.1Skamil
25561.54Skamil// DATA
25571.1Skamil
25581.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
25591.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
25601.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
25611.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
25621.54Skamil
25631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
25641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
25651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
25661.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
25671.54Skamil
25681.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
25691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
25701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
25711.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
25721.54Skamil
25731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
25741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
25751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
25761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
25771.54Skamil
25781.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
25791.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
25801.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
25811.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
25821.54Skamil
25831.54Skamil// TEXT
25841.54Skamil
25851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
25861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
25871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
25881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
25891.54Skamil
25901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
25911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
25921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
25931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
25941.54Skamil
25951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
25961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
25971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
25981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
25991.54Skamil
26001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
26011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
26021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
26031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
26041.54Skamil
26051.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
26061.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
26071.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
26081.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
26091.1Skamil
26101.54Skamil// AUXV
26111.1Skamil
26121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
26131.1Skamil
26141.54Skamil/// ----------------------------------------------------------------------------
26151.1Skamil
26161.1Skamil#if defined(HAVE_GPREGS)
26171.1SkamilATF_TC(regs1);
26181.1SkamilATF_TC_HEAD(regs1, tc)
26191.1Skamil{
26201.1Skamil	atf_tc_set_md_var(tc, "descr",
26211.1Skamil	    "Verify plain PT_GETREGS call without further steps");
26221.1Skamil}
26231.1Skamil
26241.1SkamilATF_TC_BODY(regs1, tc)
26251.1Skamil{
26261.1Skamil	const int exitval = 5;
26271.1Skamil	const int sigval = SIGSTOP;
26281.1Skamil	pid_t child, wpid;
26291.1Skamil#if defined(TWAIT_HAVE_STATUS)
26301.1Skamil	int status;
26311.1Skamil#endif
26321.1Skamil	struct reg r;
26331.1Skamil
26341.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26351.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26361.1Skamil	if (child == 0) {
26371.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26381.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26391.1Skamil
26401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26421.1Skamil
26431.13Schristos		DPRINTF("Before exiting of the child process\n");
26441.1Skamil		_exit(exitval);
26451.1Skamil	}
26461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26471.1Skamil
26481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26501.1Skamil
26511.1Skamil	validate_status_stopped(status, sigval);
26521.1Skamil
26531.13Schristos	DPRINTF("Call GETREGS for the child process\n");
26541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
26551.1Skamil
26561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26571.1Skamil	    "without signal to be sent\n");
26581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26591.1Skamil
26601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26621.1Skamil
26631.1Skamil	validate_status_exited(status, exitval);
26641.1Skamil
26651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26671.1Skamil}
26681.1Skamil#endif
26691.1Skamil
26701.1Skamil#if defined(HAVE_GPREGS)
26711.1SkamilATF_TC(regs2);
26721.1SkamilATF_TC_HEAD(regs2, tc)
26731.1Skamil{
26741.1Skamil	atf_tc_set_md_var(tc, "descr",
26751.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
26761.1Skamil}
26771.1Skamil
26781.1SkamilATF_TC_BODY(regs2, tc)
26791.1Skamil{
26801.1Skamil	const int exitval = 5;
26811.1Skamil	const int sigval = SIGSTOP;
26821.1Skamil	pid_t child, wpid;
26831.1Skamil#if defined(TWAIT_HAVE_STATUS)
26841.1Skamil	int status;
26851.1Skamil#endif
26861.1Skamil	struct reg r;
26871.1Skamil
26881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26901.1Skamil	if (child == 0) {
26911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26931.1Skamil
26941.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26951.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26961.1Skamil
26971.13Schristos		DPRINTF("Before exiting of the child process\n");
26981.1Skamil		_exit(exitval);
26991.1Skamil	}
27001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27011.1Skamil
27021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27041.1Skamil
27051.1Skamil	validate_status_stopped(status, sigval);
27061.1Skamil
27071.13Schristos	DPRINTF("Call GETREGS for the child process\n");
27081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
27091.1Skamil
27101.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
27111.1Skamil
27121.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27131.1Skamil	    "without signal to be sent\n");
27141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27151.1Skamil
27161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27181.1Skamil
27191.1Skamil	validate_status_exited(status, exitval);
27201.1Skamil
27211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27221.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27231.1Skamil}
27241.1Skamil#endif
27251.1Skamil
27261.1Skamil#if defined(HAVE_GPREGS)
27271.1SkamilATF_TC(regs3);
27281.1SkamilATF_TC_HEAD(regs3, tc)
27291.1Skamil{
27301.1Skamil	atf_tc_set_md_var(tc, "descr",
27311.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
27321.1Skamil}
27331.1Skamil
27341.1SkamilATF_TC_BODY(regs3, tc)
27351.1Skamil{
27361.1Skamil	const int exitval = 5;
27371.1Skamil	const int sigval = SIGSTOP;
27381.1Skamil	pid_t child, wpid;
27391.1Skamil#if defined(TWAIT_HAVE_STATUS)
27401.1Skamil	int status;
27411.1Skamil#endif
27421.1Skamil	struct reg r;
27431.1Skamil
27441.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27451.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27461.1Skamil	if (child == 0) {
27471.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27481.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27491.1Skamil
27501.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27511.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27521.1Skamil
27531.13Schristos		DPRINTF("Before exiting of the child process\n");
27541.1Skamil		_exit(exitval);
27551.1Skamil	}
27561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27571.1Skamil
27581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27601.1Skamil
27611.1Skamil	validate_status_stopped(status, sigval);
27621.1Skamil
27631.13Schristos	DPRINTF("Call GETREGS for the child process\n");
27641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
27651.1Skamil
27661.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
27671.1Skamil
27681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27691.1Skamil	    "without signal to be sent\n");
27701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27711.1Skamil
27721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27741.1Skamil
27751.1Skamil	validate_status_exited(status, exitval);
27761.1Skamil
27771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27791.1Skamil}
27801.1Skamil#endif
27811.1Skamil
27821.1Skamil#if defined(HAVE_GPREGS)
27831.1SkamilATF_TC(regs4);
27841.1SkamilATF_TC_HEAD(regs4, tc)
27851.1Skamil{
27861.1Skamil	atf_tc_set_md_var(tc, "descr",
27871.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
27881.1Skamil}
27891.1Skamil
27901.1SkamilATF_TC_BODY(regs4, tc)
27911.1Skamil{
27921.1Skamil	const int exitval = 5;
27931.1Skamil	const int sigval = SIGSTOP;
27941.1Skamil	pid_t child, wpid;
27951.1Skamil#if defined(TWAIT_HAVE_STATUS)
27961.1Skamil	int status;
27971.1Skamil#endif
27981.1Skamil	struct reg r;
27991.1Skamil
28001.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28011.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28021.1Skamil	if (child == 0) {
28031.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28041.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28051.1Skamil
28061.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28071.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28081.1Skamil
28091.13Schristos		DPRINTF("Before exiting of the child process\n");
28101.1Skamil		_exit(exitval);
28111.1Skamil	}
28121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28131.1Skamil
28141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28161.1Skamil
28171.1Skamil	validate_status_stopped(status, sigval);
28181.1Skamil
28191.13Schristos	DPRINTF("Call GETREGS for the child process\n");
28201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28211.1Skamil
28221.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
28231.1Skamil
28241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28251.1Skamil	    "without signal to be sent\n");
28261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28271.1Skamil
28281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28301.1Skamil
28311.1Skamil	validate_status_exited(status, exitval);
28321.1Skamil
28331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28351.1Skamil}
28361.1Skamil#endif
28371.1Skamil
28381.1Skamil#if defined(HAVE_GPREGS)
28391.1SkamilATF_TC(regs5);
28401.1SkamilATF_TC_HEAD(regs5, tc)
28411.1Skamil{
28421.1Skamil	atf_tc_set_md_var(tc, "descr",
28431.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
28441.1Skamil}
28451.1Skamil
28461.1SkamilATF_TC_BODY(regs5, tc)
28471.1Skamil{
28481.1Skamil	const int exitval = 5;
28491.1Skamil	const int sigval = SIGSTOP;
28501.1Skamil	pid_t child, wpid;
28511.1Skamil#if defined(TWAIT_HAVE_STATUS)
28521.1Skamil	int status;
28531.1Skamil#endif
28541.1Skamil	struct reg r;
28551.1Skamil
28561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28581.1Skamil	if (child == 0) {
28591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28611.1Skamil
28621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28641.1Skamil
28651.13Schristos		DPRINTF("Before exiting of the child process\n");
28661.1Skamil		_exit(exitval);
28671.1Skamil	}
28681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28691.1Skamil
28701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28721.1Skamil
28731.1Skamil	validate_status_stopped(status, sigval);
28741.1Skamil
28751.13Schristos	DPRINTF("Call GETREGS for the child process\n");
28761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28771.1Skamil
28781.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
28791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
28801.1Skamil
28811.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28821.1Skamil	    "without signal to be sent\n");
28831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28841.1Skamil
28851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28871.1Skamil
28881.1Skamil	validate_status_exited(status, exitval);
28891.1Skamil
28901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28921.1Skamil}
28931.1Skamil#endif
28941.1Skamil
28951.1Skamil#if defined(HAVE_FPREGS)
28961.1SkamilATF_TC(fpregs1);
28971.1SkamilATF_TC_HEAD(fpregs1, tc)
28981.1Skamil{
28991.1Skamil	atf_tc_set_md_var(tc, "descr",
29001.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
29011.1Skamil}
29021.1Skamil
29031.1SkamilATF_TC_BODY(fpregs1, tc)
29041.1Skamil{
29051.1Skamil	const int exitval = 5;
29061.1Skamil	const int sigval = SIGSTOP;
29071.1Skamil	pid_t child, wpid;
29081.1Skamil#if defined(TWAIT_HAVE_STATUS)
29091.1Skamil	int status;
29101.1Skamil#endif
29111.1Skamil	struct fpreg r;
29121.1Skamil
29131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29151.1Skamil	if (child == 0) {
29161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29181.1Skamil
29191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29211.1Skamil
29221.13Schristos		DPRINTF("Before exiting of the child process\n");
29231.1Skamil		_exit(exitval);
29241.1Skamil	}
29251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29261.1Skamil
29271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29291.1Skamil
29301.1Skamil	validate_status_stopped(status, sigval);
29311.1Skamil
29321.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
29331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
29341.1Skamil
29351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29361.1Skamil	    "without signal to be sent\n");
29371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29381.1Skamil
29391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29411.1Skamil
29421.1Skamil	validate_status_exited(status, exitval);
29431.1Skamil
29441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29461.1Skamil}
29471.1Skamil#endif
29481.1Skamil
29491.1Skamil#if defined(HAVE_FPREGS)
29501.1SkamilATF_TC(fpregs2);
29511.1SkamilATF_TC_HEAD(fpregs2, tc)
29521.1Skamil{
29531.1Skamil	atf_tc_set_md_var(tc, "descr",
29541.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
29551.1Skamil	    "regs");
29561.1Skamil}
29571.1Skamil
29581.1SkamilATF_TC_BODY(fpregs2, tc)
29591.1Skamil{
29601.1Skamil	const int exitval = 5;
29611.1Skamil	const int sigval = SIGSTOP;
29621.1Skamil	pid_t child, wpid;
29631.1Skamil#if defined(TWAIT_HAVE_STATUS)
29641.1Skamil	int status;
29651.1Skamil#endif
29661.1Skamil	struct fpreg r;
29671.1Skamil
29681.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29691.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29701.1Skamil	if (child == 0) {
29711.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29721.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29731.1Skamil
29741.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29751.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29761.1Skamil
29771.13Schristos		DPRINTF("Before exiting of the child process\n");
29781.1Skamil		_exit(exitval);
29791.1Skamil	}
29801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29811.1Skamil
29821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29841.1Skamil
29851.1Skamil	validate_status_stopped(status, sigval);
29861.1Skamil
29871.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
29881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
29891.1Skamil
29901.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
29911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
29921.1Skamil
29931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29941.1Skamil	    "without signal to be sent\n");
29951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29961.1Skamil
29971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29991.1Skamil
30001.1Skamil	validate_status_exited(status, exitval);
30011.1Skamil
30021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30041.1Skamil}
30051.1Skamil#endif
30061.1Skamil
30071.1Skamil#if defined(PT_STEP)
30081.1Skamilstatic void
30091.2Skamilptrace_step(int N, int setstep)
30101.1Skamil{
30111.1Skamil	const int exitval = 5;
30121.1Skamil	const int sigval = SIGSTOP;
30131.1Skamil	pid_t child, wpid;
30141.1Skamil#if defined(TWAIT_HAVE_STATUS)
30151.1Skamil	int status;
30161.1Skamil#endif
30171.1Skamil	int happy;
30181.1Skamil
30191.1Skamil#if defined(__arm__)
30201.1Skamil	/* PT_STEP not supported on arm 32-bit */
30211.1Skamil	atf_tc_expect_fail("PR kern/52119");
30221.1Skamil#endif
30231.1Skamil
30241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30261.1Skamil	if (child == 0) {
30271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30291.1Skamil
30301.1Skamil		happy = check_happy(999);
30311.1Skamil
30321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30341.1Skamil
30351.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
30361.1Skamil
30371.13Schristos		DPRINTF("Before exiting of the child process\n");
30381.1Skamil		_exit(exitval);
30391.1Skamil	}
30401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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), child);
30441.1Skamil
30451.1Skamil	validate_status_stopped(status, sigval);
30461.1Skamil
30471.1Skamil	while (N --> 0) {
30481.2Skamil		if (setstep) {
30491.13Schristos			DPRINTF("Before resuming the child process where it "
30501.2Skamil			    "left off and without signal to be sent (use "
30511.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
30521.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
30531.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
30541.2Skamil			    != -1);
30551.2Skamil		} else {
30561.13Schristos			DPRINTF("Before resuming the child process where it "
30571.2Skamil			    "left off and without signal to be sent (use "
30581.2Skamil			    "PT_STEP)\n");
30591.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
30601.2Skamil			    != -1);
30611.2Skamil		}
30621.1Skamil
30631.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30641.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
30651.1Skamil		    child);
30661.1Skamil
30671.1Skamil		validate_status_stopped(status, SIGTRAP);
30681.2Skamil
30691.2Skamil		if (setstep) {
30701.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
30711.2Skamil		}
30721.1Skamil	}
30731.1Skamil
30741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30751.1Skamil	    "without signal to be sent\n");
30761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30771.1Skamil
30781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30801.1Skamil
30811.1Skamil	validate_status_exited(status, exitval);
30821.1Skamil
30831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30841.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30851.1Skamil}
30861.1Skamil#endif
30871.1Skamil
30881.1Skamil#if defined(PT_STEP)
30891.1SkamilATF_TC(step1);
30901.1SkamilATF_TC_HEAD(step1, tc)
30911.1Skamil{
30921.1Skamil	atf_tc_set_md_var(tc, "descr",
30931.1Skamil	    "Verify single PT_STEP call");
30941.1Skamil}
30951.1Skamil
30961.1SkamilATF_TC_BODY(step1, tc)
30971.1Skamil{
30981.2Skamil	ptrace_step(1, 0);
30991.1Skamil}
31001.1Skamil#endif
31011.1Skamil
31021.1Skamil#if defined(PT_STEP)
31031.1SkamilATF_TC(step2);
31041.1SkamilATF_TC_HEAD(step2, tc)
31051.1Skamil{
31061.1Skamil	atf_tc_set_md_var(tc, "descr",
31071.1Skamil	    "Verify PT_STEP called twice");
31081.1Skamil}
31091.1Skamil
31101.1SkamilATF_TC_BODY(step2, tc)
31111.1Skamil{
31121.2Skamil	ptrace_step(2, 0);
31131.1Skamil}
31141.1Skamil#endif
31151.1Skamil
31161.1Skamil#if defined(PT_STEP)
31171.1SkamilATF_TC(step3);
31181.1SkamilATF_TC_HEAD(step3, tc)
31191.1Skamil{
31201.1Skamil	atf_tc_set_md_var(tc, "descr",
31211.1Skamil	    "Verify PT_STEP called three times");
31221.1Skamil}
31231.1Skamil
31241.1SkamilATF_TC_BODY(step3, tc)
31251.1Skamil{
31261.2Skamil	ptrace_step(3, 0);
31271.1Skamil}
31281.1Skamil#endif
31291.1Skamil
31301.1Skamil#if defined(PT_STEP)
31311.1SkamilATF_TC(step4);
31321.1SkamilATF_TC_HEAD(step4, tc)
31331.1Skamil{
31341.1Skamil	atf_tc_set_md_var(tc, "descr",
31351.1Skamil	    "Verify PT_STEP called four times");
31361.1Skamil}
31371.1Skamil
31381.1SkamilATF_TC_BODY(step4, tc)
31391.1Skamil{
31401.2Skamil	ptrace_step(4, 0);
31411.2Skamil}
31421.2Skamil#endif
31431.2Skamil
31441.2Skamil#if defined(PT_STEP)
31451.2SkamilATF_TC(setstep1);
31461.2SkamilATF_TC_HEAD(setstep1, tc)
31471.2Skamil{
31481.2Skamil	atf_tc_set_md_var(tc, "descr",
31491.2Skamil	    "Verify single PT_SETSTEP call");
31501.2Skamil}
31511.2Skamil
31521.2SkamilATF_TC_BODY(setstep1, tc)
31531.2Skamil{
31541.2Skamil	ptrace_step(1, 1);
31551.2Skamil}
31561.2Skamil#endif
31571.2Skamil
31581.2Skamil#if defined(PT_STEP)
31591.2SkamilATF_TC(setstep2);
31601.2SkamilATF_TC_HEAD(setstep2, tc)
31611.2Skamil{
31621.2Skamil	atf_tc_set_md_var(tc, "descr",
31631.2Skamil	    "Verify PT_SETSTEP called twice");
31641.2Skamil}
31651.2Skamil
31661.2SkamilATF_TC_BODY(setstep2, tc)
31671.2Skamil{
31681.2Skamil	ptrace_step(2, 1);
31691.2Skamil}
31701.2Skamil#endif
31711.2Skamil
31721.2Skamil#if defined(PT_STEP)
31731.2SkamilATF_TC(setstep3);
31741.2SkamilATF_TC_HEAD(setstep3, tc)
31751.2Skamil{
31761.2Skamil	atf_tc_set_md_var(tc, "descr",
31771.2Skamil	    "Verify PT_SETSTEP called three times");
31781.2Skamil}
31791.2Skamil
31801.2SkamilATF_TC_BODY(setstep3, tc)
31811.2Skamil{
31821.2Skamil	ptrace_step(3, 1);
31831.2Skamil}
31841.2Skamil#endif
31851.2Skamil
31861.2Skamil#if defined(PT_STEP)
31871.2SkamilATF_TC(setstep4);
31881.2SkamilATF_TC_HEAD(setstep4, tc)
31891.2Skamil{
31901.2Skamil	atf_tc_set_md_var(tc, "descr",
31911.2Skamil	    "Verify PT_SETSTEP called four times");
31921.2Skamil}
31931.2Skamil
31941.2SkamilATF_TC_BODY(setstep4, tc)
31951.2Skamil{
31961.2Skamil	ptrace_step(4, 1);
31971.1Skamil}
31981.1Skamil#endif
31991.1Skamil
32001.1SkamilATF_TC(kill1);
32011.1SkamilATF_TC_HEAD(kill1, tc)
32021.1Skamil{
32031.1Skamil	atf_tc_set_md_var(tc, "descr",
32041.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
32051.1Skamil}
32061.1Skamil
32071.1SkamilATF_TC_BODY(kill1, tc)
32081.1Skamil{
32091.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
32101.1Skamil	pid_t child, wpid;
32111.1Skamil#if defined(TWAIT_HAVE_STATUS)
32121.1Skamil	int status;
32131.1Skamil#endif
32141.1Skamil
32151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32171.1Skamil	if (child == 0) {
32181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32201.1Skamil
32211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32231.1Skamil
32241.1Skamil		/* NOTREACHED */
32251.1Skamil		FORKEE_ASSERTX(0 &&
32261.1Skamil		    "Child should be terminated by a signal from its parent");
32271.1Skamil	}
32281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32291.1Skamil
32301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32321.1Skamil
32331.1Skamil	validate_status_stopped(status, sigval);
32341.1Skamil
32351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32361.1Skamil	    "without signal to be sent\n");
32371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
32381.1Skamil
32391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32411.1Skamil
32421.1Skamil	validate_status_signaled(status, sigsent, 0);
32431.1Skamil
32441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32461.1Skamil}
32471.1Skamil
32481.1SkamilATF_TC(kill2);
32491.1SkamilATF_TC_HEAD(kill2, tc)
32501.1Skamil{
32511.1Skamil	atf_tc_set_md_var(tc, "descr",
32521.1Skamil	    "Verify that PT_KILL terminates child");
32531.1Skamil}
32541.1Skamil
32551.1SkamilATF_TC_BODY(kill2, tc)
32561.1Skamil{
32571.1Skamil	const int sigval = SIGSTOP;
32581.1Skamil	pid_t child, wpid;
32591.1Skamil#if defined(TWAIT_HAVE_STATUS)
32601.1Skamil	int status;
32611.1Skamil#endif
32621.1Skamil
32631.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
32641.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
32651.1Skamil	if (child == 0) {
32661.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
32671.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
32681.1Skamil
32691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
32701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
32711.1Skamil
32721.1Skamil		/* NOTREACHED */
32731.1Skamil		FORKEE_ASSERTX(0 &&
32741.1Skamil		    "Child should be terminated by a signal from its parent");
32751.1Skamil	}
32761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
32771.1Skamil
32781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32801.1Skamil
32811.1Skamil	validate_status_stopped(status, sigval);
32821.1Skamil
32831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32841.1Skamil	    "without signal to be sent\n");
32851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
32861.1Skamil
32871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32891.1Skamil
32901.1Skamil	validate_status_signaled(status, SIGKILL, 0);
32911.1Skamil
32921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32941.1Skamil}
32951.1Skamil
32961.1SkamilATF_TC(lwpinfo1);
32971.1SkamilATF_TC_HEAD(lwpinfo1, tc)
32981.1Skamil{
32991.1Skamil	atf_tc_set_md_var(tc, "descr",
33001.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
33011.1Skamil}
33021.1Skamil
33031.1SkamilATF_TC_BODY(lwpinfo1, tc)
33041.1Skamil{
33051.1Skamil	const int exitval = 5;
33061.1Skamil	const int sigval = SIGSTOP;
33071.1Skamil	pid_t child, wpid;
33081.1Skamil#if defined(TWAIT_HAVE_STATUS)
33091.1Skamil	int status;
33101.1Skamil#endif
33111.1Skamil	struct ptrace_lwpinfo info = {0, 0};
33121.1Skamil
33131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33151.1Skamil	if (child == 0) {
33161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33181.1Skamil
33191.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33201.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33211.1Skamil
33221.13Schristos		DPRINTF("Before exiting of the child process\n");
33231.1Skamil		_exit(exitval);
33241.1Skamil	}
33251.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33261.1Skamil
33271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33291.1Skamil
33301.1Skamil	validate_status_stopped(status, sigval);
33311.1Skamil
33321.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
33341.1Skamil
33351.13Schristos	DPRINTF("Assert that there exists a thread\n");
33361.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
33371.1Skamil
33381.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
33391.1Skamil	    info.pl_lwpid);
33401.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
33411.1Skamil	    "Received event %d != expected event %d",
33421.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
33431.1Skamil
33441.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
33451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
33461.1Skamil
33471.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
33481.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
33491.1Skamil
33501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33511.1Skamil	    "without signal to be sent\n");
33521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33531.1Skamil
33541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33551.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33561.1Skamil
33571.1Skamil	validate_status_exited(status, exitval);
33581.1Skamil
33591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33601.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33611.1Skamil}
33621.1Skamil
33631.1Skamil#if defined(TWAIT_HAVE_PID)
33641.1SkamilATF_TC(lwpinfo2);
33651.1SkamilATF_TC_HEAD(lwpinfo2, tc)
33661.1Skamil{
33671.1Skamil	atf_tc_set_md_var(tc, "descr",
33681.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
33691.1Skamil	    "tracer)");
33701.1Skamil}
33711.1Skamil
33721.1SkamilATF_TC_BODY(lwpinfo2, tc)
33731.1Skamil{
33741.1Skamil	struct msg_fds parent_tracee, parent_tracer;
33751.1Skamil	const int exitval_tracee = 5;
33761.1Skamil	const int exitval_tracer = 10;
33771.1Skamil	pid_t tracee, tracer, wpid;
33781.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
33791.1Skamil#if defined(TWAIT_HAVE_STATUS)
33801.1Skamil	int status;
33811.1Skamil#endif
33821.1Skamil	struct ptrace_lwpinfo info = {0, 0};
33831.1Skamil
33841.13Schristos	DPRINTF("Spawn tracee\n");
33851.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
33861.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
33871.1Skamil	tracee = atf_utils_fork();
33881.1Skamil	if (tracee == 0) {
33891.1Skamil
33901.1Skamil		/* Wait for message from the parent */
33911.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
33921.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
33931.1Skamil
33941.1Skamil		_exit(exitval_tracee);
33951.1Skamil	}
33961.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
33971.1Skamil
33981.13Schristos	DPRINTF("Spawn debugger\n");
33991.1Skamil	tracer = atf_utils_fork();
34001.1Skamil	if (tracer == 0) {
34011.1Skamil		/* No IPC to communicate with the child */
34021.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
34031.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
34041.1Skamil
34051.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
34061.1Skamil		FORKEE_REQUIRE_SUCCESS(
34071.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
34081.1Skamil
34091.1Skamil		forkee_status_stopped(status, SIGSTOP);
34101.1Skamil
34111.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
34121.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
34131.1Skamil		    != -1);
34141.1Skamil
34151.13Schristos		DPRINTF("Assert that there exists a thread\n");
34161.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
34171.1Skamil
34181.13Schristos		DPRINTF("Assert that lwp thread %d received event "
34191.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
34201.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
34211.1Skamil
34221.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
34231.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
34241.1Skamil		    != -1);
34251.1Skamil
34261.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
34271.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
34281.1Skamil
34291.1Skamil		/* Resume tracee with PT_CONTINUE */
34301.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
34311.1Skamil
34321.1Skamil		/* Inform parent that tracer has attached to tracee */
34331.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
34341.1Skamil		/* Wait for parent */
34351.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
34361.1Skamil
34371.1Skamil		/* Wait for tracee and assert that it exited */
34381.1Skamil		FORKEE_REQUIRE_SUCCESS(
34391.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
34401.1Skamil
34411.1Skamil		forkee_status_exited(status, exitval_tracee);
34421.1Skamil
34431.13Schristos		DPRINTF("Before exiting of the tracer process\n");
34441.1Skamil		_exit(exitval_tracer);
34451.1Skamil	}
34461.1Skamil
34471.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
34481.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
34491.1Skamil
34501.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
34511.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
34521.1Skamil
34531.13Schristos	DPRINTF("Detect that tracee is zombie\n");
34541.1Skamil	await_zombie(tracee);
34551.1Skamil
34561.13Schristos	DPRINTF("Assert that there is no status about tracee - "
34571.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
34581.1Skamil	TWAIT_REQUIRE_SUCCESS(
34591.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
34601.1Skamil
34611.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
34621.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
34631.1Skamil
34641.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
34651.1Skamil	    TWAIT_FNAME);
34661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
34671.1Skamil	    tracer);
34681.1Skamil
34691.1Skamil	validate_status_exited(status, exitval_tracer);
34701.1Skamil
34711.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
34721.1Skamil	    TWAIT_FNAME);
34731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
34741.1Skamil	    tracee);
34751.1Skamil
34761.1Skamil	validate_status_exited(status, exitval_tracee);
34771.1Skamil
34781.1Skamil	msg_close(&parent_tracer);
34791.1Skamil	msg_close(&parent_tracee);
34801.1Skamil}
34811.1Skamil#endif
34821.1Skamil
34831.1SkamilATF_TC(siginfo1);
34841.1SkamilATF_TC_HEAD(siginfo1, tc)
34851.1Skamil{
34861.1Skamil	atf_tc_set_md_var(tc, "descr",
34871.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
34881.1Skamil}
34891.1Skamil
34901.1SkamilATF_TC_BODY(siginfo1, tc)
34911.1Skamil{
34921.1Skamil	const int exitval = 5;
34931.1Skamil	const int sigval = SIGTRAP;
34941.1Skamil	pid_t child, wpid;
34951.1Skamil#if defined(TWAIT_HAVE_STATUS)
34961.1Skamil	int status;
34971.1Skamil#endif
34981.1Skamil	struct ptrace_siginfo info;
34991.1Skamil	memset(&info, 0, sizeof(info));
35001.1Skamil
35011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35031.1Skamil	if (child == 0) {
35041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35061.1Skamil
35071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35091.1Skamil
35101.13Schristos		DPRINTF("Before exiting of the child process\n");
35111.1Skamil		_exit(exitval);
35121.1Skamil	}
35131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35141.1Skamil
35151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35171.1Skamil
35181.1Skamil	validate_status_stopped(status, sigval);
35191.1Skamil
35201.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
35221.1Skamil
35231.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
35241.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
35251.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
35261.1Skamil	    info.psi_siginfo.si_errno);
35271.1Skamil
35281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35291.1Skamil	    "without signal to be sent\n");
35301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35311.1Skamil
35321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35341.1Skamil
35351.1Skamil	validate_status_exited(status, exitval);
35361.1Skamil
35371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35391.1Skamil}
35401.1Skamil
35411.1SkamilATF_TC(siginfo2);
35421.1SkamilATF_TC_HEAD(siginfo2, tc)
35431.1Skamil{
35441.1Skamil	atf_tc_set_md_var(tc, "descr",
35451.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
35461.1Skamil	    "modification of SIGINT from tracee");
35471.1Skamil}
35481.1Skamil
35491.1Skamilstatic int siginfo2_caught = 0;
35501.1Skamil
35511.1Skamilstatic void
35521.1Skamilsiginfo2_sighandler(int sig)
35531.1Skamil{
35541.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
35551.1Skamil
35561.1Skamil	++siginfo2_caught;
35571.1Skamil}
35581.1Skamil
35591.1SkamilATF_TC_BODY(siginfo2, tc)
35601.1Skamil{
35611.1Skamil	const int exitval = 5;
35621.1Skamil	const int sigval = SIGINT;
35631.1Skamil	pid_t child, wpid;
35641.1Skamil	struct sigaction sa;
35651.1Skamil#if defined(TWAIT_HAVE_STATUS)
35661.1Skamil	int status;
35671.1Skamil#endif
35681.1Skamil	struct ptrace_siginfo info;
35691.1Skamil	memset(&info, 0, sizeof(info));
35701.1Skamil
35711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35731.1Skamil	if (child == 0) {
35741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35761.1Skamil
35771.1Skamil		sa.sa_handler = siginfo2_sighandler;
35781.1Skamil		sa.sa_flags = SA_SIGINFO;
35791.1Skamil		sigemptyset(&sa.sa_mask);
35801.1Skamil
35811.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
35821.1Skamil
35831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35851.1Skamil
35861.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
35871.1Skamil
35881.13Schristos		DPRINTF("Before exiting of the child process\n");
35891.1Skamil		_exit(exitval);
35901.1Skamil	}
35911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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_stopped(status, sigval);
35971.1Skamil
35981.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
35991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36001.1Skamil
36011.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36021.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
36031.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36041.1Skamil	    info.psi_siginfo.si_errno);
36051.1Skamil
36061.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
36071.61Skre	SYSCALL_REQUIRE(
36081.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
36091.1Skamil
36101.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36111.1Skamil	    "without signal to be sent\n");
36121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
36131.1Skamil
36141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36161.1Skamil
36171.1Skamil	validate_status_exited(status, exitval);
36181.1Skamil
36191.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36201.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36211.1Skamil}
36221.1Skamil
36231.1SkamilATF_TC(siginfo3);
36241.1SkamilATF_TC_HEAD(siginfo3, tc)
36251.1Skamil{
36261.1Skamil	atf_tc_set_md_var(tc, "descr",
36271.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
36281.1Skamil	    "setting signal to new value");
36291.1Skamil}
36301.1Skamil
36311.1Skamilstatic int siginfo3_caught = 0;
36321.1Skamil
36331.1Skamilstatic void
36341.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
36351.1Skamil{
36361.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
36371.1Skamil
36381.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
36391.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
36401.1Skamil
36411.1Skamil	++siginfo3_caught;
36421.1Skamil}
36431.1Skamil
36441.1SkamilATF_TC_BODY(siginfo3, tc)
36451.1Skamil{
36461.1Skamil	const int exitval = 5;
36471.1Skamil	const int sigval = SIGINT;
36481.1Skamil	const int sigfaked = SIGTRAP;
36491.1Skamil	const int sicodefaked = TRAP_BRKPT;
36501.1Skamil	pid_t child, wpid;
36511.1Skamil	struct sigaction sa;
36521.1Skamil#if defined(TWAIT_HAVE_STATUS)
36531.1Skamil	int status;
36541.1Skamil#endif
36551.1Skamil	struct ptrace_siginfo info;
36561.1Skamil	memset(&info, 0, sizeof(info));
36571.1Skamil
36581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36601.1Skamil	if (child == 0) {
36611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36631.1Skamil
36641.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
36651.1Skamil		sa.sa_flags = SA_SIGINFO;
36661.1Skamil		sigemptyset(&sa.sa_mask);
36671.1Skamil
36681.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
36691.1Skamil
36701.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36711.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36721.1Skamil
36731.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
36741.1Skamil
36751.13Schristos		DPRINTF("Before exiting of the child process\n");
36761.1Skamil		_exit(exitval);
36771.1Skamil	}
36781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36791.1Skamil
36801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36821.1Skamil
36831.1Skamil	validate_status_stopped(status, sigval);
36841.1Skamil
36851.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
36861.61Skre	SYSCALL_REQUIRE(
36871.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
36881.1Skamil
36891.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
36901.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
36911.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
36921.1Skamil	    info.psi_siginfo.si_errno);
36931.1Skamil
36941.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
36951.1Skamil	    sigfaked, sicodefaked);
36961.1Skamil	info.psi_siginfo.si_signo = sigfaked;
36971.1Skamil	info.psi_siginfo.si_code = sicodefaked;
36981.1Skamil
36991.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
37001.61Skre	SYSCALL_REQUIRE(
37011.61Skre	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
37021.1Skamil
37031.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37041.61Skre	SYSCALL_REQUIRE(
37051.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37061.1Skamil
37071.13Schristos	DPRINTF("Before checking siginfo_t\n");
37081.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
37091.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
37101.1Skamil
37111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37121.1Skamil	    "without signal to be sent\n");
37131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
37141.1Skamil
37151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37171.1Skamil
37181.1Skamil	validate_status_exited(status, exitval);
37191.1Skamil
37201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37211.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37221.1Skamil}
37231.1Skamil
37241.1SkamilATF_TC(siginfo4);
37251.1SkamilATF_TC_HEAD(siginfo4, tc)
37261.1Skamil{
37271.1Skamil	atf_tc_set_md_var(tc, "descr",
37281.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
37291.1Skamil}
37301.1Skamil
37311.1SkamilATF_TC_BODY(siginfo4, tc)
37321.1Skamil{
37331.1Skamil	const int sigval = SIGTRAP;
37341.1Skamil	pid_t child, wpid;
37351.1Skamil#if defined(TWAIT_HAVE_STATUS)
37361.1Skamil	int status;
37371.1Skamil#endif
37381.1Skamil
37391.1Skamil	struct ptrace_siginfo info;
37401.1Skamil	memset(&info, 0, sizeof(info));
37411.1Skamil
37421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37441.1Skamil	if (child == 0) {
37451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37471.1Skamil
37481.13Schristos		DPRINTF("Before calling execve(2) from child\n");
37491.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
37501.1Skamil
37511.1Skamil		FORKEE_ASSERT(0 && "Not reached");
37521.1Skamil	}
37531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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.1Skamil	validate_status_stopped(status, sigval);
37591.1Skamil
37601.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
37611.61Skre	SYSCALL_REQUIRE(
37621.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
37631.1Skamil
37641.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
37651.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
37661.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
37671.1Skamil	    info.psi_siginfo.si_errno);
37681.1Skamil
37691.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
37701.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
37711.1Skamil
37721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37731.1Skamil	    "without signal to be sent\n");
37741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37751.1Skamil
37761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37781.1Skamil
37791.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37801.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37811.1Skamil}
37821.1Skamil
37831.1Skamil#if defined(TWAIT_HAVE_PID)
37841.1SkamilATF_TC(siginfo5);
37851.1SkamilATF_TC_HEAD(siginfo5, tc)
37861.1Skamil{
37871.1Skamil	atf_tc_set_md_var(tc, "descr",
37881.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
37891.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
37901.1Skamil}
37911.1Skamil
37921.1SkamilATF_TC_BODY(siginfo5, tc)
37931.1Skamil{
37941.1Skamil	const int exitval = 5;
37951.1Skamil	const int exitval2 = 15;
37961.1Skamil	const int sigval = SIGSTOP;
37971.1Skamil	pid_t child, child2, wpid;
37981.1Skamil#if defined(TWAIT_HAVE_STATUS)
37991.1Skamil	int status;
38001.1Skamil#endif
38011.1Skamil	ptrace_state_t state;
38021.1Skamil	const int slen = sizeof(state);
38031.1Skamil	ptrace_event_t event;
38041.1Skamil	const int elen = sizeof(event);
38051.1Skamil	struct ptrace_siginfo info;
38061.1Skamil
38071.1Skamil	memset(&info, 0, sizeof(info));
38081.1Skamil
38091.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38101.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38111.1Skamil	if (child == 0) {
38121.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38131.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38141.1Skamil
38151.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38161.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38171.1Skamil
38181.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
38191.1Skamil
38201.1Skamil		if (child2 == 0)
38211.1Skamil			_exit(exitval2);
38221.1Skamil
38231.1Skamil		FORKEE_REQUIRE_SUCCESS
38241.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
38251.1Skamil
38261.1Skamil		forkee_status_exited(status, exitval2);
38271.1Skamil
38281.13Schristos		DPRINTF("Before exiting of the child process\n");
38291.1Skamil		_exit(exitval);
38301.1Skamil	}
38311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38321.1Skamil
38331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38351.1Skamil
38361.1Skamil	validate_status_stopped(status, sigval);
38371.1Skamil
38381.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38391.61Skre	SYSCALL_REQUIRE(
38401.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38411.1Skamil
38421.13Schristos	DPRINTF("Before checking siginfo_t\n");
38431.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
38441.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
38451.1Skamil
38461.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
38471.1Skamil	event.pe_set_event = PTRACE_FORK;
38481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
38491.1Skamil
38501.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38511.1Skamil	    "without signal to be sent\n");
38521.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
38531.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
38541.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
38551.1Skamil                "state.pe_other_pid=child)\n", child);
38561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38571.1Skamil
38581.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
38591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38601.1Skamil
38611.1Skamil	validate_status_stopped(status, SIGTRAP);
38621.1Skamil
38631.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38641.61Skre	SYSCALL_REQUIRE(
38651.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38661.1Skamil
38671.13Schristos	DPRINTF("Before checking siginfo_t\n");
38681.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38691.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
38701.1Skamil
38711.61Skre	SYSCALL_REQUIRE(
38721.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
38731.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
38741.1Skamil
38751.1Skamil	child2 = state.pe_other_pid;
38761.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
38771.1Skamil
38781.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
38791.1Skamil	    TWAIT_FNAME, child2, child);
38801.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
38811.1Skamil	    child2);
38821.1Skamil
38831.1Skamil	validate_status_stopped(status, SIGTRAP);
38841.1Skamil
38851.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
38861.61Skre	SYSCALL_REQUIRE(
38871.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
38881.1Skamil
38891.13Schristos	DPRINTF("Before checking siginfo_t\n");
38901.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
38911.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
38921.1Skamil
38931.61Skre	SYSCALL_REQUIRE(
38941.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
38951.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
38961.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
38971.1Skamil
38981.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
38991.1Skamil	    "without signal to be sent\n");
39001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
39011.1Skamil
39021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39031.1Skamil	    "without signal to be sent\n");
39041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39051.1Skamil
39061.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
39071.1Skamil	    TWAIT_FNAME);
39081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
39091.1Skamil	    child2);
39101.1Skamil
39111.1Skamil	validate_status_exited(status, exitval2);
39121.1Skamil
39131.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
39141.1Skamil	    TWAIT_FNAME);
39151.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
39161.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
39171.1Skamil
39181.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
39191.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
39201.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39211.1Skamil
39221.1Skamil	validate_status_stopped(status, SIGCHLD);
39231.1Skamil
39241.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39251.61Skre	SYSCALL_REQUIRE(
39261.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
39271.1Skamil
39281.13Schristos	DPRINTF("Before checking siginfo_t\n");
39291.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
39301.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
39311.1Skamil
39321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39331.1Skamil	    "without signal to be sent\n");
39341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39351.1Skamil
39361.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
39371.1Skamil	    TWAIT_FNAME);
39381.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39391.1Skamil
39401.1Skamil	validate_status_exited(status, exitval);
39411.1Skamil
39421.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
39431.1Skamil	    TWAIT_FNAME);
39441.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39451.1Skamil}
39461.1Skamil#endif
39471.1Skamil
39481.1Skamil#if defined(PT_STEP)
39491.1SkamilATF_TC(siginfo6);
39501.1SkamilATF_TC_HEAD(siginfo6, tc)
39511.1Skamil{
39521.1Skamil	atf_tc_set_md_var(tc, "descr",
39531.1Skamil	    "Verify single PT_STEP call with signal information check");
39541.1Skamil}
39551.1Skamil
39561.1SkamilATF_TC_BODY(siginfo6, tc)
39571.1Skamil{
39581.1Skamil	const int exitval = 5;
39591.1Skamil	const int sigval = SIGSTOP;
39601.1Skamil	pid_t child, wpid;
39611.1Skamil#if defined(TWAIT_HAVE_STATUS)
39621.1Skamil	int status;
39631.1Skamil#endif
39641.1Skamil	int happy;
39651.1Skamil	struct ptrace_siginfo info;
39661.1Skamil
39671.1Skamil#if defined(__arm__)
39681.1Skamil	/* PT_STEP not supported on arm 32-bit */
39691.1Skamil	atf_tc_expect_fail("PR kern/52119");
39701.1Skamil#endif
39711.1Skamil
39721.1Skamil	memset(&info, 0, sizeof(info));
39731.1Skamil
39741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39761.1Skamil	if (child == 0) {
39771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39791.1Skamil
39801.1Skamil		happy = check_happy(100);
39811.1Skamil
39821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39841.1Skamil
39851.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
39861.1Skamil
39871.13Schristos		DPRINTF("Before exiting of the child process\n");
39881.1Skamil		_exit(exitval);
39891.1Skamil	}
39901.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39911.1Skamil
39921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39941.1Skamil
39951.1Skamil	validate_status_stopped(status, sigval);
39961.1Skamil
39971.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
39981.61Skre	SYSCALL_REQUIRE(
39991.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
40001.1Skamil
40011.13Schristos	DPRINTF("Before checking siginfo_t\n");
40021.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
40031.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
40041.1Skamil
40051.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40061.1Skamil	    "without signal to be sent (use PT_STEP)\n");
40071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
40081.1Skamil
40091.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40111.1Skamil
40121.1Skamil	validate_status_stopped(status, SIGTRAP);
40131.1Skamil
40141.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
40151.61Skre	SYSCALL_REQUIRE(
40161.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
40171.1Skamil
40181.13Schristos	DPRINTF("Before checking siginfo_t\n");
40191.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
40201.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
40211.1Skamil
40221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40231.1Skamil	    "without signal to be sent\n");
40241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40251.1Skamil
40261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40281.1Skamil
40291.1Skamil	validate_status_exited(status, exitval);
40301.1Skamil
40311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40331.1Skamil}
40341.1Skamil#endif
40351.1Skamil
40361.1Skamilvolatile lwpid_t the_lwp_id = 0;
40371.1Skamil
40381.1Skamilstatic void
40391.1Skamillwp_main_func(void *arg)
40401.1Skamil{
40411.1Skamil	the_lwp_id = _lwp_self();
40421.1Skamil	_lwp_exit();
40431.1Skamil}
40441.1Skamil
40451.1SkamilATF_TC(lwp_create1);
40461.1SkamilATF_TC_HEAD(lwp_create1, tc)
40471.1Skamil{
40481.1Skamil	atf_tc_set_md_var(tc, "descr",
40491.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
40501.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
40511.1Skamil}
40521.1Skamil
40531.1SkamilATF_TC_BODY(lwp_create1, tc)
40541.1Skamil{
40551.1Skamil	const int exitval = 5;
40561.1Skamil	const int sigval = SIGSTOP;
40571.1Skamil	pid_t child, wpid;
40581.1Skamil#if defined(TWAIT_HAVE_STATUS)
40591.1Skamil	int status;
40601.1Skamil#endif
40611.1Skamil	ptrace_state_t state;
40621.1Skamil	const int slen = sizeof(state);
40631.1Skamil	ptrace_event_t event;
40641.1Skamil	const int elen = sizeof(event);
40651.1Skamil	ucontext_t uc;
40661.1Skamil	lwpid_t lid;
40671.1Skamil	static const size_t ssize = 16*1024;
40681.1Skamil	void *stack;
40691.1Skamil
40701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40721.1Skamil	if (child == 0) {
40731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40751.1Skamil
40761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40781.1Skamil
40791.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
40801.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
40811.1Skamil
40821.13Schristos		DPRINTF("Before making context for new lwp in child\n");
40831.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
40841.1Skamil
40851.13Schristos		DPRINTF("Before creating new in child\n");
40861.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
40871.1Skamil
40881.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
40891.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
40901.1Skamil
40911.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
40921.1Skamil		    "are the same\n", lid, the_lwp_id);
40931.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
40941.1Skamil
40951.13Schristos		DPRINTF("Before exiting of the child process\n");
40961.1Skamil		_exit(exitval);
40971.1Skamil	}
40981.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40991.1Skamil
41001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41021.1Skamil
41031.1Skamil	validate_status_stopped(status, sigval);
41041.1Skamil
41051.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
41061.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
41071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
41081.1Skamil
41091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41101.1Skamil	    "without signal to be sent\n");
41111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41121.1Skamil
41131.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
41141.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
41151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41161.1Skamil
41171.1Skamil	validate_status_stopped(status, SIGTRAP);
41181.1Skamil
41191.61Skre	SYSCALL_REQUIRE(
41201.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
41211.1Skamil
41221.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
41231.1Skamil
41241.1Skamil	lid = state.pe_lwp;
41251.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
41261.1Skamil
41271.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41281.1Skamil	    "without signal to be sent\n");
41291.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41301.1Skamil
41311.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
41321.1Skamil	    TWAIT_FNAME);
41331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41341.1Skamil
41351.1Skamil	validate_status_exited(status, exitval);
41361.1Skamil
41371.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
41381.1Skamil	    TWAIT_FNAME);
41391.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41401.1Skamil}
41411.1Skamil
41421.1SkamilATF_TC(lwp_exit1);
41431.1SkamilATF_TC_HEAD(lwp_exit1, tc)
41441.1Skamil{
41451.1Skamil	atf_tc_set_md_var(tc, "descr",
41461.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
41471.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
41481.1Skamil}
41491.1Skamil
41501.1SkamilATF_TC_BODY(lwp_exit1, tc)
41511.1Skamil{
41521.1Skamil	const int exitval = 5;
41531.1Skamil	const int sigval = SIGSTOP;
41541.1Skamil	pid_t child, wpid;
41551.1Skamil#if defined(TWAIT_HAVE_STATUS)
41561.1Skamil	int status;
41571.1Skamil#endif
41581.1Skamil	ptrace_state_t state;
41591.1Skamil	const int slen = sizeof(state);
41601.1Skamil	ptrace_event_t event;
41611.1Skamil	const int elen = sizeof(event);
41621.1Skamil	ucontext_t uc;
41631.1Skamil	lwpid_t lid;
41641.1Skamil	static const size_t ssize = 16*1024;
41651.1Skamil	void *stack;
41661.1Skamil
41671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41691.1Skamil	if (child == 0) {
41701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41721.1Skamil
41731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41751.1Skamil
41761.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
41771.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
41781.1Skamil
41791.13Schristos		DPRINTF("Before making context for new lwp in child\n");
41801.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
41811.1Skamil
41821.13Schristos		DPRINTF("Before creating new in child\n");
41831.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
41841.1Skamil
41851.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
41861.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
41871.1Skamil
41881.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
41891.1Skamil		    "are the same\n", lid, the_lwp_id);
41901.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
41911.1Skamil
41921.13Schristos		DPRINTF("Before exiting of the child process\n");
41931.1Skamil		_exit(exitval);
41941.1Skamil	}
41951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41961.1Skamil
41971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41991.1Skamil
42001.1Skamil	validate_status_stopped(status, sigval);
42011.1Skamil
42021.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
42031.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
42041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
42051.1Skamil
42061.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42071.1Skamil	    "without signal to be sent\n");
42081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42091.1Skamil
42101.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
42111.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
42121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42131.1Skamil
42141.1Skamil	validate_status_stopped(status, SIGTRAP);
42151.1Skamil
42161.61Skre	SYSCALL_REQUIRE(
42171.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
42181.1Skamil
42191.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
42201.1Skamil
42211.1Skamil	lid = state.pe_lwp;
42221.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
42231.1Skamil
42241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42251.1Skamil	    "without signal to be sent\n");
42261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42271.1Skamil
42281.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
42291.1Skamil	    TWAIT_FNAME);
42301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42311.1Skamil
42321.1Skamil	validate_status_exited(status, exitval);
42331.1Skamil
42341.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
42351.1Skamil	    TWAIT_FNAME);
42361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42371.1Skamil}
42381.1Skamil
42391.1SkamilATF_TC(signal1);
42401.1SkamilATF_TC_HEAD(signal1, tc)
42411.1Skamil{
42421.1Skamil	atf_tc_set_md_var(tc, "descr",
42431.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
42441.1Skamil	    "from catching other signals");
42451.1Skamil}
42461.1Skamil
42471.1SkamilATF_TC_BODY(signal1, tc)
42481.1Skamil{
42491.1Skamil	const int exitval = 5;
42501.1Skamil	const int sigval = SIGSTOP;
42511.1Skamil	const int sigmasked = SIGTRAP;
42521.1Skamil	const int signotmasked = SIGINT;
42531.1Skamil	pid_t child, wpid;
42541.1Skamil#if defined(TWAIT_HAVE_STATUS)
42551.1Skamil	int status;
42561.1Skamil#endif
42571.1Skamil	sigset_t intmask;
42581.1Skamil
42591.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42601.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42611.1Skamil	if (child == 0) {
42621.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42631.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42641.1Skamil
42651.1Skamil		sigemptyset(&intmask);
42661.1Skamil		sigaddset(&intmask, sigmasked);
42671.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
42681.1Skamil
42691.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42701.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42711.1Skamil
42721.13Schristos		DPRINTF("Before raising %s from child\n",
42731.1Skamil		    strsignal(signotmasked));
42741.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
42751.1Skamil
42761.13Schristos		DPRINTF("Before exiting of the child process\n");
42771.1Skamil		_exit(exitval);
42781.1Skamil	}
42791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42801.1Skamil
42811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42831.1Skamil
42841.1Skamil	validate_status_stopped(status, sigval);
42851.1Skamil
42861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42871.1Skamil	    "without signal to be sent\n");
42881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42891.1Skamil
42901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42921.1Skamil
42931.1Skamil	validate_status_stopped(status, signotmasked);
42941.1Skamil
42951.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42961.1Skamil	    "without signal to be sent\n");
42971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42981.1Skamil
42991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43011.1Skamil
43021.1Skamil	validate_status_exited(status, exitval);
43031.1Skamil
43041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43051.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43061.1Skamil}
43071.1Skamil
43081.1SkamilATF_TC(signal2);
43091.1SkamilATF_TC_HEAD(signal2, tc)
43101.1Skamil{
43111.1Skamil	atf_tc_set_md_var(tc, "descr",
43121.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
43131.1Skamil	    "catching this raised signal");
43141.1Skamil}
43151.1Skamil
43161.1SkamilATF_TC_BODY(signal2, tc)
43171.1Skamil{
43181.1Skamil	const int exitval = 5;
43191.1Skamil	const int sigval = SIGSTOP;
43201.1Skamil	const int sigmasked = SIGTRAP;
43211.1Skamil	pid_t child, wpid;
43221.1Skamil#if defined(TWAIT_HAVE_STATUS)
43231.1Skamil	int status;
43241.1Skamil#endif
43251.1Skamil	sigset_t intmask;
43261.1Skamil
43271.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43281.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43291.1Skamil	if (child == 0) {
43301.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43311.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43321.1Skamil
43331.1Skamil		sigemptyset(&intmask);
43341.1Skamil		sigaddset(&intmask, sigmasked);
43351.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43361.1Skamil
43371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43391.1Skamil
43401.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
43411.1Skamil		    strsignal(sigmasked));
43421.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
43431.1Skamil
43441.13Schristos		DPRINTF("Before exiting of the child process\n");
43451.1Skamil		_exit(exitval);
43461.1Skamil	}
43471.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
43481.1Skamil
43491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43511.1Skamil
43521.1Skamil	validate_status_stopped(status, sigval);
43531.1Skamil
43541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43551.1Skamil	    "without signal to be sent\n");
43561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43571.1Skamil
43581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43601.1Skamil
43611.1Skamil	validate_status_exited(status, exitval);
43621.1Skamil
43631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43651.1Skamil}
43661.1Skamil
43671.1SkamilATF_TC(signal3);
43681.1SkamilATF_TC_HEAD(signal3, tc)
43691.1Skamil{
43701.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
43711.1Skamil	atf_tc_set_md_var(tc, "descr",
43721.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
43731.1Skamil	    "catching software breakpoints");
43741.1Skamil}
43751.1Skamil
43761.1SkamilATF_TC_BODY(signal3, tc)
43771.1Skamil{
43781.1Skamil	const int exitval = 5;
43791.1Skamil	const int sigval = SIGSTOP;
43801.1Skamil	const int sigmasked = SIGTRAP;
43811.1Skamil	pid_t child, wpid;
43821.1Skamil#if defined(TWAIT_HAVE_STATUS)
43831.1Skamil	int status;
43841.1Skamil#endif
43851.1Skamil	sigset_t intmask;
43861.1Skamil
43871.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
43881.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
43891.1Skamil	if (child == 0) {
43901.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
43911.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
43921.1Skamil
43931.1Skamil		sigemptyset(&intmask);
43941.1Skamil		sigaddset(&intmask, sigmasked);
43951.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
43961.1Skamil
43971.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
43981.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
43991.1Skamil
44001.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
44011.52Skamil		trigger_trap();
44021.1Skamil
44031.13Schristos		DPRINTF("Before exiting of the child process\n");
44041.1Skamil		_exit(exitval);
44051.1Skamil	}
44061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44071.1Skamil
44081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44101.1Skamil
44111.1Skamil	validate_status_stopped(status, sigval);
44121.1Skamil
44131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44141.1Skamil	    "without signal to be sent\n");
44151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
44161.1Skamil
44171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44191.1Skamil
44201.1Skamil	validate_status_stopped(status, sigmasked);
44211.1Skamil
44221.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44231.1Skamil	    "without signal to be sent\n");
44241.49Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
44251.1Skamil
44261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44281.1Skamil
44291.49Skamil	validate_status_signaled(status, SIGKILL, 0);
44301.1Skamil
44311.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44331.1Skamil}
44341.1Skamil
44351.1Skamil#if defined(PT_STEP)
44361.1SkamilATF_TC(signal4);
44371.1SkamilATF_TC_HEAD(signal4, tc)
44381.1Skamil{
44391.1Skamil	atf_tc_set_md_var(tc, "descr",
44401.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
44411.1Skamil	    "catching single step trap");
44421.1Skamil}
44431.1Skamil
44441.1SkamilATF_TC_BODY(signal4, tc)
44451.1Skamil{
44461.1Skamil	const int exitval = 5;
44471.1Skamil	const int sigval = SIGSTOP;
44481.1Skamil	const int sigmasked = SIGTRAP;
44491.1Skamil	pid_t child, wpid;
44501.1Skamil#if defined(TWAIT_HAVE_STATUS)
44511.1Skamil	int status;
44521.1Skamil#endif
44531.1Skamil	sigset_t intmask;
44541.1Skamil	int happy;
44551.1Skamil
44561.1Skamil#if defined(__arm__)
44571.5Skamil	/* PT_STEP not supported on arm 32-bit */
44581.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
44591.1Skamil#endif
44601.1Skamil
44611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44631.1Skamil	if (child == 0) {
44641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44661.1Skamil
44671.1Skamil		happy = check_happy(100);
44681.1Skamil
44691.1Skamil		sigemptyset(&intmask);
44701.1Skamil		sigaddset(&intmask, sigmasked);
44711.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
44721.1Skamil
44731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44751.1Skamil
44761.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
44771.1Skamil
44781.13Schristos		DPRINTF("Before exiting of the child process\n");
44791.1Skamil		_exit(exitval);
44801.1Skamil	}
44811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44821.1Skamil
44831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44851.1Skamil
44861.1Skamil	validate_status_stopped(status, sigval);
44871.1Skamil
44881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44891.1Skamil	    "without signal to be sent\n");
44901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
44911.1Skamil
44921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44941.1Skamil
44951.1Skamil	validate_status_stopped(status, sigmasked);
44961.1Skamil
44971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44981.1Skamil	    "without signal to be sent\n");
44991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45001.1Skamil
45011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45031.1Skamil
45041.1Skamil	validate_status_exited(status, exitval);
45051.1Skamil
45061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45081.1Skamil}
45091.1Skamil#endif
45101.1Skamil
45111.1SkamilATF_TC(signal5);
45121.1SkamilATF_TC_HEAD(signal5, tc)
45131.1Skamil{
45141.1Skamil	atf_tc_set_md_var(tc, "descr",
45151.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45161.1Skamil	    "catching exec() breakpoint");
45171.1Skamil}
45181.1Skamil
45191.1SkamilATF_TC_BODY(signal5, tc)
45201.1Skamil{
45211.1Skamil	const int sigval = SIGSTOP;
45221.1Skamil	const int sigmasked = SIGTRAP;
45231.1Skamil	pid_t child, wpid;
45241.1Skamil#if defined(TWAIT_HAVE_STATUS)
45251.1Skamil	int status;
45261.1Skamil#endif
45271.58Skamil	struct ptrace_siginfo info;
45281.1Skamil	sigset_t intmask;
45291.1Skamil
45301.58Skamil	memset(&info, 0, sizeof(info));
45311.14Schristos
45321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45341.1Skamil	if (child == 0) {
45351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45371.1Skamil
45381.1Skamil		sigemptyset(&intmask);
45391.1Skamil		sigaddset(&intmask, sigmasked);
45401.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
45411.1Skamil
45421.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45431.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45441.1Skamil
45451.13Schristos		DPRINTF("Before calling execve(2) from child\n");
45461.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
45471.1Skamil
45481.58Skamil		/* NOTREACHED */
45491.58Skamil		FORKEE_ASSERTX(0 && "Not reached");
45501.1Skamil	}
45511.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45521.1Skamil
45531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45551.1Skamil
45561.1Skamil	validate_status_stopped(status, sigval);
45571.1Skamil
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.1Skamil	validate_status_stopped(status, sigmasked);
45661.1Skamil
45671.58Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
45681.61Skre	SYSCALL_REQUIRE(
45691.61Skre	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
45701.58Skamil
45711.58Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
45721.58Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
45731.58Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
45741.58Skamil	    info.psi_siginfo.si_errno);
45751.58Skamil
45761.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked);
45771.58Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
45781.58Skamil
45791.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45801.1Skamil	    "without signal to be sent\n");
45811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45821.1Skamil
45831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45851.1Skamil
45861.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45881.1Skamil}
45891.1Skamil
45901.1Skamil#if defined(TWAIT_HAVE_PID)
45911.1SkamilATF_TC(signal6);
45921.1SkamilATF_TC_HEAD(signal6, tc)
45931.1Skamil{
45941.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
45951.1Skamil	atf_tc_set_md_var(tc, "descr",
45961.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
45971.1Skamil	    "catching PTRACE_FORK breakpoint");
45981.1Skamil}
45991.1Skamil
46001.1SkamilATF_TC_BODY(signal6, tc)
46011.1Skamil{
46021.1Skamil	const int exitval = 5;
46031.1Skamil	const int exitval2 = 15;
46041.1Skamil	const int sigval = SIGSTOP;
46051.1Skamil	const int sigmasked = SIGTRAP;
46061.1Skamil	pid_t child, child2, wpid;
46071.1Skamil#if defined(TWAIT_HAVE_STATUS)
46081.1Skamil	int status;
46091.1Skamil#endif
46101.1Skamil	sigset_t intmask;
46111.1Skamil	ptrace_state_t state;
46121.1Skamil	const int slen = sizeof(state);
46131.1Skamil	ptrace_event_t event;
46141.1Skamil	const int elen = sizeof(event);
46151.1Skamil
46161.38Skamil	atf_tc_expect_fail("PR kern/51918");
46171.14Schristos
46181.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
46191.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
46201.1Skamil	if (child == 0) {
46211.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
46221.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
46231.1Skamil
46241.1Skamil		sigemptyset(&intmask);
46251.1Skamil		sigaddset(&intmask, sigmasked);
46261.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
46271.1Skamil
46281.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
46291.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
46301.1Skamil
46311.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
46321.1Skamil
46331.1Skamil		if (child2 == 0)
46341.1Skamil			_exit(exitval2);
46351.1Skamil
46361.1Skamil		FORKEE_REQUIRE_SUCCESS
46371.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
46381.1Skamil
46391.1Skamil		forkee_status_exited(status, exitval2);
46401.1Skamil
46411.13Schristos		DPRINTF("Before exiting of the child process\n");
46421.1Skamil		_exit(exitval);
46431.1Skamil	}
46441.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
46451.1Skamil
46461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46481.1Skamil
46491.1Skamil	validate_status_stopped(status, sigval);
46501.1Skamil
46511.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
46521.1Skamil	event.pe_set_event = PTRACE_FORK;
46531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
46541.1Skamil
46551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46561.1Skamil	    "without signal to be sent\n");
46571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46581.1Skamil
46591.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
46601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
46611.1Skamil
46621.1Skamil	validate_status_stopped(status, sigmasked);
46631.1Skamil
46641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
46651.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46661.1Skamil
46671.1Skamil	child2 = state.pe_other_pid;
46681.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
46691.1Skamil
46701.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
46711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46721.1Skamil	    child2);
46731.1Skamil
46741.1Skamil	validate_status_stopped(status, SIGTRAP);
46751.1Skamil
46761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
46771.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
46781.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
46791.1Skamil
46801.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
46811.1Skamil	    "without signal to be sent\n");
46821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
46831.1Skamil
46841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
46851.1Skamil	    "without signal to be sent\n");
46861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
46871.1Skamil
46881.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
46891.1Skamil	    TWAIT_FNAME);
46901.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
46911.57Skamil	    child2);
46921.1Skamil
46931.1Skamil	validate_status_exited(status, exitval2);
46941.1Skamil
46951.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
46961.1Skamil	    TWAIT_FNAME);
46971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
46981.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
46991.1Skamil
47001.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
47011.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
47021.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47031.1Skamil
47041.1Skamil	validate_status_stopped(status, SIGCHLD);
47051.1Skamil
47061.57Skamil	DPRINTF("Before resuming the child process where it left off and "
47071.1Skamil	    "without signal to be sent\n");
47081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47091.1Skamil
47101.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
47111.1Skamil	    TWAIT_FNAME);
47121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47131.1Skamil
47141.1Skamil	validate_status_exited(status, exitval);
47151.1Skamil
47161.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
47171.57Skamil	    TWAIT_FNAME);
47181.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47191.1Skamil}
47201.1Skamil#endif
47211.1Skamil
47221.1Skamil#if defined(TWAIT_HAVE_PID)
47231.1SkamilATF_TC(signal7);
47241.1SkamilATF_TC_HEAD(signal7, tc)
47251.1Skamil{
47261.1Skamil	atf_tc_set_md_var(tc, "descr",
47271.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
47281.1Skamil	    "catching PTRACE_VFORK breakpoint");
47291.1Skamil}
47301.1Skamil
47311.1SkamilATF_TC_BODY(signal7, tc)
47321.1Skamil{
47331.1Skamil	const int exitval = 5;
47341.1Skamil	const int exitval2 = 15;
47351.1Skamil	const int sigval = SIGSTOP;
47361.1Skamil	const int sigmasked = SIGTRAP;
47371.1Skamil	pid_t child, child2, wpid;
47381.1Skamil#if defined(TWAIT_HAVE_STATUS)
47391.1Skamil	int status;
47401.1Skamil#endif
47411.1Skamil	sigset_t intmask;
47421.1Skamil	ptrace_state_t state;
47431.1Skamil	const int slen = sizeof(state);
47441.1Skamil	ptrace_event_t event;
47451.1Skamil	const int elen = sizeof(event);
47461.1Skamil
47471.38Skamil	atf_tc_expect_fail("PR kern/51918");
47481.14Schristos
47491.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47501.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47511.1Skamil	if (child == 0) {
47521.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47531.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47541.1Skamil
47551.1Skamil		sigemptyset(&intmask);
47561.1Skamil		sigaddset(&intmask, sigmasked);
47571.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
47581.1Skamil
47591.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47601.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47611.1Skamil
47621.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
47631.1Skamil
47641.1Skamil		if (child2 == 0)
47651.1Skamil			_exit(exitval2);
47661.1Skamil
47671.1Skamil		FORKEE_REQUIRE_SUCCESS
47681.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
47691.1Skamil
47701.1Skamil		forkee_status_exited(status, exitval2);
47711.1Skamil
47721.13Schristos		DPRINTF("Before exiting of the child process\n");
47731.1Skamil		_exit(exitval);
47741.1Skamil	}
47751.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47761.1Skamil
47771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47791.1Skamil
47801.1Skamil	validate_status_stopped(status, sigval);
47811.1Skamil
47821.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
47831.1Skamil	event.pe_set_event = PTRACE_VFORK;
47841.61Skre	SYSCALL_REQUIRE(
47851.61Skre	    ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 ||
47861.61Skre	    errno == ENOTSUP);
47871.1Skamil
47881.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47891.1Skamil	    "without signal to be sent\n");
47901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47911.1Skamil
47921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47931.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47941.1Skamil
47951.1Skamil	validate_status_stopped(status, sigmasked);
47961.1Skamil
47971.61Skre	SYSCALL_REQUIRE(
47981.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
47991.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
48001.1Skamil
48011.1Skamil	child2 = state.pe_other_pid;
48021.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
48031.1Skamil
48041.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
48051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
48061.1Skamil	    child2);
48071.1Skamil
48081.1Skamil	validate_status_stopped(status, SIGTRAP);
48091.1Skamil
48101.61Skre	SYSCALL_REQUIRE(
48111.61Skre	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
48121.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
48131.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
48141.1Skamil
48151.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
48161.1Skamil	    "without signal to be sent\n");
48171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
48181.1Skamil
48191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48201.1Skamil	    "without signal to be sent\n");
48211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48221.1Skamil
48231.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
48241.1Skamil	    TWAIT_FNAME);
48251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
48261.57Skamil	    child2);
48271.1Skamil
48281.1Skamil	validate_status_exited(status, exitval2);
48291.1Skamil
48301.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
48311.1Skamil	    TWAIT_FNAME);
48321.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
48331.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
48341.1Skamil
48351.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
48361.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
48371.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48381.1Skamil
48391.1Skamil	validate_status_stopped(status, SIGCHLD);
48401.1Skamil
48411.57Skamil	DPRINTF("Before resuming the child process where it left off and "
48421.1Skamil	    "without signal to be sent\n");
48431.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
48441.1Skamil
48451.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
48461.1Skamil	    TWAIT_FNAME);
48471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48481.1Skamil
48491.1Skamil	validate_status_exited(status, exitval);
48501.1Skamil
48511.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
48521.57Skamil	    TWAIT_FNAME);
48531.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48541.1Skamil}
48551.1Skamil#endif
48561.1Skamil
48571.1SkamilATF_TC(signal8);
48581.1SkamilATF_TC_HEAD(signal8, tc)
48591.1Skamil{
48601.1Skamil	atf_tc_set_md_var(tc, "descr",
48611.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
48621.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
48631.1Skamil}
48641.1Skamil
48651.1SkamilATF_TC_BODY(signal8, tc)
48661.1Skamil{
48671.1Skamil	const int exitval = 5;
48681.1Skamil	const int exitval2 = 15;
48691.1Skamil	const int sigval = SIGSTOP;
48701.1Skamil	const int sigmasked = SIGTRAP;
48711.1Skamil	pid_t child, child2, wpid;
48721.1Skamil#if defined(TWAIT_HAVE_STATUS)
48731.1Skamil	int status;
48741.1Skamil#endif
48751.1Skamil	sigset_t intmask;
48761.1Skamil	ptrace_state_t state;
48771.1Skamil	const int slen = sizeof(state);
48781.1Skamil	ptrace_event_t event;
48791.1Skamil	const int elen = sizeof(event);
48801.1Skamil
48811.14Schristos	atf_tc_expect_fail("PR kern/51918");
48821.14Schristos
48831.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48841.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48851.1Skamil	if (child == 0) {
48861.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48871.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48881.1Skamil
48891.1Skamil		sigemptyset(&intmask);
48901.1Skamil		sigaddset(&intmask, sigmasked);
48911.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
48921.1Skamil
48931.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48941.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48951.1Skamil
48961.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
48971.1Skamil
48981.1Skamil		if (child2 == 0)
48991.1Skamil			_exit(exitval2);
49001.1Skamil
49011.1Skamil		FORKEE_REQUIRE_SUCCESS
49021.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
49031.1Skamil
49041.1Skamil		forkee_status_exited(status, exitval2);
49051.1Skamil
49061.13Schristos		DPRINTF("Before exiting of the child process\n");
49071.1Skamil		_exit(exitval);
49081.1Skamil	}
49091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49101.1Skamil
49111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49131.1Skamil
49141.1Skamil	validate_status_stopped(status, sigval);
49151.1Skamil
49161.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
49171.1Skamil	    child);
49181.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
49191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
49201.1Skamil
49211.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49221.1Skamil	    "without signal to be sent\n");
49231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49241.1Skamil
49251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49271.1Skamil
49281.1Skamil	validate_status_stopped(status, sigmasked);
49291.1Skamil
49301.61Skre	SYSCALL_REQUIRE(
49311.61Skre	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
49321.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
49331.1Skamil
49341.1Skamil	child2 = state.pe_other_pid;
49351.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
49361.1Skamil
49371.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49381.1Skamil	    "without signal to be sent\n");
49391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49401.1Skamil
49411.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
49421.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
49431.57Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49441.1Skamil
49451.1Skamil	validate_status_stopped(status, SIGCHLD);
49461.1Skamil
49471.57Skamil	DPRINTF("Before resuming the child process where it left off and "
49481.1Skamil	    "without signal to be sent\n");
49491.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
49501.1Skamil
49511.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
49521.1Skamil	    TWAIT_FNAME);
49531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49541.1Skamil
49551.1Skamil	validate_status_exited(status, exitval);
49561.1Skamil
49571.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
49581.57Skamil	    TWAIT_FNAME);
49591.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49601.1Skamil}
49611.1Skamil
49621.1SkamilATF_TC(signal9);
49631.1SkamilATF_TC_HEAD(signal9, tc)
49641.1Skamil{
49651.1Skamil	atf_tc_set_md_var(tc, "descr",
49661.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
49671.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
49681.1Skamil}
49691.1Skamil
49701.1SkamilATF_TC_BODY(signal9, tc)
49711.1Skamil{
49721.1Skamil	const int exitval = 5;
49731.1Skamil	const int sigval = SIGSTOP;
49741.1Skamil	const int sigmasked = SIGTRAP;
49751.1Skamil	pid_t child, wpid;
49761.1Skamil#if defined(TWAIT_HAVE_STATUS)
49771.1Skamil	int status;
49781.1Skamil#endif
49791.1Skamil	sigset_t intmask;
49801.1Skamil	ptrace_state_t state;
49811.1Skamil	const int slen = sizeof(state);
49821.1Skamil	ptrace_event_t event;
49831.1Skamil	const int elen = sizeof(event);
49841.1Skamil	ucontext_t uc;
49851.1Skamil	lwpid_t lid;
49861.1Skamil	static const size_t ssize = 16*1024;
49871.1Skamil	void *stack;
49881.1Skamil
49891.14Schristos	atf_tc_expect_fail("PR kern/51918");
49901.14Schristos
49911.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49921.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49931.1Skamil	if (child == 0) {
49941.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49951.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49961.1Skamil
49971.1Skamil		sigemptyset(&intmask);
49981.1Skamil		sigaddset(&intmask, sigmasked);
49991.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
50001.1Skamil
50011.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50021.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50031.1Skamil
50041.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
50051.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
50061.1Skamil
50071.13Schristos		DPRINTF("Before making context for new lwp in child\n");
50081.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
50091.1Skamil
50101.13Schristos		DPRINTF("Before creating new in child\n");
50111.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
50121.1Skamil
50131.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
50141.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
50151.1Skamil
50161.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
50171.1Skamil		    "are the same\n", lid, the_lwp_id);
50181.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
50191.1Skamil
50201.13Schristos		DPRINTF("Before exiting of the child process\n");
50211.1Skamil		_exit(exitval);
50221.1Skamil	}
50231.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50241.1Skamil
50251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50261.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50271.1Skamil
50281.1Skamil	validate_status_stopped(status, sigval);
50291.1Skamil
50301.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
50311.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
50321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50331.1Skamil
50341.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50351.1Skamil	    "without signal to be sent\n");
50361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50371.1Skamil
50381.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
50391.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
50401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50411.1Skamil
50421.1Skamil	validate_status_stopped(status, sigmasked);
50431.1Skamil
50441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50451.1Skamil
50461.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
50471.1Skamil
50481.1Skamil	lid = state.pe_lwp;
50491.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
50501.1Skamil
50511.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50521.1Skamil	    "without signal to be sent\n");
50531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50541.1Skamil
50551.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
50561.1Skamil	    TWAIT_FNAME);
50571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50581.1Skamil
50591.1Skamil	validate_status_exited(status, exitval);
50601.1Skamil
50611.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
50621.1Skamil	    TWAIT_FNAME);
50631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50641.1Skamil}
50651.1Skamil
50661.1SkamilATF_TC(signal10);
50671.1SkamilATF_TC_HEAD(signal10, tc)
50681.1Skamil{
50691.1Skamil	atf_tc_set_md_var(tc, "descr",
50701.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
50711.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
50721.1Skamil}
50731.1Skamil
50741.1SkamilATF_TC_BODY(signal10, tc)
50751.1Skamil{
50761.1Skamil	const int exitval = 5;
50771.1Skamil	const int sigval = SIGSTOP;
50781.1Skamil	const int sigmasked = SIGTRAP;
50791.1Skamil	pid_t child, wpid;
50801.1Skamil#if defined(TWAIT_HAVE_STATUS)
50811.1Skamil	int status;
50821.1Skamil#endif
50831.1Skamil	sigset_t intmask;
50841.1Skamil	ptrace_state_t state;
50851.1Skamil	const int slen = sizeof(state);
50861.1Skamil	ptrace_event_t event;
50871.1Skamil	const int elen = sizeof(event);
50881.1Skamil	ucontext_t uc;
50891.1Skamil	lwpid_t lid;
50901.1Skamil	static const size_t ssize = 16*1024;
50911.1Skamil	void *stack;
50921.1Skamil
50931.14Schristos	atf_tc_expect_fail("PR kern/51918");
50941.14Schristos
50951.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50961.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50971.1Skamil	if (child == 0) {
50981.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50991.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
51001.1Skamil
51011.1Skamil		sigemptyset(&intmask);
51021.1Skamil		sigaddset(&intmask, sigmasked);
51031.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
51041.1Skamil
51051.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
51061.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
51071.1Skamil
51081.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
51091.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
51101.1Skamil
51111.13Schristos		DPRINTF("Before making context for new lwp in child\n");
51121.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
51131.1Skamil
51141.13Schristos		DPRINTF("Before creating new in child\n");
51151.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
51161.1Skamil
51171.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
51181.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
51191.1Skamil
51201.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
51211.1Skamil		    "are the same\n", lid, the_lwp_id);
51221.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
51231.1Skamil
51241.13Schristos		DPRINTF("Before exiting of the child process\n");
51251.1Skamil		_exit(exitval);
51261.1Skamil	}
51271.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
51281.1Skamil
51291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
51301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51311.1Skamil
51321.1Skamil	validate_status_stopped(status, sigval);
51331.1Skamil
51341.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
51351.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
51361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
51371.1Skamil
51381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51391.1Skamil	    "without signal to be sent\n");
51401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51411.1Skamil
51421.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
51431.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
51441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51451.1Skamil
51461.1Skamil	validate_status_stopped(status, sigmasked);
51471.1Skamil
51481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
51491.1Skamil
51501.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
51511.1Skamil
51521.1Skamil	lid = state.pe_lwp;
51531.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
51541.1Skamil
51551.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51561.1Skamil	    "without signal to be sent\n");
51571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51581.1Skamil
51591.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51601.1Skamil	    TWAIT_FNAME);
51611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51621.1Skamil
51631.1Skamil	validate_status_exited(status, exitval);
51641.1Skamil
51651.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51661.1Skamil	    TWAIT_FNAME);
51671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51681.1Skamil}
51691.1Skamil
51701.1Skamilstatic void
51711.1Skamillwp_main_stop(void *arg)
51721.1Skamil{
51731.1Skamil	the_lwp_id = _lwp_self();
51741.1Skamil
51751.1Skamil	raise(SIGTRAP);
51761.1Skamil
51771.1Skamil	_lwp_exit();
51781.1Skamil}
51791.1Skamil
51801.1SkamilATF_TC(suspend1);
51811.1SkamilATF_TC_HEAD(suspend1, tc)
51821.1Skamil{
51831.1Skamil	atf_tc_set_md_var(tc, "descr",
51841.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
51851.1Skamil	    "resumed by a tracee");
51861.1Skamil}
51871.1Skamil
51881.1SkamilATF_TC_BODY(suspend1, tc)
51891.1Skamil{
51901.1Skamil	const int exitval = 5;
51911.1Skamil	const int sigval = SIGSTOP;
51921.1Skamil	pid_t child, wpid;
51931.1Skamil#if defined(TWAIT_HAVE_STATUS)
51941.1Skamil	int status;
51951.1Skamil#endif
51961.1Skamil	ucontext_t uc;
51971.1Skamil	lwpid_t lid;
51981.1Skamil	static const size_t ssize = 16*1024;
51991.1Skamil	void *stack;
52001.1Skamil	struct ptrace_lwpinfo pl;
52011.1Skamil	struct ptrace_siginfo psi;
52021.1Skamil	volatile int go = 0;
52031.1Skamil
52041.17Skamil	// Feature pending for refactoring
52051.17Skamil	atf_tc_expect_fail("PR kern/51995");
52061.17Skamil
52071.16Skamil	// Hangs with qemu
52081.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
52091.16Skamil
52101.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52111.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52121.1Skamil	if (child == 0) {
52131.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52141.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52151.1Skamil
52161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52181.1Skamil
52191.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
52201.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
52211.1Skamil
52221.13Schristos		DPRINTF("Before making context for new lwp in child\n");
52231.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
52241.1Skamil
52251.13Schristos		DPRINTF("Before creating new in child\n");
52261.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
52271.1Skamil
52281.1Skamil		while (go == 0)
52291.1Skamil			continue;
52301.1Skamil
52311.1Skamil		raise(SIGINT);
52321.1Skamil
52331.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
52341.1Skamil
52351.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
52361.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
52371.1Skamil
52381.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
52391.1Skamil		    "are the same\n", lid, the_lwp_id);
52401.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
52411.1Skamil
52421.13Schristos		DPRINTF("Before exiting of the child process\n");
52431.1Skamil		_exit(exitval);
52441.1Skamil	}
52451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52461.1Skamil
52471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52491.1Skamil
52501.1Skamil	validate_status_stopped(status, sigval);
52511.1Skamil
52521.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52531.1Skamil	    "without signal to be sent\n");
52541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52551.1Skamil
52561.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52571.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
52581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52591.1Skamil
52601.1Skamil	validate_status_stopped(status, SIGTRAP);
52611.1Skamil
52621.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
52631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
52641.1Skamil
52651.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
52661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
52671.1Skamil
52681.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
52691.1Skamil	    child, getpid());
52701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
52711.1Skamil
52721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52731.1Skamil	    "without signal to be sent\n");
52741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52751.1Skamil
52761.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
52771.1Skamil	    "SIGINT\n", TWAIT_FNAME);
52781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52791.1Skamil
52801.1Skamil	validate_status_stopped(status, SIGINT);
52811.1Skamil
52821.1Skamil	pl.pl_lwpid = 0;
52831.1Skamil
52841.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52851.1Skamil	while (pl.pl_lwpid != 0) {
52861.1Skamil
52871.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
52881.1Skamil		switch (pl.pl_lwpid) {
52891.1Skamil		case 1:
52901.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
52911.1Skamil			break;
52921.1Skamil		case 2:
52931.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
52941.1Skamil			break;
52951.1Skamil		}
52961.1Skamil	}
52971.1Skamil
52981.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52991.1Skamil	    "without signal to be sent\n");
53001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53011.1Skamil
53021.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53031.1Skamil	    TWAIT_FNAME);
53041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53051.1Skamil
53061.1Skamil	validate_status_exited(status, exitval);
53071.1Skamil
53081.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53091.1Skamil	    TWAIT_FNAME);
53101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53111.1Skamil}
53121.1Skamil
53131.1SkamilATF_TC(suspend2);
53141.1SkamilATF_TC_HEAD(suspend2, tc)
53151.1Skamil{
53161.1Skamil	atf_tc_set_md_var(tc, "descr",
53171.1Skamil	    "Verify that the while the only thread within a process is "
53181.1Skamil	    "suspended, the whole process cannot be unstopped");
53191.1Skamil}
53201.1Skamil
53211.1SkamilATF_TC_BODY(suspend2, tc)
53221.1Skamil{
53231.1Skamil	const int exitval = 5;
53241.1Skamil	const int sigval = SIGSTOP;
53251.1Skamil	pid_t child, wpid;
53261.1Skamil#if defined(TWAIT_HAVE_STATUS)
53271.1Skamil	int status;
53281.1Skamil#endif
53291.1Skamil	struct ptrace_siginfo psi;
53301.1Skamil
53311.17Skamil	// Feature pending for refactoring
53321.17Skamil	atf_tc_expect_fail("PR kern/51995");
53331.17Skamil
53341.16Skamil	// Hangs with qemu
53351.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
53361.16Skamil
53371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53391.1Skamil	if (child == 0) {
53401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53421.1Skamil
53431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53451.1Skamil
53461.13Schristos		DPRINTF("Before exiting of the child process\n");
53471.1Skamil		_exit(exitval);
53481.1Skamil	}
53491.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53501.1Skamil
53511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53531.1Skamil
53541.1Skamil	validate_status_stopped(status, sigval);
53551.1Skamil
53561.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
53571.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
53581.1Skamil
53591.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
53601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
53611.1Skamil
53621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53631.1Skamil	    "without signal to be sent\n");
53641.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
53651.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
53661.1Skamil
53671.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
53681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
53691.1Skamil
53701.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53711.1Skamil	    "without signal to be sent\n");
53721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53731.1Skamil
53741.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53751.1Skamil	    TWAIT_FNAME);
53761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53771.1Skamil
53781.1Skamil	validate_status_exited(status, exitval);
53791.1Skamil
53801.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53811.1Skamil	    TWAIT_FNAME);
53821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53831.1Skamil}
53841.1Skamil
53851.1SkamilATF_TC(resume1);
53861.1SkamilATF_TC_HEAD(resume1, tc)
53871.1Skamil{
53881.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
53891.1Skamil	atf_tc_set_md_var(tc, "descr",
53901.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
53911.1Skamil	    "resumed by the debugger");
53921.1Skamil}
53931.1Skamil
53941.1SkamilATF_TC_BODY(resume1, tc)
53951.1Skamil{
53961.1Skamil	struct msg_fds fds;
53971.1Skamil	const int exitval = 5;
53981.1Skamil	const int sigval = SIGSTOP;
53991.1Skamil	pid_t child, wpid;
54001.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
54011.1Skamil#if defined(TWAIT_HAVE_STATUS)
54021.1Skamil	int status;
54031.1Skamil#endif
54041.1Skamil	ucontext_t uc;
54051.1Skamil	lwpid_t lid;
54061.1Skamil	static const size_t ssize = 16*1024;
54071.1Skamil	void *stack;
54081.1Skamil	struct ptrace_lwpinfo pl;
54091.1Skamil	struct ptrace_siginfo psi;
54101.1Skamil
54111.17Skamil	// Feature pending for refactoring
54121.17Skamil	atf_tc_expect_fail("PR kern/51995");
54131.17Skamil
54141.15Schristos	// Hangs with qemu
54151.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
54161.1Skamil
54171.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
54181.1Skamil
54191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54211.1Skamil	if (child == 0) {
54221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54241.1Skamil
54251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54271.1Skamil
54281.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
54291.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
54301.1Skamil
54311.13Schristos		DPRINTF("Before making context for new lwp in child\n");
54321.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
54331.1Skamil
54341.13Schristos		DPRINTF("Before creating new in child\n");
54351.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54361.1Skamil
54371.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
54381.1Skamil
54391.1Skamil		raise(SIGINT);
54401.1Skamil
54411.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54421.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54431.1Skamil
54441.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54451.1Skamil		    "are the same\n", lid, the_lwp_id);
54461.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54471.1Skamil
54481.13Schristos		DPRINTF("Before exiting of the child process\n");
54491.1Skamil		_exit(exitval);
54501.1Skamil	}
54511.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54521.1Skamil
54531.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54551.1Skamil
54561.1Skamil	validate_status_stopped(status, sigval);
54571.1Skamil
54581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54591.1Skamil	    "without signal to be sent\n");
54601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54611.1Skamil
54621.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54631.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54651.1Skamil
54661.1Skamil	validate_status_stopped(status, SIGTRAP);
54671.1Skamil
54681.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
54691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
54701.1Skamil
54711.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
54721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
54731.1Skamil
54741.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
54751.1Skamil
54761.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54771.1Skamil	    "without signal to be sent\n");
54781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54791.1Skamil
54801.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54811.1Skamil	    "SIGINT\n", TWAIT_FNAME);
54821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54831.1Skamil
54841.1Skamil	validate_status_stopped(status, SIGINT);
54851.1Skamil
54861.1Skamil	pl.pl_lwpid = 0;
54871.1Skamil
54881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54891.1Skamil	while (pl.pl_lwpid != 0) {
54901.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
54911.1Skamil		switch (pl.pl_lwpid) {
54921.1Skamil		case 1:
54931.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
54941.1Skamil			break;
54951.1Skamil		case 2:
54961.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
54971.1Skamil			break;
54981.1Skamil		}
54991.1Skamil	}
55001.1Skamil
55011.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
55021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
55031.1Skamil
55041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55051.1Skamil	    "without signal to be sent\n");
55061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55071.1Skamil
55081.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
55091.1Skamil	    TWAIT_FNAME);
55101.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55111.1Skamil
55121.1Skamil	validate_status_exited(status, exitval);
55131.1Skamil
55141.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
55151.1Skamil	    TWAIT_FNAME);
55161.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55171.1Skamil
55181.1Skamil	msg_close(&fds);
55191.1Skamil
55201.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
55211.1Skamil	sleep(10);
55221.1Skamil}
55231.1Skamil
55241.1SkamilATF_TC(syscall1);
55251.1SkamilATF_TC_HEAD(syscall1, tc)
55261.1Skamil{
55271.1Skamil	atf_tc_set_md_var(tc, "descr",
55281.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
55291.1Skamil}
55301.1Skamil
55311.1SkamilATF_TC_BODY(syscall1, tc)
55321.1Skamil{
55331.1Skamil	const int exitval = 5;
55341.1Skamil	const int sigval = SIGSTOP;
55351.1Skamil	pid_t child, wpid;
55361.1Skamil#if defined(TWAIT_HAVE_STATUS)
55371.1Skamil	int status;
55381.1Skamil#endif
55391.1Skamil	struct ptrace_siginfo info;
55401.1Skamil	memset(&info, 0, sizeof(info));
55411.1Skamil
55421.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55431.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55441.1Skamil	if (child == 0) {
55451.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55461.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55471.1Skamil
55481.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55491.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55501.1Skamil
55511.1Skamil		syscall(SYS_getpid);
55521.1Skamil
55531.13Schristos		DPRINTF("Before exiting of the child process\n");
55541.1Skamil		_exit(exitval);
55551.1Skamil	}
55561.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55571.1Skamil
55581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55601.1Skamil
55611.1Skamil	validate_status_stopped(status, sigval);
55621.1Skamil
55631.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55641.1Skamil	    "without signal to be sent\n");
55651.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55661.1Skamil
55671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55691.1Skamil
55701.1Skamil	validate_status_stopped(status, SIGTRAP);
55711.1Skamil
55721.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55741.1Skamil
55751.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55761.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55771.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55781.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
55791.1Skamil
55801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55811.1Skamil	    "without signal to be sent\n");
55821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
55831.1Skamil
55841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55861.1Skamil
55871.1Skamil	validate_status_stopped(status, SIGTRAP);
55881.1Skamil
55891.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
55901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
55911.1Skamil
55921.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
55931.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
55941.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
55951.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
55961.1Skamil
55971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55981.1Skamil	    "without signal to be sent\n");
55991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56001.1Skamil
56011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56031.1Skamil
56041.1Skamil	validate_status_exited(status, exitval);
56051.1Skamil
56061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56081.1Skamil}
56091.1Skamil
56101.1SkamilATF_TC(syscallemu1);
56111.1SkamilATF_TC_HEAD(syscallemu1, tc)
56121.1Skamil{
56131.1Skamil	atf_tc_set_md_var(tc, "descr",
56141.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
56151.1Skamil}
56161.1Skamil
56171.1SkamilATF_TC_BODY(syscallemu1, tc)
56181.1Skamil{
56191.1Skamil	const int exitval = 5;
56201.1Skamil	const int sigval = SIGSTOP;
56211.1Skamil	pid_t child, wpid;
56221.1Skamil#if defined(TWAIT_HAVE_STATUS)
56231.1Skamil	int status;
56241.1Skamil#endif
56251.1Skamil
56261.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
56271.6Skamil	/* syscallemu does not work on sparc (32-bit) */
56281.6Skamil	atf_tc_expect_fail("PR kern/52166");
56291.6Skamil#endif
56301.6Skamil
56311.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56321.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56331.1Skamil	if (child == 0) {
56341.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56351.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56361.1Skamil
56371.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56381.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56391.1Skamil
56401.1Skamil		syscall(SYS_exit, 100);
56411.1Skamil
56421.13Schristos		DPRINTF("Before exiting of the child process\n");
56431.1Skamil		_exit(exitval);
56441.1Skamil	}
56451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
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, sigval);
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_SYSCALL, 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_stopped(status, SIGTRAP);
56601.1Skamil
56611.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
56621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
56631.1Skamil
56641.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56651.1Skamil	    "without signal to be sent\n");
56661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
56671.1Skamil
56681.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56701.1Skamil
56711.1Skamil	validate_status_stopped(status, SIGTRAP);
56721.1Skamil
56731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56741.1Skamil	    "without signal to be sent\n");
56751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56761.1Skamil
56771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56791.1Skamil
56801.1Skamil	validate_status_exited(status, exitval);
56811.1Skamil
56821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56841.1Skamil}
56851.1Skamil
56861.1Skamil#include "t_ptrace_amd64_wait.h"
56871.1Skamil#include "t_ptrace_i386_wait.h"
56881.1Skamil#include "t_ptrace_x86_wait.h"
56891.1Skamil
56901.1SkamilATF_TP_ADD_TCS(tp)
56911.1Skamil{
56921.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
56931.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
56941.33Skamil
56951.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
56961.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
56971.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
56981.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
56991.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
57001.33Skamil
57011.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_trap);
57021.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_segv);
57031.71Skamil	ATF_TP_ADD_TC(tp, traceme_crash_ill);
57041.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_fpe);
57051.59Skamil	ATF_TP_ADD_TC(tp, traceme_crash_bus);
57061.59Skamil
57071.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1);
57081.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2);
57091.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3);
57101.50Skamil
57111.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1);
57121.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2);
57131.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3);
57141.50Skamil
57151.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1);
57161.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2);
57171.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3);
57181.50Skamil
57191.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1);
57201.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2);
57211.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3);
57221.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4);
57231.50Skamil	ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5);
57241.1Skamil
57251.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
57261.37Skamil
57271.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
57281.46Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise2);
57291.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
57301.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
57311.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
57321.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise6);
57331.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise7);
57341.47Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise8);
57351.40Skamil
57361.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap);
57371.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv);
57381.71Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill);
57391.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe);
57401.52Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus);
57411.41Skamil
57421.43Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_exec);
57431.43Skamil
57441.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap);
57451.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv);
57461.71Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill);
57471.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe);
57481.59Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus);
57491.59Skamil
57501.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent);
57511.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates);
57521.61Skre	ATF_TP_ADD_TC_HAVE_PID(tp,
57531.61Skre		unrelated_tracer_sees_terminaton_before_the_parent);
57541.67Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process);
57551.51Skamil
57561.51Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_child);
57571.66Skamil	ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child);
57581.51Skamil
57591.51Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_parent);
57601.65Skamil	ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent);
57611.51Skamil
57621.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57631.51Skamil		tracee_sees_its_original_parent_getppid);
57641.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57651.51Skamil		tracee_sees_its_original_parent_sysctl_kinfo_proc2);
57661.51Skamil	ATF_TP_ADD_TC_HAVE_PID(tp,
57671.51Skamil		tracee_sees_its_original_parent_procfs_status);
57681.1Skamil
57691.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_empty);
57701.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_fork);
57711.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork);
57721.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done);
57731.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create);
57741.53Skamil	ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit);
57751.1Skamil
57761.31Skamil	ATF_TP_ADD_TC(tp, fork1);
57771.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
57781.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
57791.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
57801.31Skamil	ATF_TP_ADD_TC(tp, fork5);
57811.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
57821.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
57831.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
57841.31Skamil
57851.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
57861.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
57871.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
57881.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
57891.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
57901.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
57911.64Smartin// thes tests hang on SMP machines, disable them for now
57921.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
57931.64Smartin//	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
57941.1Skamil
57951.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8);
57961.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16);
57971.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32);
57981.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64);
57991.54Skamil
58001.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8);
58011.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16);
58021.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32);
58031.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64);
58041.54Skamil
58051.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8);
58061.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16);
58071.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32);
58081.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64);
58091.54Skamil
58101.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8);
58111.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16);
58121.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32);
58131.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64);
58141.54Skamil
58151.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d);
58161.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i);
58171.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d);
58181.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i);
58191.54Skamil
58201.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text);
58211.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text);
58221.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text);
58231.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text);
58241.54Skamil
58251.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text);
58261.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text);
58271.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text);
58281.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text);
58291.54Skamil
58301.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text);
58311.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text);
58321.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text);
58331.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text);
58341.54Skamil
58351.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text);
58361.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text);
58371.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text);
58381.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text);
58391.54Skamil
58401.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text);
58411.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text);
58421.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text);
58431.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text);
58441.1Skamil
58451.54Skamil	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv);
58461.1Skamil
58471.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
58481.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
58491.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
58501.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
58511.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
58521.1Skamil
58531.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
58541.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
58551.1Skamil
58561.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
58571.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
58581.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
58591.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
58601.1Skamil
58611.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
58621.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
58631.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
58641.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
58651.2Skamil
58661.1Skamil	ATF_TP_ADD_TC(tp, kill1);
58671.1Skamil	ATF_TP_ADD_TC(tp, kill2);
58681.1Skamil
58691.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
58701.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
58711.1Skamil
58721.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
58731.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
58741.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
58751.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
58761.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
58771.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
58781.1Skamil
58791.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
58801.1Skamil
58811.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
58821.1Skamil
58831.1Skamil	ATF_TP_ADD_TC(tp, signal1);
58841.1Skamil	ATF_TP_ADD_TC(tp, signal2);
58851.1Skamil	ATF_TP_ADD_TC(tp, signal3);
58861.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
58871.1Skamil	ATF_TP_ADD_TC(tp, signal5);
58881.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
58891.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
58901.1Skamil	ATF_TP_ADD_TC(tp, signal8);
58911.1Skamil	ATF_TP_ADD_TC(tp, signal9);
58921.1Skamil	ATF_TP_ADD_TC(tp, signal10);
58931.1Skamil
58941.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
58951.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
58961.1Skamil
58971.1Skamil	ATF_TP_ADD_TC(tp, resume1);
58981.1Skamil
58991.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
59001.1Skamil
59011.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
59021.1Skamil
59031.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
59041.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
59051.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
59061.1Skamil
59071.1Skamil	return atf_no_error();
59081.1Skamil}
5909